APP和H5通信-JsBridge

背景

在移动开发领域,原生应用嵌入网页(H5)可以实现一套代码多端使用,那么原生应用(APP)和网页(H5)之间的通信就非常重要。

JsBridge作为一种实现此类通信的工具,用于实现原生应用和嵌入其中的网页之间的通信。

H5与native交互,本质上来说就两种调用:

  1. JavaScript 调用 native 方法
  2. native 调用 JavaScript 方法

JavaScript调用native方法有两种方式:

  1. 注入,native 往 webview 的 window 对象中添加一些原生方法,h5可以通过注入的方法来调用 app 的原生能力
  2. 拦截,H5通过与 native 之间的协议发送请求,native拦截请求再去调用 app 原生能力

本文主要介绍H5端与App(android和ios)之间通信使用方式。

代码实现

实现步骤:

这段代码实现的是 APP(Android 和 iOS) 和 H5 之间的通信。这个通信过程主要依赖于 WebViewJavascriptBridge 这个桥接库。这里是具体的流程:

  1. 初始化 WebViewJavascriptBridge 对象:

    • 对于 Android,如果 WebViewJavascriptBridge 对象已经存在,则直接使用;如果不存在,则在 'WebViewJavascriptBridgeReady' 事件触发时获取 WebViewJavascriptBridge 对象。

    • 对于 iOS,如果 WebViewJavascriptBridge 对象已经存在,直接使用;如果不存在,则创建一个隐藏的 iframe 来触发 WebViewJavascriptBridge 的初始化,并在初始化完成后通过 WVJBCallbacks 回调数组来获取 WebViewJavascriptBridge 对象。

  2. 注册事件:

    提供了 callHandlerregisterHandler 两个方法,分别用于在 JS 中调用 APP 端的方法和注册供 APP 端调用的 JS 方法。

  3. 调用方法:

    当 APP 或 JS 需要调用对方的方法时,只需调用 callHandlerregisterHandler 方法即可。

js 复制代码
const { userAgent } = navigator;
const isAndroid = userAgent.indexOf('android') > -1; // android终端

/**
 * Android  与安卓交互时:
 *      1、不调用这个函数安卓无法调用 H5 注册的事件函数;
 *      2、但是 H5 可以正常调用安卓注册的事件函数;
 *      3、还必须在 setupWebViewJavascriptBridge 中执行 bridge.init 方法,否则:
 *          ①、安卓依然无法调用 H5 注册的事件函数
 *          ①、H5 正常调用安卓事件函数后的回调函数无法正常执行
 *
 * @param {*} callback
 */
function androidFn(callback) {
  if (window.WebViewJavascriptBridge) {
    callback(window.WebViewJavascriptBridge);
  } else {
    document.addEventListener(
      'WebViewJavascriptBridgeReady',
      () => {
        callback(window.WebViewJavascriptBridge);
      },
      false,
    );
  }
}

/**
 * IOS 与 IOS 交互时,使用这个函数即可,别的操作都不需要执行
 */
function iosFn(callback) {
  if (window.WebViewJavascriptBridge) { return callback(window.WebViewJavascriptBridge); }
  if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback); }
  window.WVJBCallbacks = [callback];
  const WVJBIframe = document.createElement('iframe');
  WVJBIframe.style.display = 'none';
  WVJBIframe.src = 'https://__BRIDGE_LOADED__';
  document.documentElement.appendChild(WVJBIframe);
  setTimeout(() => { document.documentElement.removeChild(WVJBIframe); }, 0);
}

/**
 * 注册 setupWebViewJavascriptBridge 方法
 *  之所以不将上面两个方法融合成一个方法,是因为放在一起,那么就只有 iosFuntion 中相关的方法体生效
 */
const setupWebViewJavascriptBridge = isAndroid ? androidFn : iosFn;

/**
 * 这里如果不做判断是不是安卓,而是直接就执行下面的方法,就会导致
 *      1、IOS 无法调用 H5 这边注册的事件函数
 *      2、H5 可以正常调用 IOS 这边的事件函数,并且 H5 的回调函数可以正常执行
 */
