【移动端知识】移动端多 WebView 互访方案:Android、iOS 与鸿蒙实现

移动端多 WebView 互访方案:Android、iOS 与鸿蒙实现

  • [移动端多 WebView 互访方案:Android、iOS 与鸿蒙实现](#移动端多 WebView 互访方案:Android、iOS 与鸿蒙实现)
    • 一、核心架构设计
    • [二、Android 平台实现](#二、Android 平台实现)
      • [1. 基础通信架构](#1. 基础通信架构)
      • [2. 控制器实现](#2. 控制器实现)
      • [3. WebView 安全配置](#3. WebView 安全配置)
    • [三、iOS 平台实现 (Swift)](#三、iOS 平台实现 (Swift))
      • [1. WKWebView 通信桥接](#1. WKWebView 通信桥接)
      • [2. AppDelegate 路由控制](#2. AppDelegate 路由控制)
    • 四、鸿蒙平台实现 (HarmonyOS)
      • [1. WebView 通信桥接](#1. WebView 通信桥接)
      • [2. Ability 控制器实现](#2. Ability 控制器实现)
      • [3. 鸿蒙 WebView 配置](#3. 鸿蒙 WebView 配置)
    • [五、通用 JavaScript 接口](#五、通用 JavaScript 接口)
      • [1. 跨平台通信 SDK](#1. 跨平台通信 SDK)
      • [2. HTML 页面集成](#2. HTML 页面集成)
    • 六、平台差异处理表
    • 七、高级功能实现
      • [1. 双向实时通信](#1. 双向实时通信)
      • [2. 文件传输支持](#2. 文件传输支持)
      • [3. 安全控制措施](#3. 安全控制措施)
    • 八、调试与监控
      • [1. 统一日志系统](#1. 统一日志系统)
      • [2. 性能监控](#2. 性能监控)
    • 九、最佳实践建议
    • 十、完整实现流程图

移动端多 WebView 互访方案:Android、iOS 与鸿蒙实现

一、核心架构设计

平台层 JS调用 消息路由 调用目标 执行JS Android Native Bridge iOS 鸿蒙 WebView A 平台控制器 WebView B WebView B页面

二、Android 平台实现

1. 基础通信架构

java 复制代码
// WebViewBridge.java
public class WebViewBridge {
    private WeakReference<WebView> mWebViewRef;
    private String mBridgeName;
    
    public WebViewBridge(WebView webView, String bridgeName) {
        mWebViewRef = new WeakReference<>(webView);
        mBridgeName = bridgeName;
        webView.addJavascriptInterface(this, bridgeName);
    }
    
    @JavascriptInterface
    public void postMessage(String targetBridge, String message) {
        MainActivity activity = (MainActivity) mWebViewRef.get().getContext();
        activity.routeMessage(targetBridge, message);
    }
    
    public void receiveMessage(String message) {
        WebView webView = mWebViewRef.get();
        if (webView != null) {
            String js = String.format("window.%s.onMessage('%s')", 
                                     mBridgeName, message);
            webView.evaluateJavascript(js, null);
        }
    }
}

2. 控制器实现

java 复制代码
// MainActivity.java
public class MainActivity extends AppCompatActivity {
    private WebView webViewA, webViewB;
    private WebViewBridge bridgeA, bridgeB;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        webViewA = findViewById(R.id.webview_a);
        webViewB = findViewById(R.id.webview_b);
        
        // 初始化桥接
        bridgeA = new WebViewBridge(webViewA, "BridgeA");
        bridgeB = new WebViewBridge(webViewB, "BridgeB");
        
        // 加载HTML
        webViewA.loadUrl("file:///android_asset/webview_a.html");
        webViewB.loadUrl("file:///android_asset/webview_b.html");
    }
    
    // 消息路由方法
    public void routeMessage(String targetBridge, String message) {
        if ("BridgeA".equals(targetBridge)) {
            bridgeA.receiveMessage(message);
        } else if ("BridgeB".equals(targetBridge)) {
            bridgeB.receiveMessage(message);
        }
    }
}

3. WebView 安全配置

java 复制代码
// 启用JavaScript
webView.getSettings().setJavaScriptEnabled(true);

// 防止内存泄漏
webView.setWebViewClient(new WebViewClient());
webView.setWebChromeClient(new WebChromeClient());

// 文件访问权限
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
    webView.getSettings().setAllowFileAccessFromFileURLs(true);
    webView.getSettings().setAllowUniversalAccessFromFileURLs(true);
}

三、iOS 平台实现 (Swift)

1. WKWebView 通信桥接

swift 复制代码
// WebViewBridge.swift
class WebViewBridge: NSObject, WKScriptMessageHandler {
    private weak var webView: WKWebView?
    private let bridgeName: String
    
    init(webView: WKWebView, bridgeName: String) {
        self.webView = webView
        self.bridgeName = bridgeName
        super.init()
        webView.configuration.userContentController.add(self, name: bridgeName)
    }
    
    func userContentController(_ controller: WKUserContentController, 
                              didReceive message: WKScriptMessage) {
        guard let body = message.body as? [String: Any],
              let target = body["target"] as? String,
              let msg = body["message"] as? String else {
            return
        }
        
        if let delegate = UIApplication.shared.delegate as? AppDelegate {
            delegate.routeMessage(target: target, message: msg)
        }
    }
    
    func sendMessage(_ message: String) {
        let js = "window.\(bridgeName).onMessage('\(message)')"
        webView?.evaluateJavaScript(js, completionHandler: nil)
    }
}

2. AppDelegate 路由控制

swift 复制代码
// AppDelegate.swift
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?
    var webViewA: WKWebView!
    var webViewB: WKWebView!
    var bridgeA: WebViewBridge!
    var bridgeB: WebViewBridge!
    
    func application(_ application: UIApplication, 
                   didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        
        // 创建WebView
        webViewA = WKWebView(frame: .zero)
        webViewB = WKWebView(frame: .zero)
        
        // 初始化桥接
        bridgeA = WebViewBridge(webView: webViewA, bridgeName: "BridgeA")
        bridgeB = WebViewBridge(webView: webViewB, bridgeName: "BridgeB")
        
        // 加载HTML
        if let urlA = Bundle.main.url(forResource: "webview_a", withExtension: "html") {
            webViewA.loadFileURL(urlA, allowingReadAccessTo: urlA)
        }
        
        if let urlB = Bundle.main.url(forResource: "webview_b", withExtension: "html") {
            webViewB.loadFileURL(urlB, allowingReadAccessTo: urlB)
        }
        
        return true
    }
    
    // 消息路由
    func routeMessage(target: String, message: String) {
        if target == "BridgeA" {
            bridgeA.sendMessage(message)
        } else if target == "BridgeB" {
            bridgeB.sendMessage(message)
        }
    }
}

四、鸿蒙平台实现 (HarmonyOS)

1. WebView 通信桥接

java 复制代码
// HarmonyBridge.java
public class HarmonyBridge {
    private WebView webView;
    private String bridgeName;
    private Context context;
    
    public HarmonyBridge(Context context, WebView webView, String bridgeName) {
        this.context = context;
        this.webView = webView;
        this.bridgeName = bridgeName;
        this.webView.addJsInterface(this, bridgeName);
    }
    
    @JSFunction
    public void postMessage(String targetBridge, String message) {
        // 获取主Ability
        MainAbility mainAbility = (MainAbility) context;
        mainAbility.routeMessage(targetBridge, message);
    }
    
    public void receiveMessage(String message) {
        String js = "window." + bridgeName + ".onMessage('" + message + "')";
        webView.executeJs(js);
    }
}

2. Ability 控制器实现

java 复制代码
// MainAbility.java
public class MainAbility extends Ability {
    private WebView webViewA;
    private WebView webViewB;
    private HarmonyBridge bridgeA;
    private HarmonyBridge bridgeB;
    
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        DirectionalLayout layout = new DirectionalLayout(this);
        
        // 创建WebViewA
        webViewA = new WebView(this);
        webViewA.setWidth(ComponentContainer.LayoutConfig.MATCH_PARENT);
        webViewA.setHeight(ComponentContainer.LayoutConfig.MATCH_CONTENT);
        webViewA.setWeight(1);
        webViewA.load("file:///assets/webview_a.html");
        
        // 创建WebViewB
        webViewB = new WebView(this);
        webViewB.setWidth(ComponentContainer.LayoutConfig.MATCH_PARENT);
        webViewB.setHeight(ComponentContainer.LayoutConfig.MATCH_CONTENT);
        webViewB.setWeight(1);
        webViewB.load("file:///assets/webview_b.html");
        
        // 初始化桥接
        bridgeA = new HarmonyBridge(this, webViewA, "BridgeA");
        bridgeB = new HarmonyBridge(this, webViewB, "BridgeB");
        
        // 添加到布局
        layout.addComponent(webViewA);
        layout.addComponent(webViewB);
        setUIContent(layout);
    }
    
    // 消息路由
    public void routeMessage(String targetBridge, String message) {
        if ("BridgeA".equals(targetBridge)) {
            bridgeA.receiveMessage(message);
        } else if ("BridgeB".equals(targetBridge)) {
            bridgeB.receiveMessage(message);
        }
    }
}

3. 鸿蒙 WebView 配置

java 复制代码
// 启用JavaScript
WebConfig webConfig = webView.getWebConfig();
webConfig.setJavaScriptPermit(true);

// 设置WebView代理
webView.setWebAgent(new WebAgent() {
    @Override
    public boolean onPageStart(WebView webView, String url) {
        // 页面开始加载处理
        return true;
    }
});

五、通用 JavaScript 接口

1. 跨平台通信 SDK

javascript 复制代码
// bridge-sdk.js
class CrossWebViewBridge {
    constructor(bridgeName) {
        this.bridgeName = bridgeName;
        this.messageHandlers = {};
    }
    
    postMessage(targetBridge, message) {
        // Android
        if (window.AndroidBridge) {
            window.AndroidBridge.postMessage(targetBridge, message);
        }
        // iOS
        else if (window.webkit && window.webkit.messageHandlers[this.bridgeName]) {
            window.webkit.messageHandlers[this.bridgeName].postMessage({
                target: targetBridge,
                message: message
            });
        }
        // HarmonyOS
        else if (window.HarmonyBridge) {
            window.HarmonyBridge.postMessage(targetBridge, message);
        }
    }
    
    onMessage(handler) {
        this.messageHandlers['default'] = handler;
    }
    
    // 供原生调用的方法
    __onNativeMessage(message) {
        if (this.messageHandlers['default']) {
            this.messageHandlersmessage;
        }
    }
}

// 初始化
window.BridgeA = new CrossWebViewBridge('BridgeA');
window.BridgeB = new CrossWebViewBridge('BridgeB');

2. HTML 页面集成

html 复制代码
<!-- webview_a.html -->
<!DOCTYPE html>
<html>
<head>
    <title>WebView A</title>
    <script src="bridge-sdk.js"></script>
</head>
<body>
    <button onclick="sendMessage()">发送消息到WebView B</button>
    
    <script>
        // 初始化桥接
        const bridgeA = new CrossWebViewBridge('BridgeA');
        
        // 注册消息处理器
        bridgeA.onMessage(function(message) {
            console.log('WebViewA收到消息:', message);
            document.getElementById('output').innerText = message;
        });
        
        // 发送消息
        function sendMessage() {
            bridgeA.postMessage('BridgeB', 'Hello from WebView A');
        }
    </script>
    
    <div id="output"></div>
</body>
</html>

六、平台差异处理表

功能 Android iOS 鸿蒙 解决方案
JS接口注入 addJavascriptInterface WKUserContentController addJsInterface 统一桥接SDK
JS执行方式 evaluateJavascript evaluateJavaScript executeJs 封装原生方法
文件访问 需权限配置 沙盒限制 资源目录访问 使用相对路径
内存管理 WeakReference weak var 自动回收 弱引用处理
后台通信 Service支持 后台限制 ServiceAbility 消息队列缓存

七、高级功能实现

1. 双向实时通信

javascript 复制代码
// 在WebView A中
bridgeA.onMessage(function(message) {
    console.log('实时消息:', message);
    // 立即回复
    bridgeA.postMessage('BridgeB', '收到消息');
});

// 在WebView B中
setInterval(() => {
    bridgeB.postMessage('BridgeA', `心跳 ${Date.now()}`);
}, 5000);

2. 文件传输支持

java 复制代码
// Android 文件传输
@JavascriptInterface
public void sendFile(String base64Data, String fileName) {
    byte[] data = Base64.decode(base64Data, Base64.DEFAULT);
    // 保存文件
    File file = new File(getFilesDir(), fileName);
    try (FileOutputStream fos = new FileOutputStream(file)) {
        fos.write(data);
    }
    
    // 通知目标WebView
    String message = "file://" + file.getAbsolutePath();
    routeMessage("BridgeB", message);
}

3. 安全控制措施

java 复制代码
// Android 源验证
private boolean isValidOrigin(String origin) {
    return Arrays.asList(
        "file:///android_asset/", 
        "https://trusted-domain.com"
    ).contains(origin);
}

// 在WebViewClient中
@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
    if (!isValidOrigin(request.getUrl().toString())) {
        return true; // 阻止加载
    }
    return false;
}

八、调试与监控

1. 统一日志系统

javascript 复制代码
class BridgeLogger {
    constructor(bridgeName) {
        this.bridgeName = bridgeName;
    }
    
    log(message, level = 'info') {
        // 发送日志到原生
        const payload = {
            type: 'log',
            level: level,
            message: message
        };
        this.bridge.postMessage('Logger', JSON.stringify(payload));
    }
}

// 集成到SDK
CrossWebViewBridge.prototype.log = function(message) {
    this.logger.log(message);
};

2. 性能监控

java 复制代码
// Android 性能监控
private void startPerformanceMonitoring() {
    new Timer().scheduleAtFixedRate(new TimerTask() {
        @Override
        public void run() {
            Debug.MemoryInfo memoryInfo = new Debug.MemoryInfo();
            Debug.getMemoryInfo(memoryInfo);
            
            long totalMemory = memoryInfo.getTotalPss();
            int cpuUsage = getCpuUsage();
            
            String message = String.format(
                "{\"memory\":%d,\"cpu\":%d}", 
                totalMemory, cpuUsage
            );
            
            bridgeA.postMessage("Monitor", message);
        }
    }, 0, 5000); // 每5秒监控一次
}

九、最佳实践建议

  1. 消息协议标准化

    json 复制代码
    {
      "version": "1.0",
      "id": "uuid",
      "timestamp": 1685091200,
      "source": "BridgeA",
      "target": "BridgeB",
      "type": "text/json/file",
      "payload": {}
    }
  2. 错误处理机制

    javascript 复制代码
    try {
      bridgeA.postMessage("BridgeB", largeData);
    } catch (e) {
      if (e.message.includes("Message too long")) {
        // 分片发送
        sendInChunks(largeData);
      }
    }
  3. 心跳保活

    java 复制代码
    // Android心跳服务
    public class HeartbeatService extends Service {
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            new Thread(() -> {
                while (true) {
                    if (webViewA != null) {
                        webViewA.post(() -> 
                            webViewA.evaluateJavascript("BridgeA.ping()", null)
                        );
                    }
                    Thread.sleep(30000);
                }
            }).start();
            return START_STICKY;
        }
    }

十、完整实现流程图

WebView A Native Bridge Platform Router WebView B postMessage(target, data) 路由请求 调用目标bridge 执行onMessage (可选)回复消息 WebView A Native Bridge Platform Router WebView B

通过以上方案,可在Android、iOS和鸿蒙平台上实现高效稳定的WebView间通信。关键点在于:

  1. 使用标准化通信协议
  2. 统一JavaScript接口
  3. 平台特定桥接实现
  4. 完善的安全控制
  5. 性能优化措施

实际部署时建议:

  • 在小流量环境验证
  • 逐步完善错误处理
  • 添加详细日志监控
  • 定期进行安全审计
相关推荐
咕噜签名分发冰淇淋36 分钟前
苹果ios系统IPA包企业签名手机下载应用可以有几种方式可以下载到手机?
ios·智能手机
技术与健康43 分钟前
【Android代码】绘本翻页时通过AI识别,自动通过手机/pad朗读绘本
android·人工智能·智能手机
娅娅梨2 小时前
HarmonyOS-ArkUI Web控件基础铺垫4--TCP协议- 断联-四次挥手解析
网络协议·tcp/ip·http·okhttp·harmonyos·arkui·arkweb
Kiri霧3 小时前
Kotlin集合分组
android·java·前端·kotlin
l软件定制开发工作室5 小时前
基于Android的旅游计划App
android
apihz5 小时前
全球天气预报5天(经纬度版)免费API接口教程
android·服务器·开发语言·c#·腾讯云
~央千澈~5 小时前
FastAdmin后台登录地址变更原理与手动修改方法-后台入口机制原理解析-优雅草卓伊凡
android·admin入口机制
你过来啊你6 小时前
Android性能优化之包体积优化
android