Android WebViewJSBridge分析
WebViewJavascriptBridge的github地址
这种方法采用js注入的方式来实现webView与h5的交互
相关文件的UML图
Native相关操作
Activity中new WebViewJavascriptBridge()对象 bridge
在WebView加载成功之后 onPageFinish()方法中加载本地js代码
-
在WebView对象上addJavascriptInterface(Object object, String name),This method can be used to allow JavaScript to control the host application. 在本地js文件中可以通过该name来,调用Native方法,调用的方法必须由@JavascriptInterface 注解
mWebView.addJavascriptInterface(this, "_WebViewJavascriptBridge");
本地js代码实现的功能
- 在当前window上添加WebViewJavascriptBridge对象
- 在当前document对象上添加一个event, 将该WebViewJavascriptBridge添加到event中,通过document分发这个event
- 在html加载的js文件中,监听该event。收到该event消息之后,获取event中WebViewJavascriptBridge对象,进行初始化, 给WebViewJavascriptBridge._messageHandler赋值。
现在H5页面获取WebViewJavascriptBridge对象,可以进行交互啦!
H5发送消息到Native
bridge就是H5页面获取的WebViewJavascriptBridge对象
bridge.callHandler("handler1","gift for handler1",function(responseData){
console.log("got handler1 response:"+responseData);
});
Native处理H5发来的消息
-
native本地的js代码
function callHandler(handlerName, data, responseCallback) { _doSend({ handlerName:handlerName, data:data }, responseCallback) } function _doSend(message, responseCallback) { if (responseCallback) { var callbackId = 'cb_'+(uniqueId++)+'_'+new Date().getTime(); responseCallbacks[callbackId] = responseCallback; message['callbackId'] = callbackId; } console.log("sending:"+JSON.stringify(message)); //调用Native方法 _WebViewJavascriptBridge._handleMessageFromJs(JSON.stringify(message.data)||null,message.responseId||null, message.responseData||null,message.callbackId||null,message.handlerName||null); }
-
native代码处理消息
_handleMessageFromJs方法负责找到注册该hanlderName的WVJBHandler,把h5发来的信息回调回Activity,Activity做相应的处理。</br>@JavascriptInterface public void _handleMessageFromJs(final String data, String responseId, String responseData, String callbackId, String handlerName){ if (null!=responseId) { WVJBResponseCallback responseCallback = _responseCallbacks.get(responseId); responseCallback.callback(responseData); _responseCallbacks.remove(responseId); } else { WVJBResponseCallback responseCallback = null; if (null!=callbackId) { responseCallback=new CallbackJs(callbackId); } final WVJBHandler handler; if (null!=handlerName) { handler = _messageHandlers.get(handlerName); if (null==handler) { Log.e("test","WVJB Warning: No handler for "+handlerName); return ; } } else { handler = _messageHandler; } try { final WVJBResponseCallback finalResponseCallback = responseCallback; mContext.runOnUiThread(new Runnable(){ @Override public void run() { //回调给Activity处理 handler.handle(data, finalResponseCallback); } }); }catch (Exception exception) { Log.e("test","WebViewJavascriptBridge: WARNING: java handler threw. "+exception.getMessage()); } } }
Native发送消息到H5
-
Activity中WebViewJavascriptBridge对象bridge,这个对象和window.WebViewJavascriptBridge不是同一个。
bridge.callHandler("gotoMarker","1");
WebViewJavascriptBridge.java
public void callHandler(String handlerName, String data) { callHandler(handlerName, data,null); } public void callHandler(String handlerName, String data, WVJBResponseCallback responseCallback){ _sendData(data, responseCallback,handlerName); } private void _sendData(String data, WVJBResponseCallback responseCallback, String handlerName){ Map<String, String> message=new HashMap<String,String>(); message.put("data",data); if (null!=responseCallback) { String callbackId = "java_cb_"+ (++_uniqueId); _responseCallbacks.put(callbackId,responseCallback); message.put("callbackId",callbackId); } if (null!=handlerName) { message.put("handlerName", handlerName); } _dispatchMessage(message); } private void _dispatchMessage(Map<String, String> message){ String messageJSON = new JSONObject(message).toString(); //调用WebViewJavascriptBridge.js的方法 final String javascriptCommand=String.format("javascript:WebViewJavascriptBridge._handleMessageFromJava('%s');",doubleEscapeString(messageJSON)); mContext.runOnUiThread(new Runnable(){ @Override public void run() { mWebView.loadUrl(javascriptCommand); } }); }
H5处理Native发来的消息
Native的js代码处理,找到H5代码注册的那个Handler回调方法,回调回去,即可处理消息。</br>
WebViewJavascriptBridge.js
function _dispatchMessageFromJava(messageJSON) {
var message = JSON.parse(messageJSON);
var messageHandler;
if (message.responseId) {
var responseCallback = responseCallbacks[message.responseId];
if (!responseCallback) { return; }
responseCallback(message.responseData);
delete responseCallbacks[message.responseId]
} else {
var responseCallback;
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]
}
try {
handler(message.data, responseCallback)
} catch(exception) {
if (typeof console != 'undefined') {
console.log("WebViewJavascriptBridge: WARNING: javascript handler threw."+ exception)
}
}
}
}
html中方法
bridge.registerHandler("showAlert", function(data) { console.log("alert:"+data); });