新しい evaluateJavascript メソッドをAndroid 4.4で使用しようとしていますが、返されるのはnullの結果だけです:
_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
}
});
_
このメソッドに結果を返すにはどうすればよいですか?
更新:もう少し情報:
setJavascriptEnabled(true);
を持っていますreturn 'test';
_、return { test: 'this' }
_console.log('test');
は正常に実行されています。targetSdkVersion
を次のように19に設定します。 アプリでWebView を使用する場合デバイス:Nexus 7とNexus 5の両方(ストック)
このサンプルで使用されているevaluateJavascriptメソッドの例があります。
https://github.com/GoogleChrome/chromium-webview-samples/tree/master/jsinterface-example
基本的に、WebViewで実行するJavaScriptが値を返す場合、コールバックで渡されます。
主な注意点は、OnReceiveValueで返される文字列は、返される内容に応じてJSON値、JSONオブジェクト、またはJSON配列のいずれかであるということです。
これについて注意すべきことは、単一の値を返す場合、JSONリーダーでsetLenient(true)を使用して動作させる必要があるということです。
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
}
}
}
});
}
文字列応答にパーサーを引き続き使用する理由は、引用符でラップされることを意味するJSON値に変換されるためです。
たとえば、行った場合:
mWebView.evaluateJavascript("(function() { return 'this'; })();", new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
Log.d("LogName", s); // Prints: "this"
}
});
二重引用符で囲まれた文字列thisを出力します: "this"。
注目に値する他の例:
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)
}
});
わかりました。したがって、ここでresult
はJavascript呼び出しの結果-Javascriptコンソールにコマンドを入力しているかのようになります。
したがって、結果を取得するには、関数でラップする必要があります。
webView1.evaluateJavascript("(function() { return \"this\"; })();", new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
Log.d("LogName", s); // Prints 'this'
}
});
これも機能します:
webView1.evaluateJavascript("window.variable = \"asd\";", new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
Log.d("LogName", s); // Prints asd
}
});
メソッドは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 は、WebViewを使用しないJavaScriptを評価するための優れた代替手段です。
WebViewを使い続け、以前のバージョンのAndroid(4+)でJavaScriptを評価する必要がある場合、ここに小さなライブラリがあります。
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)
}
});
@GauntFaceの答えを要約し、JSONパーサーを使用せずに代替ソリューションを提供するには:
JS関数がString
のみを返し、Javaで文字列がマングルされている理由がわからない場合は、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"
}
});
(onReceiveValue
は常にString
を提供しますが、JS関数はnull
、Numberリテラルなどを返す場合があります。)
JSと同じ文字列値を取得するには、適切なString
が返されることを100%確信している場合、次のようにJSONエスケープを解除する必要があります。
String unescaped = s.substring(1, s.length() - 1) // remove wrapping quotes
.replace("\\\\", "\\") // unescape \\ -> \
.replace("\\\"", "\""); // unescape \" -> "
ただし、s
は文字列"null"
JSが適切なnull
を返す場合、明らかに最初のステップとしてそれを確認する必要があります。
if ("null".equals(s)) {
...
} else {
// unescape JSON
}
みんなの答えは素晴らしいです。もう1つだけポイントを追加します。この方法のように@JavascripInterfaceアノテーションを持つメソッド内にevaluateJavascriptを配置しないでください
@JavascripInterface
public void onData(){
mWebView.evaluateJavascript("javascript:executeNext()",null);
}
JavaBridgeスレッドをブロックするためです。 evaluateJavascriptを内部に配置する場合。このようにしてください
@JavascripInterface
public void onData(){
mWebView.post(new Runnable() {
@Override
public void run() {
mWebView.evaluateJavascript("javascript:executeNext()",null);
}
});
}