So I have a class named JavascriptBridge that I use to communicate between Java and Javascript.
To send commands to javascript, I simply use this:
public void sendDataToJs(String command) { webView.loadUrl("javascript:(function() { " + command + "})()"); }
My problem is that I would also need a function that return a response from the Javascript. I try using webView.evaluateJavascript, but it skip the callback, as evaluateJavascript is done on another thread.
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" }
The call to the method:
String result = getDataFromJs("test", webView); // Should return "test" from the webView
I've also tried using a @JavascriptInterface, but it gives the same result.
2 Answers
Answers 1
There isn't a way to evaluate Javascript synchronously on Android (i.e. on the current thread) so your best bet is to use evaluateJavascript
then wait for the callback:
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. }
There isn't a method to evaluate Javascript on the current thread, as Javascript operations can take a while (the JS engine needs time to spin up) and this can block the current thread.
Answers 2
I have written a small code snippet in Kotlin that could help you. I wrote this using RxKotlin but if you use Java you can use RxJava2 since they are the same.
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. I haven't tested the functions and cannot guarantee that they work but I don't have time and will test them and rewrite them in Java when I have time, probably in a 5 hours max.
0 comments:
Post a Comment