js 与原生交互分为两种状况:js 调用原生方法,原生调用 js 方法。javascript
本文将对这两种状况分别讲解,H5 端用 vue
实现。vue
本文的 H5 端用Vue
实现,因此在正式开始前先把 Vue
项目环境准备好。java
项目写好后,执行 npm run serve
命令启动项目,启动成功后会在命令行看到两个地址:web
http://localhost:8080/
和 http://10.0.0.188:8080/
vue-cli
10.0.0.188
是我本机的 ip
地址,每一个人的不同。npm
在电脑的浏览器访问的话哪一个都行,但在手机或模拟器访问的话须要用第二个带 ip
地址的,且要保证手机跟电脑链接同一个 wifi
或在同一网段。浏览器
注意:这里用的是 vue-cli 3.0,运行命令跟 vue-cli 2.X 有所区别。详情请自行查询官方文档。bash
启动成功后在 Android 项目中将 http://10.0.0.188:8080/
地址配置给 WebView
便可ide
Intent intent = new Intent(getActivity(), ProgressWebviewActivity.class);
intent.putExtra("url", "http://10.0.0.188:8080/");
startActivity(intent);
复制代码
到此,在手机中就能够访问 Vue
项目了。post
Android 调用 JS 有两种方式,都是经过 WebView
的方法:
webview.loadUrl()
webview.evaluateJavascript()
两者区别:
loadUrl()
会刷新页面,evaluateJavascript()
则不会使页面刷新,因此evaluateJavascript()
的效率更高
loadUrl()
得不到 js 的返回值,evaluateJavascript()
能够获取返回值
evaluateJavascript()
在 Android 4.4 以后才可使用
要实现的效果:
以下图,页面上有一行文字 ”哈哈“,要在 WebView
页面加载完的时候经过 Android 原生代码将这行字改成 ”我经过原生方法改变了文字“ + Android 传递过来的参数,并给 Android 返回一个字符串 ”js调用成功“。
先看 Vue 中代码怎么写
mounted() {
//将要给原生调用的方法挂载到 window 上面
window.callJsFunction = this.callJsFunction
},
data() {
return {
msg: "哈哈"
}
},
methods: {
callJsFunction(str) {
this.msg = "我经过原生方法改变了文字" + str
return "js调用成功"
}
}
复制代码
在 methods
中定义一个供 Android 调用的方法 callJsFunction(str)
, 并可接收一个参数 str
,而后改变页面中的文字。
若是只是在 methods
中定义方法,原生调用会找不到这个方法。因此要在页面加载的时候将方法挂载在 window
上,这样 WebView
就能够拿到此方法了。注意,这步很重要必定要写!
注意一个细节,this.callJsFunction
后面不要加括号 ()
,加括号至关于直接调用了。
总结起来 Vue
中要作的事情就两步:
methods
中定义方法mounted
中将方法挂载在 window
上须要等页面加载完在 WebView
的 onPageFinished
方法中写调用逻辑,不然不会执行。
loadUrl()
实现tbsWebView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url, headerMap);
return true;
}
@Override
public void onPageFinished(WebView webView, String s) {
super.onPageFinished(webView, s);
//安卓调用js方法。注意须要在 onPageFinished 回调里调用
tbsWebView.post(new Runnable() {
@Override
public void run() {
tbsWebView.loadUrl("javascript:callJsFunction('soloname')");
}
});
}
});
}
});
复制代码
若是不须要传参数,把参数去掉便可 tbsWebView.loadUrl("javascript:callJsFunction()");
evaluateJavascript()
实现其余地方跟loadUrl()
同样,只是把 tbsWebView.loadUrl("javascript:callJsFunction('soloname')");
替换掉
@Override
public void onPageFinished(WebView webView, String s) {
super.onPageFinished(webView, s);
//安卓调用js方法。注意须要在 onPageFinished 回调里调用
tbsWebView.post(new Runnable() {
@Override
public void run() {
tbsWebView.evaluateJavascript("javascript:callJsFunction('soloname')", new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
Logger.d("js返回的结果: " + s);
}
});
}
});
}
复制代码
能够看到页面更新了,第二种方法也拿到了返回的结果。
对于JS调用Android代码的方法有3种:
WebView
的 addJavascriptInterface()
进行对象映射WebViewClient
的 shouldOverrideUrlLoading()
方法回调拦截 urlWebChromeClient
的onJsAlert()
、onJsConfirm()
、onJsPrompt()
方法回调拦截JS对话框alert()
、confirm()
、prompt()
消息对比: 第一种最简洁,但在 Android 4. 2 如下存在漏洞;第二种和第三种使用复杂,但不存在漏洞问题。
因为目前的设备系统版本基本都在 4.2 以上,因此用第一种就能够了,简单快捷。时间有限本文只实现第一种,第二种和第三种就不实现了,想了解的能够参考 这篇文章 。
要实现的效果就是点击 H5 页面上的按钮,弹出 Android 原生的 Toast
methods: {
showAndroidToast() {
$App.showToast("哈哈,我是js调用的")
}
}
复制代码
在 methods
中定义方法 showAndroidToast()
, 点击页面上按钮 "调用Android原生Toast" 时调用。
新建类 JsJavaBridge
public class JsJavaBridge {
private Activity activity;
private WebView webView;
public JsJavaBridge(Activity activity, WebView webView) {
this.activity = activity;
this.webView = webView;
}
@JavascriptInterface
public void onFinishActivity() {
activity.finish();
}
@JavascriptInterface
public void showToast(String msg) {
ToastUtils.show(msg);
}
}
复制代码
而后经过 WebView
设置 Android
类与 JS 代码的映射
tbsWebView.addJavascriptInterface(new JsJavaBridge(this, tbsWebView), "$App");
复制代码
这里将类 JsJavaBridge
在 JS 中映射为了 $App
,因此在 Vue 中能够这样调用 $App.showToast("哈哈,我是js调用的")
。
以上就是 Android 与 JS 的互相调用。