¿Cómo funciona evaluateJavascript?
Estoy tratando de usar el nuevo método evaluateJavascript en Android 4.4, pero todo lo que nunca volver 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?
- Mostrar círculo de actividades antes de cargar la vista web - Android
- WebView con https loadUrl muestra la página en blanco
- Cómo obtener URL de enlace en Android WebView con HitTestResult para una imagen vinculada (y no la URL de imagen) con Longclick
- No se muestra el video web de Android HoneyComb
- WebView no se muestra correctamente
Actualización: Poco más información:
- Tengo el permiso de acceso a Internet
- Tengo
setJavascriptEnabled(true);
- Secuencia apóstrofe probada:
return 'test';
, - Objeto JS probado:
return { test: 'this' }
-
console.log('test');
Se está ejecutando bien. - Establezca
targetSdkVersion
en 19 según: Si su aplicación utiliza WebView
Dispositivos: Tanto Nexus 7 como Nexus 5 (Stock)
- Llamar a funciones javascript en una vista web desde la clase de actividad
- ¿Cómo puedo dejar que el emulador de Android hable con el host local?
- No más Text Reflow después de ampliar KitKat WebView
- OnLongClickListener no funciona en WebView
- Desactivar ventanas emergentes y alarmboxes en la vista web de android
- Cómo cargar URL consecutivamente una por una
- La vista web de Android shouldOverrideUrlLoading no se llama
- Flash no se muestra en WebView para Android 3.0.1
Hay un ejemplo del método evaluateJavascript que se está utilizando en este ejemplo:
https://github.com/GoogleChrome/chromium-webview-samples/tree/master/jsinterface-example
Esencialmente, si el javascript que ejecuta en el WebView devuelve un valor que se pasará en la devolución de llamada.
Lo más importante a destacar es que la cadena devuelta en OnReceiveValue es un valor JSON, un objeto JSON o una matriz JSON dependiendo de lo que devuelva.
Lo que hay que tener en cuenta es que si devuelves un solo valor, debes 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 todavía puede utilizar un analizador para una respuesta de cadena es que se convierte en un valor JSON, lo que significa que será envuelto en comillas.
Por ejemplo si fuiste:
mWebView.evaluateJavascript("(function() { return 'this'; })();", new ValueCallback<String>() { @Override public void onReceiveValue(String s) { Log.d("LogName", s); // Prints: "this" } });
Se imprimirá la cadena de este, envuelto en comillas dobles: "esto".
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 } });
Aceptar, por lo que resulta que el result
aquí es el resultado de la llamada Javascript – como si estuviera ingresando el comando en una consola de Javascript.
Así que para obtener un resultado, tiene que ser 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"} } });
AndroidJSCore es una buena alternativa para evaluar JavaScript que no utiliza un WebView.
Si quieres seguir con WebView y necesitas 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) } });
Para resumir la respuesta de @GauntFace y proporcionar una solución alternativa sin utilizar JSON parser:
Si su función JS devuelve sólo una String
y usted se está preguntando por qué la cadena se mutila en Java, es porque es JSON-escapada.
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 una String
mientras que la función JS puede devolver un null
, un número literal, etc.)
Para obtener el valor de cadena igual que en JS, si estás 100% seguro de que esperas una String
correcta devuelta, necesitarás JSON-unescape, 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 null
adecuado, por lo que obviamente necesita comprobar que como el primer paso.
if ("null".equals(s)) { ... } else { // unescape JSON }
- Buggy ListView me hace triste
- Error de facturación de la aplicación en Android Debes iniciar sesión en tu cuenta de Google