11-06 18:29:15.582: W/WebView(27807): java.lang.Throwable: A WebView method was called on thread 'JavaBridge'. All WebView methods must be called on the same thread. (Expected Looper Looper (main, tid 1) {425f48a8} called on Looper (JavaBridge, tid 92104) {426508d0}, FYI main Looper is Looper (main, tid 1) {425f48a8})
今天群里的一个朋友进来问到此问题,我提示他:异常信息提示很明确,所有的webview的方法比调用必须在一个线程,2个方法调用tid明显不同嘛。
我们先看他写得代码:
package com.webview;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.webkit.JavascriptInterface;
import android.webkit.WebView;
public class MainActivity extends Activity {
private Handler handler= new Handler();
private WebView webView;
@SuppressLint("NewApi")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView = (WebView) findViewById(R.id.webView); // 根据ID找到WebView
webView.getSettings().setJavaScriptEnabled(true); // 允许JS
webView.loadUrl("file:///android_asset/index.html"); // 加载页面
webView.addJavascriptInterface(new Contact(), "contact"); // 创建Contact对象, 传给WebView, 作为JS对象
}
class Contact {
@JavascriptInterface
public void showContacts() {
/* handler.post(new Runnable(){
@Override
public void run(){
String json = "[{name:\"王小二\", amount:\"12345\", phone:\"18600012345\"}, {name:\"黎明\", amount:\"54321\", phone:\"18600054321\"}]";
webView.loadUrl("javascript:show('" + json + "')"); // 调用JS方法// 把js数据,传递给html页面
}
});*/
String json = "[{name:\"王小二\", amount:\"12345\", phone:\"18600012345\"}, {name:\"黎明\", amount:\"54321\", phone:\"18600054321\"}]";
webView.loadUrl("javascript:show('" + json + "')"); // 调用JS方法// 把js数据,传递给html页面
}
@JavascriptInterface
public void call(final String phone) {
/* handler.post(new Runnable() {
@Override
public void run(){
startActivity(new Intent(Intent.ACTION_CALL, Uri.parse("tel://" + phone)));
}
});*/
startActivity(new Intent(Intent.ACTION_CALL, Uri.parse("tel://" + phone)));
}
}
}
上面代码其实在android4.4以下版本也不会出什么问题,以前我也这么写过,但是 Android 4.1,API 17,也就是JELLY_BEAN 开始,android就针对webview中执行js代码和原生代码之间交互做了一些改动,具体改动什么我也没有去研究,只是把依照异常信息给出解决方法而已;
上述代码,只要把js调用的方法 call()和 showContacts()都放在同一个handler.post线程执行就没有问题了。
此外,只有被JavascriptInterface 注解标识的公有方法可以被JS代码访问,大家一定记住这一点
@JavascriptInterface
public void showContacts() {
如果在android4.1以上版本,你提供给js调用的方法,没有标示注解,这个方法是无法被webview里的javascript访问到的,很多人也问到这个问题了。
看看最终执行效果:
assets目录下的index.html代码:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript">
function show(jsondata) {
var jsonobjs = eval(jsondata); // 生成json数组
var table = document.getElementById("personTable");
for ( var y = 0; y < jsonobjs.length; y++) { // 遍历json数组
var tr = table.insertRow(table.rows.length); // 每个对象创建1个TR
var td1 = tr.insertCell(0); // 创建3个TD
var td2 = tr.insertCell(1);
var td3 = tr.insertCell(2);
td1.innerHTML = jsonobjs[y].name; // 设置TD的内容为json对象的name属性
td2.innerHTML = jsonobjs[y].amount;
td3.innerHTML = "<a href='javascript:contact.call(\"" + jsonobjs[y].phone + "\")'>" + jsonobjs[y].phone + "</a>"; // 点击超链接时执行Java方法
}
}
</script>
</head>
<body onLoad="javascript:contact.showContacts()">
<table width="100%" id="personTable">
<tr>
<td width="30%">姓名</td>
<td width="30%" align="center">存款</td>
<td align="center">电话</td>
</tr>
</table>
</body>
</html>
源代码下载:(有人需要我就上传)
- 欢迎加入优快云技术群:221057495 交流