¿Cómo funciona evaluateJavascript?
Estoy tratando de usar el nuevo método evaluateJavascript en Android 4.4, pero todo lo que obtengo es un resultado nulo:
webView1.evaluateJavascript("return \"test\";", new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
Log.d("LogName", s); // Log is written, but s is always null
}
});
¿Cómo devuelvo un resultado a este método?
Actualización: Poco más información:
- Tengo el permiso de INTERNET establecido
- Tengo
setJavascriptEnabled(true);
- Cadena de apóstrofo probada:
return 'test';
, - Objeto JS probado:
return { test: 'this' }
-
console.log('test');
está siendo ejecutado multa. - Establecer
targetSdkVersion
a 19 según: Si tu app usa WebView
Dispositivos: Ambos Nexus 7 y Nexus 5 (Stock)
4 answers
Hay un ejemplo del método evaluateJavascript que se utiliza en esta muestra:
Https://github.com/GoogleChrome/chromium-webview-samples/tree/master/jsinterface-example
Esencialmente si el javascript que ejecuta en la WebView devuelve un valor, se pasará en la devolución de llamada.
Lo principal a tener en cuenta es que la cadena devuelta en OnReceiveValue es un Valor JSON, un objeto JSON o una matriz JSON dependiendo de lo que devuelva.
Cosas para tenga en cuenta que si devuelve un solo valor, debe usar setLenient(true) en un lector JSON para que funcione.
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
}
}
}
});
}
La razón por la que aún puede querer usar un analizador para una respuesta de cadena es que se convierte a un valor JSON, lo que significa que estará envuelto entre comillas.
Por ejemplo, si usted fue:
mWebView.evaluateJavascript("(function() { return 'this'; })();", new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
Log.d("LogName", s); // Prints: "this"
}
});
Imprimiría la cadena this, envuelta entre comillas dobles: "this".
Otros ejemplos dignos de mención:
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)
}
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-22 15:54:47
OK, entonces resulta que el result
aquí está el resultado de la llamada a Javascript - como si uno estuviera ingresando el comando en una consola Javascript.
Así que para obtener un resultado, necesita estar envuelto en una función:
webView1.evaluateJavascript("(function() { return \"this\"; })();", new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
Log.d("LogName", s); // Prints 'this'
}
});
Esto también funcionará:
webView1.evaluateJavascript("window.variable = \"asd\";", new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
Log.d("LogName", s); // Prints asd
}
});
El método también maneja objetos Javascript:
webView1.evaluateJavascript("(function() { return { var1: \"variable1\", var2: \"variable2\" }; })();", new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
Log.d("LogName", s); // Prints: {"var1":"variable1","var2":"variable2"}
}
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-05 14:06:43
AndroidJSCore es una buena alternativa para evaluar JavaScript que no utiliza una vista WEB.
Si desea seguir con WebView y necesita evaluar JavaScript en versiones anteriores de Android (4+), aquí hay una pequeña biblioteca:
Https://github.com/evgenyneu/js-evaluator-for-android
jsEvaluator.evaluate("put your JavaScript code", new JsCallback() {
@Override
public void onResult(final String result) {
// get result here (optional)
}
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-06 01:13:20
Para resumir la respuesta de @GauntFace y proporcionar una solución alternativa sin usar el analizador JSON:
Si su función JS devuelve solo un String
y se pregunta por qué la cadena está destrozada en Java, es porque es JSON-escaped.
mWebView.evaluateJavascript("(function() { return 'Earvin \"Magic\" Johnson'; })();", new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
Log.d("LogName", s);
// expected: s == Earvin "Magic" Johnson
// actual: s == "Earvin \"Magic\" Johnson"
}
});
(tenga en cuenta que onReceiveValue
siempre proporciona un String
mientras que la función JS puede devolver un null
, un número literal, etc.)
Para obtener el valor de la cadena igual que en JS, si está 100% seguro de que está esperando un String
devuelto, usted necesitaría JSON-unescape él, por ejemplo así:
String unescaped = s.substring(1, s.length() - 1) // remove wrapping quotes
.replace("\\\\", "\\") // unescape \\ -> \
.replace("\\\"", "\""); // unescape \" -> "
Sin Embargo, tenga en cuenta que s
puede ser una cadena "null"
si JS devuelve adecuado null
, por lo que, obviamente, necesita comprobar que, como primer paso.
if ("null".equals(s)) {
...
} else {
// unescape JSON
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-06 13:13:19