evaluateJavascript 是如何工作的?
Posted
技术标签:
【中文标题】evaluateJavascript 是如何工作的?【英文标题】:How does evaluateJavascript work? 【发布时间】:2013-11-16 06:51:47 【问题描述】:我正在尝试在 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
);
如何将结果返回给该方法?
更新:更多信息:
-
我设置了 INTERNET 权限
我有
setJavascriptEnabled(true);
尝试过的撇号字符串:return 'test';
,
尝试过的 JS 对象:return test: 'this'
console.log('test');
执行良好。
将targetSdkVersion
设置为 19,如下所示:If your app uses WebView
设备: Nexus 7 和 Nexus 5(库存)
【问题讨论】:
你试过去掉javascript中的return关键字吗?所以:webView1.evaluateJavascript("\"test\"", new ValueCallback<String>() /*callback code here*/ );
我已经阅读了WebView 文档,并试图了解evaluateJavascript
函数的实际用例?
【参考方案1】:
本示例中使用了 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)
);
【讨论】:
@TargetApi(Build.VERSION_CODES.HONEYCOMB)在evaluateJavascript里面有什么用? 它涵盖了使用 Honeycomb 中引入的 JSONReader 类的编译器警告 我们如何评估 KITKAT 之前的 JavaScript?当您检查 API 时 - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) @KaluKhanLuhar 你可以使用webview.loadurl("javascript:(function () document.body.background='red';);");
+1 用于说明 onReceiveValue
返回例如JSON 值。花了很多时间试图弄清楚为什么在 html 元素上调用 innerHTML
会返回 qoutes 中的内容【参考方案2】:
好的,原来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"
);
【讨论】:
【参考方案3】: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)
);
【讨论】:
当我在 onPageFinished(WebView view, String url) 方法中使用它与 webview.evaluareJavaScript() 非常相似时,我没有得到与 evaluareJavaScript() 方法相同的 html 【参考方案4】:总结@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
、数字字面量等)
要获得与 JS 中相同的字符串值,如果您 100% 确定您期望返回正确的 String
,则需要对其进行 JSON 转义,例如:
String unescaped = s.substring(1, s.length() - 1) // remove wrapping quotes
.replace("\\\\", "\\") // unescape \\ -> \
.replace("\\\"", "\""); // unescape \" -> "
但是,请注意,如果 JS 返回正确的 null
,s
可能是一个字符串 "null"
,因此您显然需要在第一步进行检查。
if ("null".equals(s))
...
else
// unescape JSON
【讨论】:
【参考方案5】:每个人的回答都很棒。我只是再补充一点。不要像这样将evaluateJavascript放在带有@JavascripInterface注解的方法中
@JavascriptInterface //this is the right annotation
public void onData()
mWebView.evaluateJavascript("javascript:executeNext()",null);
因为它会阻塞 JavaBridge 线程。 如果你想把evaluateJavascript放在里面。用这种方法做
@JavascriptInterface
public void onData()
mWebView.post(new Runnable()
@Override
public void run()
mWebView.evaluateJavascript("javascript:executeNext()",null);
);
【讨论】:
我已经阅读了WebView 文档,并试图了解evaluateJavascript
函数的实际用例?
@AdamHurwitz 例如,向 webview 注入一些脚本以与网站显示进行交互【参考方案6】:
重要提示:
在调用 evaluateJavascript
之前,您必须为您的 WebView 启用 JavaScript。否则你不会得到任何结果。
WebSettings settings = yourWebview.getSettings();
settings.setJavaScriptEnabled(true);
【讨论】:
以上是关于evaluateJavascript 是如何工作的?的主要内容,如果未能解决你的问题,请参考以下文章
WKWebview evaluateJavascript 不工作,抛出错误
WKWebView goBack(_:) evaluateJavaScript 如果返回超过 2 个历史记录失败
如何使用evaluateJavaScript 将数据从WKWebview 发送到HTML 文件| iOS | Objective-C