Webview是Android平台中一个重要组件,通常是通过在Activity中嵌套一个简单浏览器,实现在线网页浏览的功能或者实现Android与JavaScript的通信,此时addJavascriptInterface方法就显得尤为重要。但熟悉的人应该会有所发现,在API 17以后,addJavascriptInterface方法就失效了,下面将详细的介绍addJavascriptInterface方法以及失效解决方法。
一、 addJavascriptInterface简介
addJavascriptInterface是WebKit的原生API,属于WebView对象的公共方法,用于暴露一个java对象给js,使得js可以直接调用方法。当然,java与js的相互调用也离不开loadUrl()方法的配合使用。但是addJavascriptInterface的使用也是有些问题,因为Android平台封装WebKit内核时,不同的版本中会有些不一致。
二、网页内容
1. HTML代码
<html>
<head>
<meta charset="gb-2312">
<title>无标题文档</title>
<link href="http://code./mobile/1.0/jquery.mobile-1.0.min.css" rel="stylesheet" type="text/css">
<script src="http://code./jquery-1.6.4.min.js" type="text/javascript"></script>
<script src="http://code./mobile/1.0/jquery.mobile-1.0.min.js" type="text/javascript"></script>
</head>
<body>
<div data-role="page" id="page">
<div data-role="header">
<h1>标题</h1>
</div>
<div data-role="content">
<ul data-role="listview" data-inset="true">
<li data-role="list-divider">
注册
</li>
<li>
<div data-role="fieldcontain">
<label for="username">用户名:</label>
<input type="text" name="textinput" id="username" value="张三" />
</div></li><li>
<div data-role="fieldcontain">
<label for="password">密码:</label>
<input type="password" name="textinput" id="password" value="zhangsan" />
</div></li><li>
<div data-role="fieldcontain">
<fieldset data-role="controlgroup" data-type="horizontal">
<legend>性别:</legend>
<input type="radio" name="radio1" id="man" value="0" />
<label for="man">男</label>
<input type="radio" name="radio1" id="woman" value="1" />
<label for="woman">女</label>
</fieldset>
</div></li><li>
<div data-role="fieldcontain">
<fieldset data-role="controlgroup" data-type="horizontal">
<legend>爱好</legend>
<input type="checkbox" name="checkbox1" id="football" class="custom" value="0" />
<label for="football">足球</label>
<input type="checkbox" name="checkbox1" id="basketball" class="custom" value="1" />
<label for="basketball">篮球</label>
<input type="checkbox" name="checkbox1" id="vollyball" class="custom" value="2" />
<label for="vollyball">排球</label>
</fieldset>
</div>
</li>
<li>
<div data-role="fieldcontain">
<label for="selectmenu" class="select">国籍:</label>
<select name="selectmenu" id="selectmenu">
<option value="China">中国</option>
<option value="America">美国</option>
<option value="Japan">日本</option>
</select>
</div>
</li>
<li>
<button id="commit">提交</button>
</li>
</ul>
</div>
<div data-role="footer" data-position="fixed">
<h4>脚注</h4>
</div>
</div>
</body>
</html>
2.JS代码
<script>
$(function(){
$("#commit").click(function(){
var result = "{";
result +="\"username\":\"";
result +=$("#username").val();
result +="\",\"password\":\"";
result +=$("#password").val();
result += "\",\"gender\":\"";
result += $('input[name="radio1"]:checked').val();
result += "\",\"interest\":\"";
$('input[name="checkbox1"]:checked').each(function() {
result += $(this).val()+",";
});
result += "\",\"country\":\"";
result += $("#selectmenu option:selected").text()+"\"}";
register_js.register(result);
});
});
</script>
3.实现效果图

三、API 17以前addJavascriptInterface的使用方法
1.获取网页
wv = (WebView) this.findViewById(R.id.wv1);
wv.getSettings().setJavaScriptEnabled(true);
wv.loadUrl("file:///android_asset/index.html");
wv.addJavascriptInterface(new JSInterface(), "register_js")
register_js为交互时相互定义的名字。
2.JS中调用方法在Android中响应
public void register(String userInfo){
Toast.makeText(MainActivity.this, userInfo, Toast.LENGTH_LONG).show();
}
register方法为js中调用的方法名,与addJavascriptInterface相对应。具体可参照JavaScript的代码。
四、API 17以后addJavascriptInterface的使用方法
1. 获取网页
wv = (WebView) this.findViewById(R.id.wv1);
wv.getSettings().setJavaScriptEnabled(true);
wv.loadUrl("file:///android_asset/index.html");
wv.addJavascriptInterface(new JSInterface(), "register_js")
2.JS中调用方法在Android中响应
public void register(String userInfo){
Toast.makeText(MainActivity.this, userInfo, Toast.LENGTH_LONG).show();
}
3.注意
需要添加注解,否则addJavascriptInterface方法会失效。
@SuppressLint("JavascriptInterface")
@JavascriptInterface
4.方法更换原因
Android4.2以前WebView 提供了javascript 调用Java代码的方法,会造成很大的安全漏洞。Android官方在API 17后,限制javascript代码只能调用声明了@JavascriptInterface 注解的Java方法。
所以必须要给每个可供js代码调用的Java方法加一个@JavascriptInterface接口。
五、MainActivity.java代码
package com.example.administrator.addjavascriptinterfacefunctiontest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.webkit.JavascriptInterface;
import android.webkit.WebView;
import android.widget.Toast;
public class MainActivity extends Activity {
private WebView wv;
@SuppressLint("JavascriptInterface")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
wv = (WebView) this.findViewById(R.id.wv1);
wv.getSettings().setJavaScriptEnabled(true);
wv.loadUrl("file:///android_asset/index.html");
wv.addJavascriptInterface(new JSInterface(), "register_js");
}
private final class JSInterface{
@SuppressLint("JavascriptInterface")
@JavascriptInterface
public void register(String userInfo){
Toast.makeText(MainActivity.this, userInfo, Toast.LENGTH_LONG).show();
}
}
}
六、源码下载
地址:http://download.csdn.net/download/u012721519/10225784
Good luck!
Write by Jimmy.li