美文网首页
Android WebViewJSBridge分析

Android WebViewJSBridge分析

作者: 小锡兵鸥 | 来源:发表于2017-12-08 16:46 被阅读849次

Android WebViewJSBridge分析

WebViewJavascriptBridge的github地址

这种方法采用js注入的方式来实现webView与h5的交互
相关文件的UML图


image

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); });

相关文章

网友评论

      本文标题:Android WebViewJSBridge分析

      本文链接:https://www.haomeiwen.com/subject/vwoeixtx.html