if (isAndroid) {
  /**
     * 与安卓交互时,不调用这个函数会导致:
     *      1、H5 可以正常调用 安卓这边的事件函数,但是无法再调用到 H5 的回调函数
     *
     * 前提 setupWebViewJavascriptBridge 这个函数使用的是 andoirFunction 这个,否则还是会导致上面 1 的现象出现
     */
  setupWebViewJavascriptBridge((bridge) => {
    console.log('打印***bridge', bridge);
    // 注册 H5 界面的默认接收函数(与安卓交互时,不注册这个事件无法接收回调函数)
    bridge.init((message, responseCallback) => {
      responseCallback('JS 初始化');
    });
  });
}

export default {
  // js调APP方法 (参数分别为:app提供的方法名  传给app的数据  回调)
  callHandler(name, params, callback) {
    setupWebViewJavascriptBridge((bridge) => {
      bridge.callHandler(name, params, callback);
    });
  },

  // APP调js方法 (参数分别为:js提供的方法名  回调)
  registerHandler(name, callback) {
    setupWebViewJavascriptBridge((bridge) => {
      bridge.registerHandler(name, (data, responseCallback) => {
        callback(data, responseCallback);
      });
    });
  },
};

使用 JSBridge 总结:

1、跟 IOS 交互的时候,只需要且必须注册 iosFuntion 方法即可,不能在 setupWebViewJavascriptBridge 中执行 bridge.init 方法,否则 IOS 无法调用到 H5 的注册函数;

2、与安卓进行交互的时候

  • 使用 iosFuntion,就可以实现 H5 调用 安卓的注册函数,但是安卓无法调用 H5 的注册函数, 并且 H5 调用安卓成功后的回调函数也无法执行
  • 使用 andoirFunction 并且要在 setupWebViewJavascriptBridge 中执行 bridge.init 方法, 安卓才可以正常调用 H5 的回调函数,并且 H5 调用安卓成功后的回调函数也可以正常执行了

H5使用

h5获取app返回的数据:

js 复制代码
jsBridge.callHandler('getAppUserInfo', { title: '首页' }, (data) => {
    console.log('获取app返回的数据', data);
 });

app获取h5返回的数据:

js 复制代码
 jsBridge.registerHandler('getInfo', (data, responseCallback) => {
    console.log('打印***get app data', data);
    responseCallback('我是返回的数据');
  });

两者都可通信,只要一方使用registerHandler注册了事件,另一方通过callHandler接受数据

总结

主要介绍了原生应用嵌入网页(H5)与APP(android和ios)之间的通信实现方法。

这个通信过程主要依赖于 WebViewJavascriptBridge 这个桥接库。通过在JavaScript中调用native方法和native调用JavaScript方法,实现APP和H5的互通。

主要通过提供了 callHandlerregisterHandler 两个方法,分别用于在 JS 中调用 APP 端的方法和注册供 APP 端调用的 JS 方法。

参考资料:

ios-webview

android-webview

参考案例

相关推荐
L耀早睡7 分钟前
mapreduce打包运行
大数据·前端·spark·mapreduce
HouGISer21 分钟前
副业小程序YUERGS,从开发到变现
前端·小程序
outstanding木槿27 分钟前
react中安装依赖时的问题 【集合】
前端·javascript·react.js·node.js
霸王蟹1 小时前
React中useState中更新是同步的还是异步的?
前端·javascript·笔记·学习·react.js·前端框架
霸王蟹1 小时前
React Hooks 必须在组件最顶层调用的原因解析
前端·javascript·笔记·学习·react.js
专注VB编程开发20年1 小时前
asp.net IHttpHandler 对分块传输编码的支持,IIs web服务器后端技术
服务器·前端·asp.net
爱分享的程序员2 小时前
全栈项目搭建指南:Nuxt.js + Node.js + MongoDB
前端
隐含3 小时前
webpack打包,把png,jpg等文件按照在src目录结构下的存储方式打包出来。解决同一命名的图片资源在打包之后,重复命名的图片就剩下一个图片了。
前端·webpack·node.js
lightYouUp3 小时前
windows系统中下载好node无法使用npm
前端·npm·node.js
Dontla3 小时前
npm cross-env工具包介绍(跨平台环境变量设置工具)
前端·npm·node.js