在WebView中不仅可以运行HTML代码,更重要的是,WebView可以与Javascript互相调用。也就是说,在Javascript中可以获取WebView的内容,与此同时,在WebView中也可以调用Javascript里面的方法。
下面通过如下案例来分析WebView与javascript的交互
1.第一步在布局文件中声明WebView(activity_main.xml)
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="${relativePackage}.${activityClass}" >
<WebView
android:id="@+id/webView1"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
2.在项目的assets目录下面存放html文件(user.html)
<!DOCTYPE html>
<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){
//通过eval函数 转化成 josn对象
var jsonobjs = eval(jsondata);
var table = document.getElementById("user");
for(var y=0; y<jsonobjs.length; y++){
var tr = table.insertRow(table.rows.length); //添加一行
//添加三列
var td1 = tr.insertCell(0);
var td2 = tr.insertCell(1);
td2.align = "center";
var td3 = tr.insertCell(2);
//设置列内容和属性
td1.innerHTML = jsonobjs[y].id;
td2.innerHTML = "<a href='javascript:csdn.call("+jsonobjs[y].phone+")'>"+ jsonobjs[y].name + "</a>";
td3.innerHTML = jsonobjs[y].phone;
}
}
//警告框
function alertMsg(){
alert("hello alert");
}
//确认框
function confirmMsg(){
confirm("hello confirm");
}
//提示框
function promptMsg(){
prompt("hello prompt");
}
</script>
</head>
<body onload="javascript:csdn.userList()">
<table border="0" width="100%" id="user">
<tr>
<td width="20%">序号</td><td align="center">姓名</td><td width="20%">电话</td>
</tr>
</table>
<div>
<input type="button" onclick="javascript:alertMsg()" value="弹出警告框"/>
<input type="button" onclick="javascript:confirmMsg()" value="确认框"/>
<input type="button" onclick="javascript:promptMsg()" value="提示框"/>
</div>
</body>
</html>
备注:为了让WebView从apk文件中加载 assets,Android SDK提供了一个schema,前缀为"file:///android_asset/"。WebView遇到这样的schema,就去当前包中的 assets目录中找内容
3.具体代码的实现(详解见代码注释)
public class MainActivity extends Activity {
// 声明控件对象
private WebView webView;
// 声明handler对象
private Handler handler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 获取控件对象
webView = (WebView) findViewById(R.id.webView1);
// 获取webview控件属性对象
WebSettings webSettings = webView.getSettings();
// 支持javascript代码
webSettings.setJavaScriptEnabled(true);
// 添加javascript接口对象
webView.addJavascriptInterface(new JavascriptUser(), "csdn");
// WebChromeClient主要用来辅助WebView处理Javascript的对话框、网站图标、网站标题以及网页加载进度等。
webView.setWebChromeClient(new WebChromeClient() {
//处理确认框
@Override
public boolean onJsConfirm(WebView view, String url,
String message, final JsResult result) {
// 创建builder对象
new AlertDialog.Builder(MainActivity.this)
.setTitle("onJsConfirm").setMessage(message)
.setPositiveButton("确认", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
result.cancel();//如果不取消,按钮只能处理一次,取消后不限制
}
}).show();
return true;
}
//处理提示框
@Override
public boolean onJsPrompt(WebView view, String url, String message,
String defaultValue, final JsPromptResult result) {
// 创建builder对象
new AlertDialog.Builder(MainActivity.this)
.setTitle("onJsPrompt").setMessage(message)
.setPositiveButton("确认", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
result.cancel();
}
}).show();
return true;
}
//处理警告框
@Override
public boolean onJsAlert(WebView view, String url, String message,
final JsResult result) {
/*
* Toast.makeText(MainActivity.this, message, 1).show();
*
* result.confirm(); //确认后,可以处理多次点击,否则按钮只能点击一次
*/
// 创建builder对象
new AlertDialog.Builder(MainActivity.this)
.setTitle("onJsAlert").setMessage(message)
.setPositiveButton("确认", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
result.cancel();
}
}).show();
return true;
}
});
// 加载显示的网页 规定:schema file:///android_asset
webView.loadUrl("file:///android_asset/user.html");
}
class JavascriptUser {
// 打电话 备注:在android17版本之后必须通过 @JavascriptInterface 注解实现,否则会出现bug(详见异常)
//这个方法是在网页中调用的:<a href='javascript:csdn.call("+jsonobjs[y].phone+")'>"+ jsonobjs[y].name + "</a>
@JavascriptInterface
public void call(final String phone) {
//处理的操作要在hanlder中处理
handler.post(new Runnable() {
@Override
public void run() {
//这里要实现打电话的操作,必须添加打电话的权限 <uses-permission android:name="android.permission.CALL_PHONE"/>
startActivity(new Intent(Intent.ACTION_CALL, Uri
.parse("tel:" + phone)));
}
});
}
//加载所有的数据 备注:在android 17版本之后必须通过 @JavascriptInterface 注解实现,
//否则会出现"Uncaught TypeError: Object [object Object] has no method 'userList'",
//source: file:///android_asset/user.html (31)
//这个方法是在网页中调用的onload="javascript:csdn.userList()"
@JavascriptInterface
public void userList() {
handler.post(new Runnable() {
@Override
public void run() {
try {
// 创建json对象
JSONObject jsonObject = new JSONObject();
jsonObject.put("id", 1);
jsonObject.put("name", "chenhj");
jsonObject.put("phone", "110");
// 创建json对象
JSONObject jsonObject2 = new JSONObject();
jsonObject2.put("id", 2);
jsonObject2.put("name", "wangsan");
jsonObject2.put("phone", "112");
// 创建json数组
JSONArray jsonArray = new JSONArray();
jsonArray.put(jsonObject);
jsonArray.put(jsonObject2);
// 把json数组转换成字符串
String jsonstr = jsonArray.toString();
// TODO Auto-generated method stub
// 调用网页中的javascript中的show函数
webView.loadUrl("javascript:show('" + jsonstr + "')");
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
}
}
4.运行效果图说明:
4.1当成功部署,启动后的界面如下(备注:网页中调用的onload="javascript:csdn.userList()" 与java代码中调用了webView.loadUrl("javascript:show('" + jsonstr + "')");
4.2当点击用户名比如chj时 会进入到拨号界面;说明成功调用了java中的call方法
4.3当点击弹出警告框 按钮时 会出现如下界面;说明成功调用了WebChromeClient子类中重写的onJsAlert
4.4当点击 确认框 按钮时 会出现如下界面;说明成功调用了WebChromeClient子类中重写的onJsConfirm
4.5当点击提示框 按钮 会出现如下界面;说明成功调用了WebChromeClient子类中重写的onJsPrompt
备注:关于WebChromeClient常用方法:
onCloseWindow 关闭WebView
onCreateWindow 创建WebView
onJsAlert 处理Javascript中的Alert对话框
onJsConfirm处理Javascript中的Confirm对话框
onJsPrompt处理Javascript中的Prompt对话框
onProgressChanged 加载进度条改变
onReceivedlcon 网页图标更改
onReceivedTitle 网页Title更改
onRequestFocus WebView显示焦点