How to return value from webView.evaluateJavascript callback?

So, I have a class called JavascriptBridge that I use to communicate between Java and Javascript.

To send commands to javascript, I just use this:

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

My problem is that I will also need a function that returns a response from Javascript. I am trying to use webView.evaluateJavascript , but it misses the callback since the Javascript evaluation is being done in 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" } 

Method call:

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

I also tried using @JavascriptInterface , but it gives the same result.

+6
source share
2 answers

It is not possible to evaluate Javascript synchronously on Android (i.e. on the current thread), so it is best to use evaluateJavascript and 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 is no method for evaluating Javascript in the current thread, as Javascript operations may take some time (the JS engine takes time to reverse), and this may block the current thread.

+4
source

I wrote a small piece of code 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) } } } 

PS I did not test the functions and I can not guarantee that they work, but I do not have time, and they will test them and rewrite them in Java when I have time, possibly for a maximum of 5 hours.

0
source

All Articles