跨岛奇遇之JSBridge

80 阅读4分钟

下面我将化身“移动端魔法建造师”,用一场跨岛奇遇故事 + 代码实战,带你彻底掌握JSBridge的设计精髓。准备好,我们要出发了!🚀


🌉 第一章:孤岛之谜——为什么需要JSBridge?

剧情:Native岛(Android世界)有强大的超能力(相机📷/GPS📍/文件读写),但造房子(UI开发)慢;Web岛(H5世界)造房子快⛵,却手无缚鸡之力。两岛隔海相望(运行环境隔离),急需合作却无法直接沟通。

技术本质

WebView虽能加载H5,但JS与Java运行在独立沙箱中,就像两个语言不通的国家。JSBridge就是这座双向通信的魔法桥


🛠️ 第二章:造桥三法——JS如何呼叫Native?

剧情:Web岛居民想调用Native岛的摄像头,工程师们提出三种建桥方案:

方案1:空投补给包(注入API)

Native岛空投一个名为NativeBridge的魔法包裹到Web岛:

java

// Android工程师建造"补给包"
webView.addJavascriptInterface(new Object() {
    @JavascriptInterface  // 安全封印!
    public void openCamera(String type) {
        if ("front".equals(type) || "back".equals(type)) {
            startCamera(type); // 启动相机
        }
    }
}, "NativeBridge"); // 包裹名

javascript

// Web岛居民拆包即用
window.NativeBridge.openCamera("back");

✅ 优势:速度最快(直接调用)
⚠️ 风险:Android 4.2以下有安全漏洞,必须用@JavascriptInterface标记安全方法。


方案2:漂流瓶传信(拦截URL Scheme)  

Web岛写需求塞入漂流瓶(特殊URL),投入大海🌊:

javascript

// 扔出漂流瓶(iframe保证连续发送不丢失)
const iframe = document.createElement('iframe');
iframe.src = "jsbridge://openCamera?type=back&callbackId=123";
document.body.appendChild(iframe);

java

// Native岛海关拦截
public boolean shouldOverrideUrlLoading(WebView view, String url) {
    if (url.startsWith("jsbridge://")) {
        parseCommand(url); // 解析指令
        return true; // 拦截成功!
    }
    return false;
}

❌ 缺陷:瓶子可能丢失(URL长度限制)、速度慢。


方案3:信鸽快递(拦截prompt)  

Web岛训练信鸽(prompt)携带加密指令:

javascript

// 派出信鸽(JSON避免长度限制)
const cmd = {method: "openCamera", args: "back"};
prompt(JSON.stringify(cmd)); 

java

// Native岛信鸽接收站
public boolean onJsPrompt(WebView view, String msg) {
    if (msg.startsWith("{")) handleCommand(msg); // 解析指令
    return true; // 阻止默认弹窗
}

💡 适用场景:Android 4.2以下的兼容方案8。

🔥 方案选择铁律

deepseek_mermaid_20250626_f7ff59.png


📨 第三章:逆向通信——Native如何呼叫JS?

剧情:Native岛扫描完二维码,需用“无人机投递”将结果送回Web岛:

java

// Android派无人机(异步获取返回值)
webView.evaluateJavascript(
    "javascript:onScanSuccess('QR_Code_Result')", 
    new ValueCallback<String>() {
        @Override
        public void onReceiveValue(String value) {
            // 处理JS返回的数据
        }
    }
);

⚠️ 旧版兼容

java

// Android 4.4以下用loadUrl(无返回值)
webView.loadUrl("javascript:onScanSuccess('QR_Code_Result')");

📜 第四章:通信协议设计——解决三大核心问题

问题1:如何避免消息混乱?  → 协议统一

json

// 请求协议
{
  "method": "pay",          // 指令名
  "callbackId": "K38x7",    // 唯一回调ID
  "data": {"amount": 100}   // 参数
}

// 响应协议
{
  "responseId": "K38x7",    // 关联请求
  "data": {"success": true} // 结果
}

问题2:如何管理回调?  → 回调映射表 

javascript

// Web岛的回调管理局
const callbacks = {};
let id = 0;

function callNative(method, data, callback) {
    const callbackId = `cb_${id++}`;
    callbacks[callbackId] = callback; // 存回调地址
    send({ method, data, callbackId }); // 发送指令
}

// Native完成任务后回信
window.onNativeResult = (responseId, data) => {
    callbacks[responseId](data); // 找到回调执行
    delete callbacks[responseId]; // 清理内存
};

问题3:Web未加载完怎么办?  → 消息队列 

java

// Android端消息队列
List<Message> pendingMessages = new ArrayList<>();

void dispatchMessage(Message m) {
    if (webViewLoaded) {
        webView.evaluateJavascript(convertToJs(m));
    } else {
        pendingMessages.add(m); // 先存起来!
    }
}

🛡️ 第五章:桥梁加固——安全防御指南

攻击剧情:海盗(恶意脚本)试图伪造指令!

防御工事

  1. 白名单管控:仅允许@JavascriptInterface标记的方法被调用1
  2. 参数核验:Native端严格检查参数类型和范围

java

@JavascriptInterface
public void transferMoney(String account, double amount) {
    if (!isValidAccount(account) || amount <= 0) {
        return; // 非法请求拒收!
    }
    // 执行转账
}

3. 权限最小化:关闭WebView不必要的存储/定位权限7


🚀 第六章:跨岛协同——实战支付流程

完整剧情:Web岛发起支付 → Native岛调起支付宝 → 结果回传6

javascript

// Web岛发起支付
callNative("alipay", {orderId: "2025xxx"}, (result) => {
    if (result.success) showToast("支付成功!");
});

java

// Native岛处理支付
@JavascriptInterface
public void alipay(String json) {
    PaymentData data = parseJson(json);
    Alipay.execute(data, new PaymentCallback() {
        @Override
        public void onResult(boolean success) {
            String js = String.format("window.onPayResult('%s')", success);
            webView.evaluateJavascript(js); // 结果回传Web
        }
    });
}

💎 终章:桥梁的终极意义——为什么Hybrid永不落幕?

JSBridge不是一座冰冷的桥,而是效率与体验的平衡艺术

  • 开发速度:H5快速迭代页面 + 原生提供能力支持
  • 动态更新:紧急Bug修复无需发版(替换H5资源)
  • 体验升级:相比纯WebAPP,可调用硬件获得原生体验

🌈 未来之桥:小程序/React Native底层仍在复用JSBridge思想,掌握它等于握住了跨端开发的万能钥匙🔑


附录:造桥工程师速查手册 🧰

技术点最佳方案备选方案核心原理
JS调Native注入API (Android 4.2+)拦截prompt (兼容旧版)对象注入/消息拦截
Native调JSevaluateJavascript (4.4+)loadUrl (兼容旧版)JS代码执行
回调管理唯一ID + 回调映射表JSONP模式回调函数存储
消息队列消息缓存+页面加载后分发延时重发异步任务调度