在混合开发(Hybrid App)中,Web 与 Native(Android/iOS)之间的通信是核心需求。常见的三种通信方式是:
- JSBridge(基于
addJavascriptInterface/WKScriptMessageHandler) postMessage+MessageChannel(现代 WebView 通信)- URL Scheme(拦截自定义协议)
下面从 原理、区别、安全性、平台实现 等维度详细对比,并给出 Android 和 iOS 的实现方式。
一、三种方式概览对比
| 特性 | JSBridge | postMessage(MessageChannel) | URL Scheme |
|---|---|---|---|
| 通信方向 | 双向(JS → Native,Native → JS) | 双向(更标准) | 主要 JS → Native |
| 实时性 | 高 | 高(异步消息通道) | 中(依赖页面跳转/iframe) |
| 安全性 | 中(需谨慎暴露接口) | 高(沙箱隔离) | 低(易被中间人劫持) |
| 兼容性 | Android ≥ API 17;iOS ≥ WKWebView | Android ≥ 6.0(API 23);iOS ≥ WKWebView | 全平台支持 |
| 实现复杂度 | 中 | 中高 | 低 |
| 是否推荐 | ✅ 常用(但注意安全) | ✅✅ 推荐(现代方案) | ⚠️ 仅用于简单场景 |
二、详细说明与实现
1. JSBridge(传统桥接)
✅ 原理:
- Android:通过
WebView.addJavascriptInterface()注入 Java 对象。 - iOS:通过
WKWebView.configuration.userContentController.add(_:name:)注册消息处理器。
🔐 安全要求:
- Android 必须加
@JavascriptInterface - iOS 需验证来源(如域名白名单)
📱 Android 实现:
java
编辑
1// Java
2public class Bridge {
3 @JavascriptInterface
4 public void callNative(String data) {
5 // 处理 JS 调用
6 }
7}
8webView.addJavascriptInterface(new Bridge(), "Android");
javascript
编辑
1// JS
2Android.callNative("hello");
🍏 iOS 实现(Swift):
swift
编辑
1// Swift
2class BridgeHandler: NSObject, WKScriptMessageHandler {
3 func userContentController(_ controller: WKUserContentController, didReceive message: WKScriptMessage) {
4 if message.name == "iosBridge" {
5 print("收到 JS 消息:", message.body)
6 }
7 }
8}
9
10let config = WKWebViewConfiguration()
11config.userContentController.add(BridgeHandler(), name: "iosBridge")
12let webView = WKWebView(frame: .zero, configuration: config)
javascript
编辑
1// JS
2window.webkit.messageHandlers.iosBridge.postMessage("hello");
✅ 优点:简单直接,广泛使用
❌ 缺点:Android 旧版本有安全漏洞;iOS 无法直接返回值(需回调)
2. postMessage + MessageChannel(现代通信)
✅ 原理:
利用 HTML5 的 MessageChannel 创建一个双向、异步、隔离的消息通道,Native 作为另一端接收端口。
这是 Chrome 团队推荐的 WebView 通信方式,安全性高。
📱 Android 实现(API ≥ 23):
java
编辑
1webView.evaluateJavascript("(function() {" +
2 "const channel = new MessageChannel();" +
3 "channel.port1.onmessage = function(e) { console.log('Reply:', e.data); };" +
4 "window.nativePort = channel.port2;" +
5 "})()", null);
6
7// Native 发送消息到 JS
8webView.postWebMessage(
9 new WebMessageCompat("Hello from Android", new WebMessagePortCompat[]{port}),
10 Uri.parse("https://your-trusted-domain.com")
11);
注意:需配合
WebMessageListener(AndroidX)或postWebMessage使用。
🍏 iOS 实现(WKWebView):
iOS 的 WKScriptMessageHandler 本身不直接支持 MessageChannel,但可通过 JS 端模拟双向通信,或使用 evaluateJavaScript 返回结果。
目前 Android 对
MessageChannel原生支持更好,iOS 仍以messageHandlers为主。
✅ 优点:安全、标准、支持流式通信
❌ 缺点:兼容性较差(Android < 6.0 不支持)
3. URL Scheme(拦截跳转)
✅ 原理:
JS 通过 location.href = "myapp://action?param=xxx" 触发页面跳转,Native 拦截该 URL 并解析。
📱 Android 实现:
java
编辑
1webView.setWebViewClient(new WebViewClient() {
2 @Override
3 public boolean shouldOverrideUrlLoading(WebView view, String url) {
4 if (url.startsWith("myapp://")) {
5 // 解析参数并处理
6 return true; // 拦截,不加载
7 }
8 return false;
9 }
10});
🍏 iOS 实现:
swift
编辑
1func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
2 if let url = navigationAction.request.url,
3 url.scheme == "myapp" {
4 // 处理自定义协议
5 decisionHandler(.cancel) // 拦截
6 return
7 }
8 decisionHandler(.allow)
9}
💡 技巧:避免页面跳转闪烁
-
使用隐藏的
<iframe>触发:javascript 编辑 1const iframe = document.createElement('iframe'); 2iframe.src = 'myapp://call?data=xxx'; 3iframe.style.display = 'none'; 4document.body.appendChild(iframe); 5setTimeout(() => document.body.removeChild(iframe), 100);
✅ 优点:兼容性极好(所有 WebView 支持)
❌ 缺点:
- 无法直接返回值(需 JS 再调一次)
- URL 长度有限(~2000 字符)
- 安全性差(可能被第三方页面伪造调用)
三、如何选择?
| 场景 | 推荐方案 |
|---|---|
| 现代 App(Android ≥ 6.0,iOS ≥ 9) | ✅ JSBridge + 安全校验 或 postMessage(Android 优先) |
| 需要高安全性(如金融类) | ✅ postMessage + 域名白名单 + HTTPS |
| 兼容老旧设备 | ⚠️ URL Scheme(但需加密参数、校验来源) |
| 频繁双向通信(如聊天、实时数据) | ✅ JSBridge + 回调机制 或 MessageChannel |
| 仅简单通知(如分享、埋点) | ✅ URL Scheme 足够 |
四、最佳实践建议
- 永远启用 HTTPS,防止中间人注入恶意 JS。
- 验证 WebView 加载的域名(白名单),避免第三方页面调用你的 Native 接口。
- 不要在 JSBridge 中暴露敏感操作(如读取文件、获取 token)。
- 对 URL Scheme 参数做签名或加密,防止伪造。
- 优先使用
WKWebView(iOS)和AndroidX WebView(Android) ,避免使用过时的UIWebView或系统 WebView。