J'essaie d'utiliser la nouvelle méthode assessmentJavascript dans Android 4.4, mais tout ce que je reçois est un résultat nul:
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
}
});
Comment puis-je retourner un résultat à cette méthode?
Mise à jour: Un peu plus d'infos:
setJavascriptEnabled(true);
return 'test';
,return { test: 'this' }
console.log('test');
est bien exécuté.targetSdkVersion
sur 19 selon: Si votre application utilise WebViewAppareils: Nexus 7 et Nexus 5 (Stock)
Voici un exemple de la méthode assessmentJavascript utilisée dans cet exemple:
https://github.com/GoogleChrome/chromium-webview-samples/tree/master/jsinterface-example
Essentiellement, si le javascript que vous exécutez dans WebView renvoie une valeur, il sera transmis dans le rappel.
La principale chose à noter est que la chaîne renvoyée dans OnReceiveValue est une valeur JSON, un objet JSON ou un tableau JSON, en fonction de ce que vous retournez.
Ce qu'il faut noter à ce sujet, c'est que si vous renvoyez une valeur unique, vous devez utiliser setLenient (true) sur un lecteur JSON pour que cela fonctionne.
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
}
}
}
});
}
Si vous souhaitez toujours utiliser un analyseur syntaxique pour une réponse de chaîne, c'est parce qu'il est converti en une valeur JSON, ce qui signifie qu'il sera entouré de guillemets.
Par exemple si vous êtes allé:
mWebView.evaluateJavascript("(function() { return 'this'; })();", new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
Log.d("LogName", s); // Prints: "this"
}
});
Cela afficherait la chaîne this, entourée de guillemets: "this".
Autres exemples à noter:
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)
}
});
OK, il s’avère que la result
est le résultat de l’appel Javascript - comme si l’on introduisait la commande dans une console Javascript.
Donc, pour obtenir un résultat, il doit être encapsulé dans une fonction:
webView1.evaluateJavascript("(function() { return \"this\"; })();", new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
Log.d("LogName", s); // Prints 'this'
}
});
Cela fonctionnera également:
webView1.evaluateJavascript("window.variable = \"asd\";", new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
Log.d("LogName", s); // Prints asd
}
});
La méthode gère également les objets 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 est une bonne alternative pour évaluer JavaScript qui n'utilise pas WebView.
Si vous souhaitez vous en tenir à WebView et que vous avez besoin d'évaluer JavaScript dans les versions précédentes d'Android (4+), voici une petite bibliothèque:
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)
}
});
Pour résumer la réponse de @GauntFace et fournir une solution alternative sans utiliser l’analyseur JSON:
Si votre fonction JS retourne juste une String
et que vous vous demandez pourquoi la chaîne est mutilée en Java, c'est parce qu'elle est échappée en JSON.
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"
}
});
(notez que onReceiveValue
fournit toujours une String
alors que la fonction JS peut renvoyer une null
, un nombre littéral, etc.)
Pour obtenir la même valeur de chaîne que dans JS, si vous êtes absolument sûr que vous attendez un String
correct renvoyé, vous devez le supprimer par JSON, par exemple, comme ceci:
String unescaped = s.substring(1, s.length() - 1) // remove wrapping quotes
.replace("\\\\", "\\") // unescape \\ -> \
.replace("\\\"", "\""); // unescape \" -> "
Cependant, notez que s
peut être une chaîne "null"
si JS renvoie null
correct. Vous devez donc évidemment vérifier cela dès la première étape.
if ("null".equals(s)) {
...
} else {
// unescape JSON
}
La réponse de tout le monde est géniale. Je viens d'ajouter un autre point. Ne mettez pas evaluationJavascript dans la méthode avec l'annotation @JavascripInterface comme ceci
@JavascripInterface
public void onData(){
mWebView.evaluateJavascript("javascript:executeNext()",null);
}
Parce que cela bloquera le fil JavaBridge . Si vous voulez y placerJavaScript. Faites-le avec cette voie
@JavascripInterface
public void onData(){
mWebView.post(new Runnable() {
@Override
public void run() {
mWebView.evaluateJavascript("javascript:executeNext()",null);
}
});
}