背景
在移动开发领域,原生应用嵌入网页(H5)可以实现一套代码多端使用,那么原生应用(APP)和网页(H5)之间的通信就非常重要。
JsBridge作为一种实现此类通信的工具,用于实现原生应用和嵌入其中的网页之间的通信。
H5与native交互,本质上来说就两种调用:
- JavaScript 调用 native 方法,
- native 调用 JavaScript 方法。
JavaScript调用native方法有两种方式:
- 注入,native 往 webview 的 window 对象中添加一些原生方法,h5可以通过注入的方法来调用 app 的原生能力
- 拦截,H5通过与 native 之间的协议发送请求,native拦截请求再去调用 app 原生能力
本文主要介绍H5端与App(android和ios)之间通信使用方式。
代码实现
实现步骤:
这段代码实现的是 APP(Android 和 iOS) 和 H5 之间的通信。这个通信过程主要依赖于 WebViewJavascriptBridge 这个桥接库。这里是具体的流程:
-
初始化 WebViewJavascriptBridge 对象:
-
对于 Android,如果 WebViewJavascriptBridge 对象已经存在,则直接使用;如果不存在,则在 'WebViewJavascriptBridgeReady' 事件触发时获取 WebViewJavascriptBridge 对象。
-
对于 iOS,如果 WebViewJavascriptBridge 对象已经存在,直接使用;如果不存在,则创建一个隐藏的 iframe 来触发 WebViewJavascriptBridge 的初始化,并在初始化完成后通过 WVJBCallbacks 回调数组来获取 WebViewJavascriptBridge 对象。
-
-
注册事件:
提供了
callHandler
和registerHandler
两个方法,分别用于在 JS 中调用 APP 端的方法和注册供 APP 端调用的 JS 方法。 -
调用方法:
当 APP 或 JS 需要调用对方的方法时,只需调用
callHandler
或registerHandler
方法即可。
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的互通。
主要通过提供了 callHandler
和 registerHandler
两个方法,分别用于在 JS 中调用 APP 端的方法和注册供 APP 端调用的 JS 方法。