JSBridge定义

  1. 定义:正如其命名一样,JSBridge就相当于jsnative之间进行全双工通信的一座桥梁,其内部定义了一套用于jsnative进行通信的规范(包括协议、方法、传参及回调等);
  2. 用途:JSBridge可以桥连jsnative的通信,从而使基于容器的web开发和优化成为可能,如比较火的hybrid app技术;能够提升页面性能,丰富页面功能等;

JSBridge原理简析6+

  1. 框架简析:
    JSBridge框架其实主要由两部分组成:第一部分是Native调用js,主要用于消息推送、状态同步及回溯调用结果等;第二部分是js调用Native,主要用于调用系统api、事件监听及状态同步等;

  2. Native调用js

    1. Android
      Android有两种方式:4.4.0以前使用方法loadUrl——调用方便,无法获取回调结果,会刷新webview;4.4.0+使用方法evaluateScript提供更加高效完善的功能——可以获取返回值并且不刷新webview;
      需要注意的是,这里可调用的方法是全局方法;

      # loadUrl
      mWebView.loadUrl("javascript: methodName(paramStr)");# evaluateScript
      mWebView.evaluateScript("javascript: method(paramStr)", new ValueCallback<String>() {@overridepublic void onReceiveValue() {// do something after receive js callback value}
      }
      
    2. IOS
      # UIWebView
      mWebView.stringByEvaluatingJavaScriptFromString("methodName(paramStr)");#WKWebView
      mWebView.evaluateScript("methodName(paramStr)");
      
  3. js调用Native

    1. url schema拦截
      h5native约定一套通信协议作为通信基础,一般如下:
      schema://methodName?params=xxx&cb=xxx;
      其中schema为双方协商的协议名,methodName为js调用native的方法名,params为参数集字符串,cb为接收回调结果的js方法名;在h5中发起请求时,一般通过构建一个不可见的iframe发起请求;请求以约定的方式以url形式发送,native会拦截h5的所有请求(如进行长连接优化等),如果发现url中的协议名是约定的协议名(如jsbridge),则会解析其中的methodNameparamscb等信息。如下给出了简单实现:

      window.callId = 0;
      const callNative = (method, params = null, cb) => {const paramsObj = {data: params ? JSON.stringify(params) : null,}if (typeof cb === 'function') {const cbName = cb + window.callId++;window[cbName] = cb;paramsObj['cbName'] =  cbName;}// 设定通信url供native拦截const url = `jsbridge://${method}?${JSON.stringify(paramsObj)}`;const iframe = document.createElement('iframe');iframe.src = url;iframe.style.width = 0;iframe.style.height = 0;iframe.frameborder = 0;iframe.style.display = 'none';document.body.appendChild(iframe);setTimeout(() => {iframe.parentNode.removeChild(iframe);}, 100);
      }
      

      缺点:消息传输通过url传输,因此传输数据长度受到限制;

    2. promptalertconfirm拦截
      一般通过prompt进行通信,其他实现与url schema拦截类似;native收到prompt事件后会通过onJsPrompt等类似事件对prompt做处理,从而获取js传入的methodparamscb等;

      function callNative(method, params, cb) {...const url = `jsbridge://${method}?${JSON.stringify(paramsObj)}`;prompt(url);
      }
      

      缺点:iosUIWebkit不支持;

    3. 注入JS上下文
      这种方法一般是将需要供js调用的native方法通过实例对象的方式通过webview提供的方法注入到js全局上下文,这样位于webview内的h5页面中js可以直接调用native的实例方法;
      注入方式:Android的webview通过addJ avascriptInterfaceios UIWebview通过JSContextios WKWebview通过scriptMessageHandler
      下面是来自文献2的Android客户端关于注入JS上下文的简单demo;

      首先,声明一个NativeMethods的类,用于定义对外暴露给js调用的方法,格式如methodName(webview, args, cb)
      然后定义一个JSBridge类:其中定义了两个静态方法和一个实例方法;register用于将nativeMethods类下的方法转为hashMap格式,便于查询;call是暴露给js的供js统一调用的方法;
      最后在webview创建后注册对外方法并将JSBridge实例通过addJavascriptInterface注入到JS全局上下文中;

      public class MainActivity extends AppCompatActivity {private WebView mWebView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mWebView = (WebView) findViewById(R.id.mWebView);...// 将 NativeMethods 类下面的提供给 js 的方法转换成 hashMapJSBridge.register("JSBridge", NativeMethods.class);// 将 JSBridge 的实例对象注入到 js 全局上下文中,名字为 _jsbridge,该实例对象下有 call 方法mWebView.addJavascriptInterface(new JSBridge(mWebView), "_jsBridge");}
      }public class NativeMethods {// 用来供 js 调用的方法public static void methodName(WebView view, JSONObject arg, CallBack callBack) {}
      }public class JSBridge {private WebView mWebView;public JSBridge(WebView webView) {this.mWebView = webView;}private  static Map<String, HashMap<String, Method>> exposeMethods = new HashMap<>();// 静态方法,用于将传入的第二个参数的类下面用于提供给 javacript 的接口转成 Map,名字为第一个参数public static void register(String exposeName, Class<?> classz) {...if (!exposeMethods.containsKey(exposeName)) {exposeMethods.put(exposeName, getAllMethod(classz));}}// 实例方法,用于提供给 js 统一调用的方法@JavascriptInterfacepublic String call(String methodName, String args) {...}
      }

      根据上述代码可以看到注入到js全局对象中的实例对象为_jsBridge;在h5中的调用如下:

      window.callId = 0;
      const callNative = (method, params = null, cb) => {const paramsObj = {data: params ? JSON.stringify(params) : null,}if (typeof cb === 'function') {const cbName = cb + window.callId++;window[cbName] = cb;paramsObj['cbName'] =  cbName;}if (window._jsBridge) {window._jsBridge.call(method, JSON.stringify(paramsObj));} else {// 兜底方案const url = `jsbridge://${method}?${JSON.stringify(paramsObj)}`;prompt(url);}

      缺点:安卓4.2以下存在安全漏洞,可能会导致用户信息泄露;

      JSBridge静态方法的call方法实现:

      public static String call(WebView webView, String urlString) {if (!urlString.equals("") && urlString!=null && urlString.startsWith("jsbridge")) {Uri uri = Uri.parse(urlString);String methodName = uri.getHost();try {JSONObject args = new JSONObject(uri.getQuery());JSONObject arg = new JSONObject(args.getString("data"));String cbName = args.getString("cbName");if (exposeMethods.containsKey("JSBridge")) {HashMap<String, Method> methodHashMap = exposeMethods.get("JSBridge");if (methodHashMap!=null && methodHashMap.size()!=0 && methodHashMap.containsKey(methodName)) {Method method = methodHashMap.get(methodName);if (method!=null) {method.invoke(null, webView, arg, new CallBack(webView, cbName));}}}} catch (Exception e) {e.printStackTrace();}}return null;
      }
      

      除此之外,js调用native方法成功需要给h5响应的结果反馈,因此native端需要定义一个Callback类用于处理js调用成功的结果反馈;其本质还是native调用js方法,以下是安卓端使用evaluatecript方法实现的Callback类:

      public class CallBack {private  String cbName;private WebView mWebView;public CallBack(WebView webView, String cbName) {this.cbName = cbName;this.mWebView = webView;}public void apply(JSONObject jsonObject) {if (mWebView!=null) {mWebView.post(() -> {mWebView.evaluateJavascript("javascript:" + cbName + "(" + jsonObject.toString() + ")", new ValueCallback<String>() {@Overridepublic void onReceiveValue(String value) {return;}});});}}
      }
      

JSBridge的引用

  1. h5引用
    h5引用即使用对应的封装好的JSBridgenpm包,内部封装了js调用native方法的方法集;该方式能够保证调用时JSBridge一定存在;缺点是当有变更时,需要nativeh5同时做变更进行兼容;
  2. native注入
    即上边提到的将JSBridge实例对象注入到js全局上下文;该方式有利于保障API与Native的一致性,但是由于注入方法和时机受到限制,h5调用时总是要判断JSBridge实例对象是否存在;

参考文献

  1. JSBridge 深度剖析
  2. 从零开始写一个 JSBridge

JSbridge原理与实现简析相关推荐

  1. ntp如何确认与服务器偏差_NTP时钟同步原理及误差简析

    原标题:NTP时钟同步原理及误差简析 在我们某试验系统方案设计中,由于数据同步性的要求,需要将我们WP4000变频功率分析仪的时钟与客户的NI系统的时钟进行同步,对于WP4000变频功率测试系统而言, ...

  2. NTP时钟服务器原理及误差简析(京准)

    NTP时钟服务器原理及误差简析 1.引言 作为数字通信网的基础支撑技术,时钟同步技术的发展演进始终受到通信网技术发展的驱动.在网络方面,通信网从模拟发展到数字,从TDM网络为主发展到以分组网络为主:在 ...

  3. NTP时钟同步原理及误差简析

    在我们某试验系统方案设计中,由于数据同步性的要求,需要将我们WP4000变频功率分析仪的时钟与客户的NI系统的时钟进行同步,对于WP4000变频功率测试系统而言,多台分析仪之间可通过同步光纤接口达到严 ...

  4. mmap内存 android,Android中mmap原理及应用简析

    mmap是Linux中常用的系统调用API,用途广泛,Android中也有不少地方用到,比如匿名共享内存,Binder机制等.本文简单记录下Android中mmap调用流程及原理.mmap函数原型如下 ...

  5. SIFT特征原理简析(HELU版)

    SIFT(Scale-Invariant Feature Transform)是一种具有尺度不变性和光照不变性的特征描述子,也同时是一套特征提取的理论,首次由D. G. Lowe于2004年以< ...

  6. ceph存储原理_Ceph存储引擎BlueStore简析

    前文我们创建了一个单节点的Ceph集群,并且创建了2个基于BlueStore的OSD.同时,为了便于学习,这两个OSD分别基于不同的布局,也就是一个OSD是基于3中不同的存储介质(这里是模拟的,并非真 ...

  7. Webpack模块化原理简析

    webpack模块化原理简析 1.webpack的核心原理 一切皆模块:在webpack中,css,html.js,静态资源文件等都可以视作模块:便于管理,利于重复利用: 按需加载:进行代码分割,实现 ...

  8. Android Handler与Looper原理简析

    一直感觉自己简直就是一个弱智,最近越来越感觉是这样了,真的希望自己有一天能够认同自己,认同自己. 本文转载于:https://juejin.im/post/59083d7fda2f60005d14ef ...

  9. 基于IdentityServer4的OIDC实现单点登录(SSO)原理简析

     # 写在前面 IdentityServer4的学习断断续续,兜兜转转,走了不少弯路,也花了不少时间.可能是因为没有阅读源码,也没有特别系统的学习资料,相关文章很多园子里的大佬都有涉及,有系列文章 ...

  10. grpc通信原理_gRPC原理简析

    gRPC原理简析 gRPC是由谷歌提出并开发的RPC协议,gRPC提供了一套机制,使得应用程序之间可以进行通信. 降级开发者的使用门槛,屏蔽网络协议,调用对端的接口就像是调用本地的函数一样.而gRPC ...

最新文章

  1. BE镜像还原系统过程
  2. 服务器硬件电路设计书籍,家庭网关硬件接口电路设计大全——电路精选(3)...
  3. WPF数据绑定、多个元素
  4. 计算机与应用教学,教学方法与教学手段
  5. MATLAB-M文件
  6. JSP EL 表达式取request parameter
  7. [设计模式]代理模式
  8. ios 顶部tab滑动实现_iOS开发之多表视图滑动切换示例(仿头条客户端)
  9. 【nyoj - 890】 分东西 (水题 二进制)
  10. java中字母用什么单词赋值_Java初学
  11. M斐波那契数列(HDU-4549)
  12. 常用CSS优化总结——网络性能与语法性能建议
  13. JavaScript 函数 对象 数组
  14. 神经网络ANN分类器及OpenCV实现
  15. 激光技术领域的又一重大突破:光学频率梳
  16. android关于自定义Dialog中布局match_parent 属性 失效的问题
  17. phalapi可以依赖注入么_PhalApi 2.7 开发快速上手
  18. 用python画钢铁侠图片_Photoshop快速把钢铁侠图片转为素描水墨风格教程
  19. 回归预测分析(RANSAC、多项式回归、残差图、随机森林)
  20. 点石互动--kyw之:30步,网站信任度提升200%

热门文章

  1. Lwm2m的server分析
  2. 鸢尾花数据集分类--神经网络
  3. 机器学习常见的优化算法
  4. step 7在win10上安装教程及安装包
  5. oc引导win方法_适配自己的OC引导一键生成Opencore Generation X使用指南
  6. 用注册机破解navicat12
  7. USB加密狗复制USBTrace数据截取工具分享
  8. linux优化ssd磁盘,Ubuntu下针对ssd硬盘优化
  9. 88个塑胶模具设计中常用知识点!
  10. miRNA数据库篇——Rfam数据库