前段时间,阿里的去啊App 5.1.1发布了,这轮发布的热点就是Hybrid混合框架搞定了H5的“无缝秒出”。伴随着H5的发展,Native+HTML5的混合开发模式已经成 为一种潮流,著名的框架比如FaceBook的React Native,AngularJS,最近微信发布的应用号也是为混合开发填了一把火。我最近研究了一下关于Native和HTML混合开发的一些基础知 识,特发文于一文,与大家分享一下成果。
首先是在布局文件建WebView,并在Activity中获取实例,不赘述。以下为MainActivity代码:
public class MainActivity extends Activity {
private WebView webView;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//加载页面
webView = (WebView) findViewById(R.id.webview);
//允许JavaScript执行
webView.getSettings().setJavaScriptEnabled(true);
// 添加一个对象, 让JS可以访问该对象的方法, 该对象中可以调用JS中的方法
webView.addJavascriptInterface(new Contact(this, webView), "contact");
webView.getSettings().setDomStorageEnabled(true);// H5页面,开启Dom缓存
webView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
//从网络加载HTML
webView.loadUrl("http://192.168.4.252:8080/JS_NativeDemo/index.html");
//加载本地HTML
// webView.loadUrl("file:///android_asset/index.html");
}
}
这段代码的作用主要是为webView对象允许JavaScript的执行,并将自己的脚本对象传递给webView,contact对象的具体作用可查看index.html源码中的调用过程。
注意此处是使用web的html界面,需要添加网络请求的相关权限:
<uses-permission
android
:name=
"android.permission.INTERNET"
/>
Contact对象的代码如下:
public class Contact {
private Activity activity;
private WebView webView;
public Contact(Activity activity, WebView webView) {
this.activity = activity;
this.webView = webView;
}
//JavaScript调用此方法拨打电话
@JavascriptInterface
public void call(String phone) {
// startActivity(new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + phone)));
Toast.makeText(activity, phone, Toast.LENGTH_LONG).show();
}
//Html调用此方法传递数据
@JavascriptInterface
public void showcontacts() {
handler.sendEmptyMessage(0);
}
@JavascriptInterface
public void toast(String str) {
Toast.makeText(activity, "aaaaaaaaaaaa --- " + str, Toast.LENGTH_LONG).show();
}
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 0:
String json = "[{\"name\":\"zxx\", \"amount\":\"9999999\", \"phone\":\"18600012345\"}]";
// 调用JS中的方法
webView.loadUrl("javascript:show('" + json + "')");
break;
default:
break;
}
}
};
// 重写addJavaScriptInteface getClass方法,防止类对象漏洞攻击
public Object getClass(Object o) {
return null;
}
}
getClass(Object o)方法是一个重写方法,是为了修补Android 4.2(API17)之前的javaScrip脚本注入添加的。然后每个定义在这个类中的要被HTML页面调用的方法都要加上@JavascriptInterface注解。此处需要注意的是showcontacts()方法触发的Javascript脚本涉及了界面绘制,因此必须要在主线程中调用,此处使用了Handler来解决这个问题。关键的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); var table = document.getElementById("personTable"); 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); td3.align = "center"; td1.innerHTML = jsonobjs[y].name; td2.innerHTML = jsonobjs[y].amount; td3.innerHTML = "<a href='javascript:contact.call(\""+ jsonobjs[y].phone+ "\")'>"+ jsonobjs[y].phone+ "</a>"; } } </script> </head> <body οnlοad="javascript:contact.showcontacts()"> <button id="button" onclick = "javascript:contact.toast('123')">haha</button> <table border="0" width="100%" id="personTable" cellspacing="0"> <tr> <td width="30%">姓名</td> <td width="30%" align="center">存款</td> <td align="center">电话</td> </tr> </table> </body> </html>
javascript:contact.showcontacts()、javascript:contact.toast('123')调用了MainActivity中contact对象的方法。而
webView.loadUrl("javascript:show('" + json + "')")一句则调用了index.html中的JavaScript脚本。虽然例子中的实现的功能非常简单,但是这种混合的交互方式可以为开发者解决很多开发中的限制。另外,index.html文件可以放到Android的assets目录下,实现本地调用。
如文章有错漏或demo有BUG,欢迎指正,求教育,求教导~~~
源码下载地址