目录一、Hybrid 通信整体概述二、两大通信方向底层原理2.1 原生调用 H5App → H5通信原理H5 基础回调示例两端原生调用 API 对比2.2 H5 调用原生H5 → App2.2.1 AndroidaddJavascriptInterface 对象注入2.2.2 iOSWKScriptMessageHandler 消息通道三、双平台原生完整实现代码3.1 Android Kotlin 端实现3.2 iOS Swift 端实现四、通用跨平台 JSBridge 封装bridge.js4.1 设计思路4.2 完整源码五、业务层实战调用示例main.js原生主动回调 H5 执行语句六、生产环境避坑注意事项七、全文总结一、Hybrid 通信整体概述在混合开发Hybrid App场景中H5 页面嵌入 App WebView 后存在两类核心通信需求H5 主动调用原生唤起相册、定位、支付、弹窗等 App 原生能力原生主动回调 H5原生处理完成业务后将结果数据回传给页面渲染。Android、iOS 两套 WebView 底层通信 API 完全不兼容直接业务层写分支判断会造成大量冗余代码。本文从底层原理出发实现一套屏蔽平台差异、支持 Promise 异步、可直接上生产的通用 JSBridge 方案。二、两大通信方向底层原理2.1 原生调用 H5App → H5通信原理H5 提前在window全局挂载约定名称的回调函数Android /iOS 通过 WebView 提供的evaluateJavascript/evaluateJavaScript动态执行 JS 代码携带业务数据调用全局函数。H5 基础回调示例// 防止页面重复注册覆盖函数 if (!window.nativeCallback) { /** * 原生统一回调入口 * param {string|object} res 原生返回数据 */ window.nativeCallback function (res) { // 兼容 Android JSON字符串 / iOS JS对象两种格式 const data typeof res string ? JSON.parse(res) : res; console.log(接收原生回调数据, data); } }两端原生调用 API 对比平台核心 API调用示例AndroidevaluateJavascriptwebView.evaluateJavascript(window.nativeCallback({\code\:0}), null)iOSevaluateJavaScriptwebView.evaluateJavaScript(window.nativeCallback({\code\:0}))2.2 H5 调用原生H5 → App2.2.1 AndroidaddJavascriptInterface 对象注入原生通过addJavascriptInterface将 Java/Kotlin 对象注入 H5 windowH5 通过window.[注入别名].[方法名]()调用原生逻辑限制参数仅支持字符串H5 必须手动JSON.stringify序列化对象强制要求暴露给 JS 的方法必须添加JavascriptInterface安全注解。2.2.2 iOSWKScriptMessageHandler 消息通道WKWebView 注册WKUserContentController消息处理器H5 使用系统内置固定 APIwindow.webkit.messageHandlers.[名称].postMessage()优势可直接传递 JS 对象无需强制转 JSON 字符串限制仅 WKWebView 支持废弃 UIWebView 无此能力。三、双平台原生完整实现代码3.1 Android Kotlin 端实现import android.webkit.JavascriptInterface import android.webkit.WebView import com.google.gson.Gson class WebBridge(private val webView: WebView) { private val gson Gson() init { // 将原生对象注入windowH5通过 window.NativeBridge 访问 webView.addJavascriptInterface(BridgeObj(), NativeBridge) } inner class BridgeObj { /** * H5调用获取用户信息 * param jsonStr H5传递的JSON字符串参数 */ JavascriptInterface fun getUserInfo(jsonStr: String) { // 解析H5参数 val params gson.fromJson(jsonStr, Map::class.java) println(收到H5请求$params) // 模拟业务逻辑组装返回数据 val result mapOf( code to 0, data to mapOf(name to 张三, userId to 10001) ) val callbackJson gson.toJson(result) // 调用H5全局回调回传数据 webView.evaluateJavascript(window.Bridge.onCallback(cb_get_user, $callbackJson), null) } /** * H5调用弹出Toast提示 */ JavascriptInterface fun showToast(jsonStr: String) { val params gson.fromJson(jsonStr, Map::class.java) val msg params[message] ?: println(Toast提示$msg) } } }3.2 iOS Swift 端实现import WebKit class WebViewController: UIViewController, WKScriptMessageHandler { var webView: WKWebView! override func viewDidLoad() { super.viewDidLoad() let config WKWebViewConfiguration() // 注册消息处理器名称与H5约定 NativeBridge config.userContentController.add(self, name: NativeBridge) webView WKWebView(frame: view.bounds, configuration: config) view.addSubview(webView) } // 接收H5 postMessage 消息统一入口 func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { guard message.name NativeBridge, let payload message.body as? [String: Any], let funcName payload[funcName] as? String else { return } switch funcName { case getUserInfo: let callbackId payload[__callbackId__] as! String let res: [String: Any] [ code: 0, data: [name: 张三, userId: 10001] ] // 回调H5 let jsonData try! JSONSerialization.data(withJSONObject: res) let jsonStr String(data: jsonData, encoding: .utf8)! webView.evaluateJavaScript(window.Bridge.onCallback(\(callbackId), \(jsonStr))) case showToast: guard let msg payload[message] as? String else { return } print(Toast提示\(msg)) default: break } } }四、通用跨平台 JSBridge 封装bridge.js4.1 设计思路使用 IIFE 闭包隔离内部变量不污染全局UA 自动识别 Android /iOS/macOS / Windows / Linux 环境底层统一分发双端通信逻辑业务层无需区分平台基于 CallbackId Promise 实现异步回调解决回调地狱全局缓存回调函数原生回调后自动销毁避免内存泄漏兼容 CommonJS 打包与浏览器直接引入两种使用方式。4.2 完整源码/** * 跨平台通用 JSBridge 通信模块 * 兼容 Android / iOS / macOS / Windows / Linux * 能力同步调用、Promise异步回调、环境检测、原生回调分发 */ const Bridge (() { // 1. 识别当前运行系统 const detectOS () { const ua navigator.userAgent.toLowerCase(); const platform navigator.platform.toLowerCase(); if (/android/i.test(ua)) return android; if (/iphone|ipad|ipod/i.test(ua)) return ios; if (/macintosh|macintel/i.test(platform)) return macos; if (/win32|windows/i.test(platform)) return windows; if (/linux/i.test(platform) !/android/i.test(ua)) return linux; return unknown; }; // 2. 底层分发统一调用原生方法 const _invokeNative (objName, funcName, data) { const os detectOS(); const jsonString typeof data string ? data : JSON.stringify(data); // Android / Windows / Linux 注入对象调用 if ([android, windows, linux].includes(os)) { const nativeObj window[objName]; if (nativeObj typeof nativeObj[funcName] function) { nativeObj[funcName](jsonString); return true; } } // iOS / macOS webkit messageHandler if ([ios, macos].includes(os)) { const handler window.webkit?.messageHandlers?.[objName]; if (handler typeof handler.postMessage function) { handler.postMessage(jsonString); return true; } } console.warn([Bridge Warn] 当前环境${os}不支持 ${objName}.${funcName}); return false; }; // 对外暴露API return { /** * 同步单向调用原生无需返回结果 * param {string} objName 桥接对象名 * param {string} funcName 原生方法名 * param {object|string} data 请求参数 * returns {boolean} 是否成功发起调用 */ invoke(objName, funcName, data {}) { return _invokeNative(objName, funcName, data); }, /** * 异步调用原生Promise 返回业务结果 * param {string} objName * param {string} funcName * param {object} data * param {string} [callbackId] 自定义回调标识不传自动生成 * returns {Promiseany} */ invokeAsync(objName, funcName, data {}, callbackId) { return new Promise((resolve, reject) { // 生成唯一回调ID const payload { ...data, funcName, __callbackId__: callbackId || cb_${Date.now()}_${Math.random().toString(36).slice(2)} }; // 全局缓存Promise回调 window.__bridge_callbacks__ window.__bridge_callbacks__ || {}; window.__bridge_callbacks__[payload.__callbackId__] { resolve, reject }; const invokeSuccess _invokeNative(objName, funcName, payload); if (!invokeSuccess) { delete window.__bridge_callbacks__[payload.__callbackId__]; reject(new Error(Native Bridge 环境不存在)); } }); }, /** * 原生统一回调入口由App主动执行 * param {string} callbackId 异步请求唯一标识 * param {string|object} resultJson 原生返回数据 */ onCallback(callbackId, resultJson) { const cbCache window.__bridge_callbacks__?.[callbackId]; if (!cbCache) return; // 统一格式化返回数据 const result typeof resultJson string ? JSON.parse(resultJson) : resultJson; // 约定协议code0 成功其余失败 if (result.code 0 || result.success) { cbCache.resolve(result.data); } else { cbCache.reject(result); } // 销毁缓存防止内存泄漏 delete window.__bridge_callbacks__[callbackId]; }, /** 获取当前系统标识 */ getOS: detectOS }; })(); // 兼容打包工具导出 if (typeof module ! undefined module.exports) { module.exports Bridge; }五、业务层实战调用示例main.jsimport Bridge from ./bridge.js; // 同步单向调用仅通知原生不需要返回 function showNativeToast() { Bridge.invoke(NativeBridge, showToast, { message: 操作成功, duration: 2000 }); } // Promise 异步调用等待原生返回数据 async function fetchUserInfo() { try { const user await Bridge.invokeAsync( NativeBridge, getUserInfo, {}, cb_get_user ); console.log(获取用户信息成功, user); } catch (err) { console.error(获取用户信息失败, err); } } // 平台差异化UI适配 function adaptSafeArea() { if (Bridge.getOS() ios) { // iPhone底部小黑条安全区适配 document.body.style.paddingBottom 34px; } } // 页面初始化执行 document.addEventListener(DOMContentLoaded, () { adaptSafeArea(); showNativeToast(); fetchUserInfo(); });原生主动回调 H5 执行语句App 处理完业务后执行下面 JS 将结果回传给页面 Promise// Android / iOS 统一执行脚本示例 window.Bridge.onCallback(cb_get_user, {code:0,data:{name:张三,userId:10001}})六、生产环境避坑注意事项Android 安全强制注解所有暴露给 JS 的方法必须添加JavascriptInterfaceAndroid 4.2 无注解会直接拦截调用出现无响应。数据格式兼容问题Android 仅支持字符串参数H5 调用原生方法必须JSON.stringifyiOS postMessage 可直接传对象但为双端统一建议全部序列化。回调内存泄漏异步请求回调执行完成后必须删除全局缓存的 resolve/reject页面频繁刷新、多次请求会造成内存堆积。命名强约定H5 与原生的桥对象名、方法名、回调字段__callbackId__必须完全一致大小写敏感。WebView 生命周期页面销毁前清空全局window.__bridge_callbacks__避免页面卸载后原生回调空白页面报错。iOS 废弃 UIWebViewUIWebView 无webkit.messageHandlers通道必须使用 WKWebView。七、全文总结原生调 H5依靠 WebView 执行 JS调用 window 全局挂载的回调函数H5 调原生Android 对象注入、iOS WKWebView 消息通道两套底层 API 完全隔离工程化方案通过 JSBridge 闭包封装屏蔽平台差异对外提供统一invoke/invokeAsync异步闭环CallbackId 映射 Promise 缓存原生通过统一onCallback分发结果替代传统多层回调落地价值一套 JS 代码同时兼容双端业务层无需写大量平台判断可直接投入线上生产。