评估JavaScript如何工作?

我试图在Android 4.4中使用新的evaluateJavascript方法,但是我得到的所有结果都是空的:

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 } }); 

如何将结果返回给此方法?

更新:一点点更多信息:

  1. 我有INTERNET权限设置
  2. 我有setJavascriptEnabled(true);
  3. 试图撇号string: return 'test';
  4. 试过JS对象: return { test: 'this' }
  5. console.log('test'); 正在执行罚款。
  6. targetSdkVersion设置为19: 如果您的应用程序使用WebView

设备: Nexus 7和Nexus 5(股票)

本示例中使用了evaluateJavascript方法的示例:

https://github.com/GoogleChrome/chromium-webview-samples/tree/master/jsinterface-example

本质上,如果您在WebView中执行的JavaScript返回一个值,它将在callback中传递。

主要要注意的是,OnReceiveValue中返回的string是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 } } } }); } 

您可能仍然希望使用parsing器来处理string响应的原因是将其转换为JSON值,这意味着它将被用引号括起来。

例如,如果你去了:

 mWebView.evaluateJavascript("(function() { return 'this'; })();", new ValueCallback<String>() { @Override public void onReceiveValue(String s) { Log.d("LogName", s); // Prints: "this" } }); 

它会打印出这个string,用双引号括起来:“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) } }); 

好的,所以原来这里的结果是Javascript调用结果 – 就好像有人将命令input到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的好select。

如果你想坚持使用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的答案,并提供不使用JSONparsing器的替代解决scheme:

如果你的JS函数只返回一个String ,你想知道为什么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 ,一个数字文字等)

为了得到与JS相同的string值,如果你100%肯定你期望返回一个正确的String ,你需要JSON-unescape它,例如:

 String unescaped = s.substring(1, s.length() - 1) // remove wrapping quotes .replace("\\\\", "\\") // unescape \\ -> \ .replace("\\\"", "\""); // unescape \" -> " 

但是,请注意,如果JS返回正确的null ,那么s可能是一个string"null" ,所以你显然需要检查这是第一步。

 if ("null".equals(s)) { ... } else { // unescape JSON }