场景
为了降低开发成本和跨平台一致性的用户体验.通常敏捷开发中通常采用混合型应用Hybrid App
(Native View与WebView交替调用),而Js作为Html页面中常用的逻辑处理脚本,掌握JS和Java的相互通信是非常重要的!
操作步骤
- webView设置支持JavaScript
- webView提供JavaScript接口
- 客户端和网页端定义好方法申明.编写代码
Js调用Java
ps: 有时候,在webview中有个Button,而点击这个Button.我们的App需要finish掉这个页面,但是我们在App中是没法捕捉到这个按钮的点击事件的,.那么这时候就需要用到Js 回调Java的方法来实现了
①布局文件
<WebView
android:id="@+id/webview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
②Js代码
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=gb2312">
</head>
<body>
<title>test html</title>
<button onclick="window.js.comeplete()">comeplete()</button>
<br/>
</body>
</html>
很简单,就是一个按钮,并添加点击事件,这里需要注意的是我们的调用,里面有一个.js,其实这个是我们在java代码中天加的接口名字.
③java代码
首先为了能够支持JavaScript,我们的webView必须setJavaScriptEnabled(true)
mWebView = (WebView) findViewById(R.id.webview);
// 启用javascript
mWebView .getSettings().setJavaScriptEnabled(true);
// 从assets目录下面的加载html
mWebView .loadUrl("file:///android_asset/js.html");
mWebView .addJavascriptInterface(this, "js");
④最后添加相应的方法
public void comeplete(){
this.finish();
}
Java调用JS
同样,有时候,我们又需要根据不同的操作,让页面显示不同的内容,那么这时候就需要用到Java调用JavaScript了/
①这时候,我们的html页面是这样的
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=gb2312">
<script type="text/javascript">
function javacalljs(){
document.getElementById("content").innerHTML +=
"<br\>java调用了js函数";
}
function javacalljswithargs(arg){
document.getElementById("content").innerHTML +=
("<br\>"+arg);
}
</script>
</head>
<body>
<title>test html</title>
<div id="content">内容显示</div>
</body>
</html>
②布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<WebView
android:id="@+id/webview"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<Button
android:id="@+id/button1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="java调用js函数" />
<Button
android:id="@+id/button2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="java调用js函数(带参数)" />
</LinearLayout>
③Java代码
mWebView = (WebView) findViewById(R.id.webview);
// 启用javascript
mWebView .getSettings().setJavaScriptEnabled(true);
// 从assets目录下面的加载html
mWebView .loadUrl("file:///android_asset/js.html");
Button button1 = (Button) findViewById(R.id.button1);
button1.setOnClickListener(btnClickListener);
Button button2 = (Button) findViewById(R.id.button2);
button2.setOnClickListener(btnClickListener);
④按钮的点击事件
OnClickListener btnClickListener = new Button.OnClickListener() {
public void onClick(View v) {
switch (v.getId()) {
case R.id.button1:
// 无参数调用
mWebView.loadUrl("javascript:javacalljs()");
break;
case R.id.button2:// 传递参数调用
mWebView .loadUrl("javascript:javacalljswithargs(" + "'hello world,i`m Java'" + ")");
break;
default:
break;
}
}
};
Android 4.2以后的注入事项
- @JavascriptInterface
在使用中,我们发现当targetSdkVersion>17
的时候就会出现一下异常E/Web Console: Uncaught TypeError: Object [object Object] has no method 'toString'
通过查看官方文档,解释如下
From the Android 4.2 documentation:
Caution: If you've set your targetSdkVersion to 17 or higher, you must add the @JavascriptInterface annotation to any method that you want available your web page code (the method must also be public). If you do not provide the annotation, then the method will not accessible by your web page when running on Android 4.2 or higher.
意思就是当targetSdkVersion>17
的时候,我们需要在暴露给js的接口加上@JavascriptInterface
注解
因此4.2 之后的js 调用java方式是这样的
@JavascriptInterface
public void comeplete(){
this.finish();
}
调用js有参数有返回值的函数
Android在4.4之前并没有提供直接调用js函数并获取值的方法,所以在此之前,常用的思路是 java调用js方法,js方法执行完毕,再次调用java代码将值返回。
Js代码:
function button2click1(){
window.js.showResult(index);
}
Java代码
mWebView.loadUrl("javascript:button2click1()");
// 在回调中获取返回值
@JavascriptInterface
public void showResult(String s){
Toast.makeText(this,s+"",Toast.LENGTH_LONG).show();
}
Android 4.4之后使用evaluateJavascript
即可获取JavaScript返回值.
Js代码
var index=0;
function android_call_js_parameter(arg){
index+=Number(arg);
document.getElementById("content").innerHTML +=("<br\>"+index);
return index;
}
function button2click(){
return 1;
}
Java代码
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
mWebView.evaluateJavascript("button2click()",
//设置回调接口
new ValueCallback<String>() {
@Override
public void onReceiveValue(String value) {
mWebView.loadUrl("javascript:android_call_js_parameter('" + value + "')");
}
});
}
效果图:
使用Dmeo:JsJavaInteractive [Github]
参考:
stackoverflow: [Android - How I can call javascript function and getting the retur value from javascript function]
技术小黑屋: [Android中Java和JavaScript交互]