How does evaluateJavascript work?
There is an example of the evaluateJavascript method being used in this sample:
https://github.com/GoogleChrome/chromium-webview-samples/tree/master/jsinterface-example
Essentially if the javascript you execute in the WebView returns a value it'll be passed in the callback.
The main thing to note is that the String returned in OnReceiveValue is either a JSON Value, JSON Object or JSON Array depending on what you return.
Things to note about this is if you return a single value, you need to use setLenient(true) on a JSON reader for it to work.
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
// In KitKat+ you should use the evaluateJavascript method
mWebView.evaluateJavascript(javascript, new ValueCallback<String>() {
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
public void onReceiveValue(String s) {
JsonReader reader = new JsonReader(new StringReader(s));
// Must set lenient to parse single values
reader.setLenient(true);
try {
if(reader.peek() != JsonToken.NULL) {
if(reader.peek() == JsonToken.STRING) {
String msg = reader.nextString();
if(msg != null) {
Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_LONG).show();
}
}
}
} catch (IOException e) {
Log.e("TAG", "MainActivity: IOException", e);
} finally {
try {
reader.close();
} catch (IOException e) {
// NOOP
}
}
}
});
}
The reason you may still want to use a parser for a string response is it is converted to a JSON value which means it will be wrapped in quotes.
For example if you went:
mWebView.evaluateJavascript("(function() { return 'this'; })();", new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
Log.d("LogName", s); // Prints: "this"
}
});
It would print the string this, wrapped in double quotes: "this".
Other examples worth noting:
mWebView.evaluateJavascript("(function() { return null; })();", new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
Log.d("LogName", s); // Prints the string 'null' NOT Java null
}
});
mWebView.evaluateJavascript("(function() { })();", new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
Log.d("LogName", s); //s is Java null
}
});
mWebView.evaluateJavascript("(function() { return ''; })();", new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
Log.d("LogName", s); // Prints "" (Two double quotes)
}
});
Android Webview EvaluateJavascript sometimes does not return a response
I did eventually figure out what happened here.
The shorter version is, this can happen when you have a memory leak and an object that is utilizing a semi-destroyed webview will fire off commands, but the newly-initialized webview will not receive a response because it is going to a dead listener.
If you want to prevent this from occurring, just make sure that all objects that maintain an application Context
are properly disposed of or correctly reset if the activity restarts, else you have all objects that use the same Application-level context, but are using new views and callbacks entirely.
Android webview blocking evaluateJavascript
Since the call onReceiveValue
won't be synchronous and would involve blocking your main Thread in case you want to make it synchronous, I would recommend you to avoid doing it. Instead of trying to implement it as synchronous call, implement callbacks and let it continue as asynchronous.
You can achieve it as follows:
private void getFirstUser(final ValueCallback<String> valueCallback){
String evS = "document.getElementsByClassName(\"hm-user\")[0].innerHTML";
final StringBuilder sb = new StringBuilder();
try{
evaluateJavascript(evS, valueCallback);
}catch (Exception e){
valueCallback.onReceiveValue(null);// You can pass any value instead of null.
};
}
While calling method simply do:
getFirstUser(new ValueCallback<String>() {
@Override
public void onReceiveValue(String value) {
if(value != null && value.length() != 0 && !value.equals("null")){
//do something with proper value
}else{
// take necessary action if value is null
}
}
});
Related Topics
Android: Why Is There No Maxheight for a View
How to Add the Aidl File to Android Studio (From the In-App Billing Example)
Android Studio: Cannot Recover Key
Android Studio 3.0 Execution Failed for Task: Unable to Merge Dex
How to Use a Tablayout with Toolbar Inside Collapsingtoolbarlayout
Example: Android Bi-Directional Network Socket Using Asynctask
Overlay Images Onto Camera Preview Surfaceview
Scroll Webview Horizontally Inside a Viewpager
Custom Seekbar (Thumb Size, Color and Background)
Jar Mismatch! Fix Your Dependencies
Android Permissions: Phone Calls: Read Phone State and Identity
Sending Intent to Broadcastreceiver from Adb
How to Exit When Back Button Is Pressed
How to Log Request and Response Body with Retrofit-Android
Generate Signed APK Android Studio