最近一直都在做webView与H5互调方面的开发,也就是大家通常所说的hybird app开发,正好赶上周末手头的事情基本处理完了,闲下来更了这篇博客,打算分两期介绍WebView与H5互调,今天先简单分析下安卓上webview与h5互调的简单实现,js代码采用本地代码讲解,我先把完整的示例代码贴上之后让大家有个大概的认识,在博客最后再对一些细节进行稍微简短的分析下。
进入正题:对于webView在这里就不多做讲解了,今天主要是讲解webview与js的互调上。
先在studio的assets文件夹下面新建一个html文件,我本地命名的html文件为zhuandian.html。
代码如下:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=gb2312">
<script type="text/javascript">
function webViewcalljs(){
document.getElementById("content").innerHTML =
"<br\>Android中的Webview调用了JS的无参函数";
}
function webViewcalljswith(arg){
document.getElementById("content").innerHTML =
("<br\>"+arg);
}
</script>
</head>
<body>
HTML 内容显示 <br/>
<h1><div id="content">内容显示</div></h1>
<br/>
<input type="button" value="点击调用安卓中的startFunction方法" onclick="window.zhuandian.startFunction()" />
<br/>
<input type="button" value="点击调用安卓中startFunction方法并传递参数" onclick="window.zhuandian.startFunction('')" />
</body>
</html>
如上所示:html代码简单明了,定义了两个js代码供安卓中的webview调用,同时在最后的几行代码中,在html页面中定义了两个button点击事件触发的是安卓上的事件。稍后会在安卓中mainActivity中看见。
接下来是安卓布局文件:上面两个按钮,分别绑定的监听事件为调用js的无参函数跟有参函数,下面是一个webview。
代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:id="@+id/button"
android:layout_margin="8dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="调用JS"
android:background="@color/colorAccent"
android:textColor="#ffffff"
/>
<Button
android:id="@+id/button2"
android:layout_margin="8dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="调用有参JS"
android:background="@color/colorAccent"
android:textColor="#ffffff"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="WebView"
android:layout_marginTop="8dp"
/>
<WebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
最后是MainActivity.java代码,在代码中主要处理了对js中点击事件的响应和处理js中的回调。先贴上代码,最后再分析
/**
* @author 谢栋
*/
public class MainActivity extends AppCompatActivity {
private WebView contentWebView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
contentWebView = (WebView) findViewById(R.id.webview);
// 启用javascript
contentWebView.getSettings().setJavaScriptEnabled(true);
// 从assets目录下面的加载html
contentWebView.loadUrl("file:///android_asset/zhuandian.html");
contentWebView.addJavascriptInterface(MainActivity.this,"zhuandian");
//Button按钮 无参调用HTML js方法
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 无参数调用 JS的方法
contentWebView.loadUrl("javascript:webViewcalljs()");
}
});
//Button按钮 有参调用HTML js方法
findViewById(R.id.button2).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 传递参数调用JS的方法
contentWebView.loadUrl("javascript:webViewcalljswith(" + "'我是从webview上传递过来,我会显示在html上'" + ")");
}
});
}
//由于安全原因 targetSdkVersion>=17需要加 @JavascriptInterface
//JS调用Android JAVA方法名和HTML中的按钮 onclick后的别名后面的名字对应
@JavascriptInterface
public void startFunction(){
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this,"show",Toast.LENGTH_LONG).show();
}
});
}
@JavascriptInterface
public void startFunction(final String text){
runOnUiThread(new Runnable() {
@Override
public void run() {
new AlertDialog.Builder(MainActivity.this).setMessage(text).show();
}
});
}
}
至此整个示例已完成,下面我简单分析下整个互调的过程。在webview中调起js中调方法,首先要先对webview启用javascript,并切把写好的与js互调的java方法通过addJavaScriptInterface完成关联。
// 启用javascript
contentWebView.getSettings().setJavaScriptEnabled(true);
contentWebView.addJavascriptInterface(MainActivity.this,"zhuandian");
第一个参数这里如果是直接在当前类里写的方法可以直接传this进来,如果是以类的形式注册的方法则一定要写全类名
由于webview在之前的版本中有好多不可避免的漏洞,具体是何漏洞感兴趣的可以深入了解下,这里不多做解说。所以只要你的targetSdkVersion>=17的话需要在方法前加@JavaScriptInterface,处于安全考虑。
第二个参数一定要和html中的按钮onclick事件后面的别名保持一致,否则累死h5也调不同安卓上写好的方法。
对MainActivity中调按钮1通过loadUrl的方式绑定到javascript上的webviewCallJs()方法。
//Button按钮 无参调用HTML js方法
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 无参数调用 JS的方法
contentWebView.loadUrl("javascript:webViewcalljs()");
}
});
js中对应的方法为
function webViewcalljs(){
document.getElementById("content").innerHTML =
"<br\>Android中的Webview调用了JS的无参函数";
}
点击安卓上的按钮后会在html上打印这句话。buttom2事件类似。
接下来分析下从h5上调安卓的方法,html代码中的button的onClick事件为:
<input type="button" value="点击调用安卓中startFunction方法并传递参数" onclick="window.zhuandian.startFunction('我是从webview上传递过来,我会显示在html')" />
可以看到html上的button的点击事件后面的别名是我刚提到过的zhuandian,与在安卓MainActivity中注册的别名保持一致
contentWebView.addJavascriptInterface(MainActivity.this,"zhuandian");
再往后的startFunction方法即为安卓MainActivity中的供H5调用的已经写好的方法
@JavascriptInterface
public void startFunction(final String text){
runOnUiThread(new Runnable() {
@Override
public void run() {
new AlertDialog.Builder(MainActivity.this).setMessage(text).show();
}
});
}
点击H5上的按钮会在安卓手机屏幕上弹出一个Dialog并且H5上传递过来的参数会显示到dialog上。
今天先简单的分析这些,由浅入深,下次我会分享一个实际演示的例子来加深大家对安卓与H5互调的理解。当然在今天的基础上
你完全可以自由发挥去做一下尝试。