功能描述: 1.Android调用JS 2.JS调用Android
直接上代码:
1.在app的build.gradle中添加依赖库:
compile'com.github.lzyzsd:jsbridge:1.0.4'
添加完成编译后会报错如下:
报这个错是因为第三方库jsbridge也需要依赖库,
2.在项目的build.gradle中添加:
maven {url "https://jitpack.io" }
再次编译通过
3.在布局中添加自定义WebView:
com.github.lzyzsd.jsbridge.BridgeWebView
4.业务逻辑
初始化WebView并注册Handler
注:1.其中registerHandler是供JS调用Android使用 2.callHandler是Android主动调起JS
WebView初始化以及常用的配置信息
```
/**
* 初始化BridgeWebView
*/
private void setBridgeWebView() {
bridgeWebView = findViewById(R.id.bridgewebview);
//WebView常用配置
WebSettings settings =bridgeWebView.getSettings();
settings.setJavaScriptEnabled(true);//允许使用js
settings.setDomStorageEnabled(true);//设置适应Html5
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
bridgeWebView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
}
/**
* LOAD_CACHE_ONLY: 不使用网络,只读取本地缓存数据
* LOAD_DEFAULT: (默认)根据cache-control决定是否从网络上取数据。
* LOAD_NO_CACHE: 不使用缓存,只从网络获取数据.
* LOAD_CACHE_ELSE_NETWORK,只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据。
*/
settings.setCacheMode(WebSettings.LOAD_NO_CACHE);//不使用缓存,只从网络获取数据.
// 设置WebView属性,能够执行Javascript脚本
settings.setDefaultTextEncodingName("utf-8");
//允许webview对文件的操作
settings.setAllowUniversalAccessFromFileURLs(true);
settings.setAllowFileAccess(true);
settings.setAllowFileAccessFromFileURLs(true);
settings.setAllowContentAccess(true);
settings.setDatabaseEnabled(true);
bridgeWebView.setWebChromeClient(new WebChromeClient());
bridgeWebView.setWebViewClient(new BridgeWebViewClient(bridgeWebView) {
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
//页面加载完成...
}
});
}
```
最后Android想要调起JS需要在assets目录下添加桥文件:
WebViewJavascriptBridge.js
//notation: js file can only use this kind of comments
//since comments will cause error when use in webview.loadurl,
//comments will be remove by java use regexp
(function() {
if (window.WebViewJavascriptBridge) {
return;
}
var messagingIframe;
var bizMessagingIframe;
var sendMessageQueue = [];
var receiveMessageQueue = [];
var messageHandlers = {};
var CUSTOM_PROTOCOL_SCHEME ='yy';
var QUEUE_HAS_MESSAGE ='__QUEUE_MESSAGE__/';
var responseCallbacks = {};
var uniqueId =1;
// 创建消息index队列iframe
function _createQueueReadyIframe(doc) {
messagingIframe = doc.createElement('iframe');
messagingIframe.style.display ='none';
doc.documentElement.appendChild(messagingIframe);
}
//创建消息体队列iframe
function _createQueueReadyIframe4biz(doc) {
bizMessagingIframe = doc.createElement('iframe');
bizMessagingIframe.style.display ='none';
doc.documentElement.appendChild(bizMessagingIframe);
}
//set default messageHandler 初始化默认的消息线程
function init(messageHandler) {
if (WebViewJavascriptBridge._messageHandler) {
throw new Error('WebViewJavascriptBridge.init called twice');
}
WebViewJavascriptBridge._messageHandler = messageHandler;
var receivedMessages = receiveMessageQueue;
receiveMessageQueue =null;
for (var i =0; i < receivedMessages.length; i++) {
_dispatchMessageFromNative(receivedMessages[i]);
}
}
// 发送
function send(data, responseCallback) {
_doSend({
data: data
}, responseCallback);
}
// 注册线程 往数组里面添加值
function registerHandler(handlerName, handler) {
messageHandlers[handlerName] = handler;
}
// 调用线程
function callHandler(handlerName, data, responseCallback) {
_doSend({
handlerName: handlerName,
data: data
}, responseCallback);
}
//sendMessage add message, 触发native处理sendMessage
function _doSend(message, responseCallback) {
if (responseCallback) {
var callbackId ='cb_' + (uniqueId++) +'_' +new Date().getTime();
responseCallbacks[callbackId] = responseCallback;
message.callbackId = callbackId;
}
sendMessageQueue.push(message);
messagingIframe.src = CUSTOM_PROTOCOL_SCHEME +'://' + QUEUE_HAS_MESSAGE;
}
// 提供给native调用,该函数作用:获取sendMessageQueue返回给native,由于android不能直接获取返回的内容,所以使用url shouldOverrideUrlLoading 的方式返回内容
function _fetchQueue() {
var messageQueueString = JSON.stringify(sendMessageQueue);
sendMessageQueue = [];
//android can't read directly the return data, so we can reload iframe src to communicate with java
bizMessagingIframe.src = CUSTOM_PROTOCOL_SCHEME +'://return/_fetchQueue/' + encodeURIComponent(messageQueueString);
}
//提供给native使用,
function _dispatchMessageFromNative(messageJSON) {
setTimeout(function() {
var message = JSON.parse(messageJSON);
var responseCallback;
//java call finished, now need to call js callback function
if (message.responseId) {
responseCallback = responseCallbacks[message.responseId];
if (!responseCallback) {
return;
}
responseCallback(message.responseData);
delete responseCallbacks[message.responseId];
}else {
//直接发送
if (message.callbackId) {
var callbackResponseId = message.callbackId;
responseCallback =function(responseData) {
_doSend({
responseId: callbackResponseId,
responseData: responseData
});
};
}
var handler = WebViewJavascriptBridge._messageHandler;
if (message.handlerName) {
handler = messageHandlers[message.handlerName];
}
//查找指定handler
try {
handler(message.data, responseCallback);
}catch (exception) {
if (typeof console !='undefined') {
console.log("WebViewJavascriptBridge: WARNING: javascript handler threw.", message, exception);
}
}
}
});
}
//提供给native调用,receiveMessageQueue 在会在页面加载完后赋值为null,所以
function _handleMessageFromNative(messageJSON) {
console.log(messageJSON);
if (receiveMessageQueue) {
receiveMessageQueue.push(messageJSON);
}
_dispatchMessageFromNative(messageJSON);
}
var WebViewJavascriptBridge = window.WebViewJavascriptBridge = {
init: init,
send: send,
registerHandler: registerHandler,
callHandler: callHandler,
_fetchQueue: _fetchQueue,
_handleMessageFromNative: _handleMessageFromNative
};
var doc = document;
_createQueueReadyIframe(doc);
_createQueueReadyIframe4biz(doc);
var readyEvent = doc.createEvent('Events');
readyEvent.initEvent('WebViewJavascriptBridgeReady');
readyEvent.bridge = WebViewJavascriptBridge;
doc.dispatchEvent(readyEvent);
})();
最后清单文件添加网络权限
<uses-permission android:name="android.permission.INTERNET" />
备注:交互一般都是在WebView加载完成后使用,未加载完成时,交互会出问题