如何从webView.evaluateJavascript回调中返回值?

时间:2016-09-05 01:32:08

标签: javascript java android callback

所以我有一个名为 JavascriptBridge 的类,用于在Java和Javascript之间进行通信。

要向javascript发送命令,我只需使用:

public void sendDataToJs(String command) {
    webView.loadUrl("javascript:(function() { " + command + "})()");
}

我的问题是我还需要一个从Javascript返回响应的函数。我尝试使用 webView.evaluateJavascript ,但它会跳过回调,因为evaluateJavascript是在另一个线程上完成的。

public String getDataFromJs(String command, WebView webView) {
    String data = null;

    webView.evaluateJavascript("(function() { return " + command + "; })();", new ValueCallback<String>() {
        @Override
        public void onReceiveValue(String s) {
            Log.d("LogName", s); // Print "test"
            // data = s; // The value that I would like to return
        }
    });

    return data; // Return null, not "test"
}

对方法的调用:

String result = getDataFromJs("test", webView); // Should return "test" from the webView

我也尝试过使用 @JavascriptInterface ,但结果相同。

2 个答案:

答案 0 :(得分:6)

没有办法在Android上同步评估Javascript(即在当前线程上),所以最好的办法是使用evaluateJavascript然后等待回调:

public void getDataFromJs(String command, WebView webView) {
    webView.evaluateJavascript("(function() { return " + command + "; })();", new ValueCallback<String>() {
        @Override
        public void onReceiveValue(String s) {
            returnDataFromJs(s);
        }
    });
}

public returnDataFromJs(String data) {
    // Do something with the result.
}

没有一种方法可以在当前线程上评估Javascript,因为Javascript操作可能需要一段时间(JS引擎需要时间来启动),这可以阻止当前线程。

答案 1 :(得分:0)

我在Kotlin写了一个可以帮助你的小代码片段。我使用RxKotlin编写了这个,但如果你使用Java,你可以使用RxJava2,因为它们是相同的。

fun getDataFromJsSync(command: String, webView: WebView): String {
    return getDataFromJs(command, webView).blockingGet()
}

fun getDataFromJs(command: String, webView: WebView): Single<String> {
    return Single.create { emitter: SingleEmitter<String> ->
        try {
            webView.evaluateJavascript(
                    "(function() { return $command; })();",
                    { result -> emitter.onSuccess(result) }
            )
        } catch (e: Exception) {
            emitter.onError(e)
        }
    }
}

P.S。我没有测试过这些功能,也无法保证它们能够正常运行,但是我没有时间进行测试,并且在有空的时候用Java重写它们,最多可能需要5个小时。