此项目,主要演示Android的WebView视图中,Native Call JavaScript、以及JavaScript Call Native的几种方式。
写在前面: Hybrid不可避免使用Native和JS交互,本文主要总结一下Android和JavaScript交互的解决方方。
[TOC]
mWebView.loadUrl("javascript:alert('hello world')");StringjsString = "sum(a, b)";
mWebView.evaluateJavascript(js, newValueCallback<String>() {
@OverridepublicvoidonReceiveValue(Strings) {
// 这里可以处理被调用js方法的return
}
});方案三:引用JsBridge框架
- Web首先初始化WebViewJavascriptBridge,注册事件监听。
- Web然后初始化接收函数回调,分为默认接收和指定接收,responseCallback回调给Native信息
- Native 调用
Webview.send()或WebView.callHandler()
//注册事件监听,初始化functionsetupWebViewJavascriptBridge(callback){if(window.WebViewJavascriptBridge){callback(WebViewJavascriptBridge)}else{document.addEventListener('WebViewJavascriptBridgeReady',function(){callback(WebViewJavascriptBridge)},false);}}//回调函数,接收java发送来的数据setupWebViewJavascriptBridge(function(bridge){//默认接收bridge.init(function(message,responseCallback){// 处理接收到消息});//指定接收,bridge.registerHandler("JSFUCN",function(data,responseCallback){// 处理接收到消息});})// 默认接收privatevoidcallJavaScriptDefaut() {
mWebView.send("发送数据给js默认接收, new CallBackFunction() { @Override public void onCallBack(String data) { //处理js回传的数据 }); } // 指定接收 private void callJavaScriptSpec() { mWebView.callHandler("JSFUCN", "发送数据给js指定接收", newCallBackFunction() {
@OverridepublicvoidonCallBack(Stringdata) { //处理js回传的数据
}
});
}利用 webview调用js需要注意一下几点
- WebSettings设置支持javascript
// 设置在类之前@SuppressLint("SetJavaScriptEnabled") mWebView.getSettings().setJavaScriptEnabled(true);- 在运行Js脚本前,要有document对象,至少得load一个空白页
webView.loadData("","text/html","UTF-8");- 如果还是不行的话,就应该是因为第一个还没执行完呢 - 从界面按钮调用 - 延时调用 - 在onPageFinished中调用
webView.loadData(“”,"text/html","UTF-8");
webView.loadUrl("javascript:alert('hello')");- 必须实现WebChromeClient、WebViewClient
webView.setWebViewClient(newWebViewClient());
webView.setWebChromeClient(newWebChromeClient());- 使用JSBridge不用实现WebViewClient
- WebViewClient重载
shouldOverrideUrlLoading拦截URL
Web代码
functionopenMyBlogNewTarget(){window.open('https://www.jianshu.com/u/263c210b047c')}functionopenMyBlog(){window.location.href='https://www.jianshu.com/u/263c210b047c'}<ahref="http://www.baidu.com" title="baidu" target="_blank">新标签页打开百度</a><ahref="http://www.baidu.com" title="baidu" >当前页打开百度</a><buttononclick='openMyBlogNewTarget()'>新标签打开我的博客</button><buttononclick="openMyBlog()">打开我的博客</button>Android代码
privateclassMYWebViewClientextendsWebViewClient {
@OverridepublicvoidonPageStarted(WebViewview, Stringurl, Bitmapfavicon) {
super.onPageStarted(view, url, favicon);
}
// 新方法 API21以后@OverridepublicbooleanshouldOverrideUrlLoading(WebViewview, WebResourceRequestrequest) {
super.shouldOverrideUrlLoading(view, request);
// 拦截Requestif (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Log.d(TAG, "shouldOverrideUrlLoading: " + request.getUrl().toString());
}
returntrue;
}
// 旧方法 兼容API21之前@OverridepublicbooleanshouldOverrideUrlLoading(WebViewview, Stringurl) {
super.shouldOverrideUrlLoading(view, url);
// 拦截urlLog.d(TAG, "shouldOverrideUrlLoading: " + url);
returntrue;
}
}- JS中使用window.objects.function语法调用Native,其中objects与Native中一直。
- Native中定义Class,以及被调用的func用 public、@JavascriptInterface修饰。
- Native中
addJavascriptInterface(obj, name)。
functioncallNative(){varamount=123.5;varorderno="FG1afsdakewqr";window.mobileApp.toPay(amount,orderno);}<buttononclick="window.mobileApp.sendMessage('特斯拉 Model 3')">获取商品名</button><buttononclick="callNative()">支付按钮</button>mWebView.addJavascriptInterface(newJsInterface(tv), "mobileApp");
privateclassJsInterface {
privateTextViewshowText;
publicJsInterface(TextViewtv) {
showText = tv;
}
@JavascriptInterfacepublicvoidsendMessage(Stringmsg) {
Log.d(TAG, "sendMessage: " + msg);
}
@JavascriptInterfacepublicvoidtoPay(floatamount, Stringoderno) {
Log.d(TAG, "sendMessage: " + amount);
}
}方案三:引用JsBridge框架
- JS中调用
window.WebViewJavascriptBridge.send或者window.WebViewJavascriptBridge.callHandler向Native发消息 - Native中注册指定接收
WebView.registerHandler或者注册默认接收WebView.setDefaultHandler
//js传递数据给javafunctionjsCallNativeDefault(){window.WebViewJavascriptBridge.send({'param': "str1"},function(responseData){//处理java回传的数据});}functionjsCallNativeSpec(){window.WebViewJavascriptBridge.callHandler('Spec'//指定接收参数 submitFromWeb与java一致,'指定接收',function(responseData){//处理java回传的数据});}mWebView.registerHandler("Spec", newBridgeHandler() {
@Overridepublicvoidhandler(Stringdata, CallBackFunctionfunction) {
Log.i("", "handler = submitFromWeb, data from web = " + data);
function.onCallBack("submitFromWeb exe, response data 中文 from Java");
showTextView.setText("指定接收:" + data);
}
});
mWebView.setDefaultHandler(newDefaultHandler() {
@Overridepublicvoidhandler(Stringdata, CallBackFunctionfunction) {
Log.i("", "handler = submitFromWeb, data from web = " + data);
function.onCallBack("submitFromWeb exe, response data 中文 from Java");
showTextView.setText("默认接收:" + data);
}
});