关于jsBridge

最近在开发移动端项目时,需要用到jsBridge,因此总结下自己了解jsbridge的过程

一、为什么会用到jsbridge

在混合开发中的前端部分(javascript)调用native的功能时需要用到jsbriage,例如:分享时我们需要打开微信、QQ,以及调用摄像头,获取地理位置等;因为app内嵌的H5页面中我们无法调出这些功能。

在了解jsbridge前,我们需要了解下整个移动端的大致发展流程,可能会更容易理解了

最早之前,1)是有原生的IOS和Android,开发成本高;

2)随着H5标准的发布,就有了webapp的概念,也就是在触屏浏览器里运行的,宿主是浏览器,不再是操作系统。依赖于浏览器的处理能量并且与原生交互受限;为了解决WebApp 与原生接口交互受限。交互体验差,便提出了混合开发(hybrid)的概念,称作混合模式移动应用,介于WebApp与Native App两者之间的开发技术;(ios和android依然是2套代码);用html+js来写页面的逻辑,然后由native通过jsbriage等方法提供统一的api,最终的页面也是在webview中显

3)跨平台,例如react native,weex,以及大火的flutter(并没有相关研究,只是举个例子)

最后附上相关链接:https://zhuanlan.zhihu.com/p/79495800  ,https://zhuanlan.zhihu.com/p/58691238

二、怎么使用(封装)jsbridge

在使用jsbridge之前,需要知道什么是jsbridge?

jsbridge是一个 iOS/OSX 桥或Android/js桥,用于在 WKWebViews、UIWebViews 和 WebViews 中的 Obj-C 和 JavaScript 之间发送消息

由于javascript运行在一个单独的 JS Context 中,与原生运行环境天然隔离,jsbriage就是来建立这两者之间的通道

现在你知道jsbridge是native和非native之前通信的通道,而且这个通道是双向的,js可以通过jsbridge调用native的原生api,native也可以向js发送消息,传达native调用后的状态

双向通信的通道:

  • JS 向 Native 发送消息: 调用相关功能、通知 Native 当前 JS 的相关状态等。
  • Native 向 JS 发送消息: 回溯调用结果、消息推送、通知 JS 当前 Native 的状态等

那么jsbriage是如何在native和js之前通信的呢?

三、javascript是如何调用native的?

javascript调用native的方式有2种:注入API 和 拦截URL SCHEME

1)注入API :向JavaScript的window注入native的方法,让javascript可以直接调用原生native的的逻辑,达到 JavaScript 调用 Native 的目的。

在java中注册一个处理函数,让js可以调用它

webView.registerHandler("submitFromWeb", new BridgeHandler() {
        @Override
        public void handler(String data, CallBackFunction function) {
            Log.i(TAG, "handler = submitFromWeb, data from web = " + data);
            function.onCallBack("submitFromWeb exe, response data from Java");
        }
    });

在js中调用这个事件 :WebViewJavascriptBridge是native为web视图创建的javascript的桥,而实例化的一个对象

 

WebViewJavascriptBridge.callHandler(  
        'submitFromWeb'
        , {'param': str1}
        , function(responseData) {
            document.getElementById("show").innerHTML = "send get responseData from java, data = " + responseData
        }
    );

 2)拦截URL SCHEME

URL SCHEME 是一种类似于url的链接,为了方便app之间直接互相调用设计

拦截 URL SCHEME 的主要流程是:Web 端通过某种方式(例如 iframe.src)发送 URL Scheme 请求,之后 Native 拦截到请求并根据 URL SCHEME(包括所带的参数)进行相关操作。

正常的网络请求可能是: https://img.lifecdn.com/tps/123.png
我们可以自定义协议,改成jsbridge://methodName?param1=value1&param2=value2
Native拦截jsbridge开头的网络请求,做出对应的动作。
最常见的做法就是创建一个隐藏的iframe来实现通信。

在实现过程中,这种方式有一定的缺陷:使用 iframe.src 发送 URL SCHEME 会有 url 长度的隐患。

缺点:创建请求,需要一定的耗时,比注入 API 的方式调用同样的功能,耗时会较长

四、native调用javascript的方法

native端调用js的方法:需要js在WebViewJavascriptBridge上注册一个js事件,然后java可以通过事件名来调用这个事件;

registerHandler在Native端定义(是JSBridge对象的一个方法),由前端来注册,js注册了事件之后,native端就可以来调用

native调用主动调用js有2种情况:一种native主动触发前端注册的事件,通知前端页面的状态变化;另一种是前端调用native的回调

    WebViewJavascriptBridge.registerHandler("functionInJs", function(data, responseCallback) {
        document.getElementById("show").innerHTML = ("data from Java: = " + data);
        var responseData = "Javascript Says Right back aka!";
        responseCallback(responseData);
    });

Java可以通过以下方式调用这个js处理函数“functionInJs”:

webView.callHandler("functionInJs", new Gson().toJson(user), new CallBackFunction() {
        @Override
        public void onCallBack(String data) {

        }
    });

实际项目中使用:

export function setupWebViewJavascriptBridge (callback) {
    if (window.WebViewJavascriptBridge) {
      return callback(window.WebViewJavascriptBridge)
    }
    if (window.WVJBCallbacks) {
      return window.WVJBCallbacks.push(callback)
    }
    window.WVJBCallbacks = [callback]
    var WVJBIframe = document.createElement('iframe')
    WVJBIframe.style.display = 'none'
    WVJBIframe.src = 'wvjbscheme://__BRIDGE_LOADED__'
    document.documentElement.appendChild(WVJBIframe)
    setTimeout(function () {
      document.documentElement.removeChild(WVJBIframe)
    }, 0)
  }
  

js调用:

var js_bridge = require("../../utils/nativejsbridge.js");

var data = {  
          title:'001', 
          desc:'001测试',
          image:'http://img',
          shareUrl: 'http://....'
        };

js_bridge .setupWebViewJavascriptBridge(function(bridge) {
          bridge.callHandler("friend", data, function(  // 这里的bridge就是window.WebViewJavascriptBridge这个对象,然后去调用native 的shareFriend事件,shareData是发送给native的数据,
            data,
            responseCallback
          ) {
            console.log('001')
            });
        });    

 

 

最后附上一些文档,方便查阅:

https://segmentfault.com/a/1190000010356403

https://www.jianshu.com/p/be491bfbca0d

https://blog.csdn.net/yuzhengfei7/article/details/93468914

https://github.com/lzyzsd/JsBridge

https://github.com/marcuswestin/WebViewJavascriptBridge

只是自己对jsbridge的一些浅显的了解,勿喷

 

posted @ 2021-08-10 16:45  程序员瑶琴  阅读(805)  评论(0编辑  收藏  举报