全面解析 iOS 和 Android 内嵌 H5 页面通信与交互实现方案

文章目录

  • 前言
  • 一、交互需求
  • 二、ios与H5通信
    • [2.1 H5 调用 iOS 原生方法](#2.1 H5 调用 iOS 原生方法)
      • [H5 调用代码:](#H5 调用代码:)
      • [iOS 原生处理:](#iOS 原生处理:)
    • [2.2 iOS 调用 H5 方法](#2.2 iOS 调用 H5 方法)
      • [iOS 调用 H5 代码:](#iOS 调用 H5 代码:)
  • [三、Android 与 H5 通信](#三、Android 与 H5 通信)
    • [3.1 H5 调用 Android 原生方法](#3.1 H5 调用 Android 原生方法)
      • [H5 调用代码:](#H5 调用代码:)
      • [Android 原生处理:](#Android 原生处理:)
    • [3.2 Android 调用 H5 方法](#3.2 Android 调用 H5 方法)
      • [Android 调用 H5 代码:](#Android 调用 H5 代码:)
  • [四、使用 JSBridge 实现跨平台通信](#四、使用 JSBridge 实现跨平台通信)
    • [4.1 JSBridge 基本结构](#4.1 JSBridge 基本结构)
      • [H5 代码:](#H5 代码:)
      • [H5 处理原生返回的结果:](#H5 处理原生返回的结果:)
      • [iOS 和 Android 原生处理:](#iOS 和 Android 原生处理:)
        • [iOS 中的 JSBridge 实现](#iOS 中的 JSBridge 实现)
        • [iOS 原生处理 JSBridge 请求:](#iOS 原生处理 JSBridge 请求:)
          • [设置 WebView 和 Bridge 接口:](#设置 WebView 和 Bridge 接口:)
        • [Android 中的 JSBridge 实现](#Android 中的 JSBridge 实现)
        • [Android 原生处理 JSBridge 请求:](#Android 原生处理 JSBridge 请求:)
          • [设置 WebView 和 JSBridge 接口:](#设置 WebView 和 JSBridge 接口:)
  • 五、常见应用场景
    • [5.1 登录授权](#5.1 登录授权)
    • [5.2 支付](#5.2 支付)
    • [5.3 获取设备信息](#5.3 获取设备信息)
    • [5.4 文件上传或下载](#5.4 文件上传或下载)
  • 六、总结

前言

随着移动互联网的发展,很多移动应用都会在 App 内嵌 H5 页面,以便于灵活更新内容或通过 Web 技术快速开发某些模块。为了保证 H5 页面与 App 原生功能的紧密结合,H5 页面与 App 之间的通信与交互显得尤为重要。本篇文章将详细介绍 iOS 和 Android 内嵌 H5 页面时,如何实现与原生 App 之间的通信,并通过真实可靠的代码示例进行讲解。


一、交互需求

H5 页面嵌入 App 时,常见的交互需求包括:

•	H5 页面调用原生 App 功能(如摄像头、支付等)。
•	原生 App 调用 H5 页面中的 JavaScript 方法。
•	H5 页面和 App 之间的数据交换。

这些需求在不同平台的实现方式有所不同,本文将分别介绍 iOS 和 Android 平台下的实现方法,以及如何通过 JSBridge 实现跨平台通信。

二、ios与H5通信

在 iOS 中,WKWebView 是用于加载 H5 页面并与之通信的组件。H5 与原生 App 的通信通常通过 window.webkit.messageHandlers 和 evaluateJavaScript 方法进行。

2.1 H5 调用 iOS 原生方法

在 H5 页面中,可以通过 JavaScript 调用 iOS 原生方法,iOS 端通过 WKScriptMessageHandler 接口来处理这些消息。

H5 调用代码:

javascript 复制代码
// 通过 messageHandlers 调用 iOS 原生方法
window.webkit.messageHandlers.nativeHandler.postMessage({
    'action': 'login',
    'data': { username: 'user1', password: 'password123' }
});

iOS 原生处理:

在 iOS 端,我们通过 WKScriptMessageHandler 协议来监听 H5 页面发送的消息:

swift 复制代码
import WebKit

class ViewController: UIViewController, WKScriptMessageHandler {

    // 创建 WKWebView 并设置 message handler
    func setupWebView() {
        let webConfiguration = WKWebViewConfiguration()
        let contentController = WKUserContentController()

        contentController.add(self, name: "nativeHandler")
        webConfiguration.userContentController = contentController

        let webView = WKWebView(frame: self.view.bounds, configuration: webConfiguration)
        self.view.addSubview(webView)

        if let url = URL(string: "https://example.com") {
            webView.load(URLRequest(url: url))
        }
    }

    // 处理 H5 发送的消息
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        if message.name == "nativeHandler", let body = message.body as? [String: Any] {
            if let action = body["action"] as? String, action == "login" {
                let data = body["data"] as? [String: Any]
                print("登录请求数据: \(String(describing: data))")
                // 处理登录逻辑
            }
        }
    }
}

通过 contentController.add(self, name: "nativeHandler"),我们注册了一个消息处理器,名称为 "nativeHandler",用于接收从 H5 发送的消息。

2.2 iOS 调用 H5 方法

iOS 端可以通过 evaluateJavaScript 方法调用 H5 页面上的 JavaScript 方法,并处理 JavaScript 的返回结果。

iOS 调用 H5 代码:

swift 复制代码
// 调用 H5 页面上的 JavaScript 方法
webView.evaluateJavaScript("javascriptFunction('Hello from iOS')") { (result, error) in
    if let result = result {
        print("JS 返回结果: \(result)")
    }
    if let error = error {
        print("JS 执行出错: \(error)")
    }
}

通过 evaluateJavaScript 方法,iOS 可以执行 H5 页面上的 JavaScript 方法,实现与 H5 页面的互动。

三、Android 与 H5 通信

在 Android 平台上,WebView 是内嵌 H5 页面的主要组件,使用 JavascriptInterface 可以实现 H5 与原生 App 之间的通信。

3.1 H5 调用 Android 原生方法

H5 页面可以通过 JavaScript 调用 Android 的原生方法,前提是 Android 端通过 addJavascriptInterface 将 Java 方法暴露给 H5 页面。

H5 调用代码:

javascript 复制代码
// 调用 Android 原生方法
window.Android.showToast("Hello from H5!");

Android 原生处理:

java 复制代码
public class MyWebViewActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_webview);

        WebView webView = findViewById(R.id.webView);
        webView.getSettings().setJavaScriptEnabled(true);
        
        // 添加 JavaScript 接口,将 Java 方法暴露给 H5 页面
        webView.addJavascriptInterface(new WebAppInterface(this), "Android");
        
        // 加载 H5 页面
        webView.loadUrl("https://example.com");
    }

    public class WebAppInterface {
        Context mContext;

        WebAppInterface(Context c) {
            mContext = c;
        }

        // 被 H5 调用的方法
        @JavascriptInterface
        public void showToast(String toast) {
            Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();
        }
    }
}

通过 webView.addJavascriptInterface(new WebAppInterface(this), "Android"),我们将 Java 方法暴露给 H5 页面,并通过 @JavascriptInterface 注解来实现通信。

3.2 Android 调用 H5 方法

Android 原生 App 也可以通过 evaluateJavascript 方法调用 H5 页面上的 JavaScript 方法。

Android 调用 H5 代码:

java 复制代码
// 调用 H5 页面上的 JavaScript 方法
webView.evaluateJavascript("javascriptFunction('Hello from Android')", new ValueCallback<String>() {
    @Override
    public void onReceiveValue(String value) {
        Log.d("WebView", "JS 返回结果: " + value);
    }
});

通过 evaluateJavascript,Android 可以与 H5 页面进行双向交互。

四、使用 JSBridge 实现跨平台通信

为了统一 H5 与原生 App 的通信方式,我们可以使用 JSBridge 这种桥接模式来实现跨平台通信。JSBridge 可以为 H5 和原生提供一套统一的接口,无论是在 Android 还是 iOS,都可以通过相同的调用方式进行通信。

4.1 JSBridge 基本结构

•	H5 页面调用原生方法时,通过 JSBridge 桥接层统一分发消息。
•	原生 App 调用 H5 方法时,也通过 JSBridge 进行分发。

H5 代码:

javascript 复制代码
window.JSBridge.callNative('login', { username: 'user1', password: 'password123' }, function(response) {
    console.log('Response from native:', response);
});

H5 处理原生返回的结果:

javascript 复制代码
window.JSBridge = {
    callNative: function(action, params, callback) {
        // 生成一个全局回调
        window.JSBridge.callback = callback;

        // 向原生发送请求,iOS 和 Android 都会接收到
        if (window.webkit && window.webkit.messageHandlers) {
            // iOS 端调用
            window.webkit.messageHandlers.JSBridge.postMessage({ action, params });
        } else if (window.JSBridge) {
            // Android 端调用
            window.JSBridge[action](JSON.stringify(params));
        }
    },

    // 原生处理完返回结果后,调用该方法
    handleResult: function(result) {
        if (window.JSBridge.callback) {
            window.JSBridge.callback(result);
        }
    }
};

解析代码:

•	callNative:H5 页面通过 JSBridge 调用原生 App 的方法,action 为要执行的动作,params 为传递的参数。
•	handleResult:H5 处理原生 App 返回的结果,并执行回调函数。

iOS 和 Android 原生处理:

在 iOS 和 Android 中分别实现对应的 JSBridge 接口,让原生 App 可以处理 H5 发来的请求,并将结果返回给 H5。

iOS 中的 JSBridge 实现

在 iOS 中,使用 WKWebView 和 evaluateJavaScript 实现 JSBridge 通信,H5 调用原生方法,原生 App 处理并返回结果给 H5。

iOS 原生处理 JSBridge 请求:
设置 WebView 和 Bridge 接口:
swift 复制代码
import WebKit

class ViewController: UIViewController, WKScriptMessageHandler {

    var webView: WKWebView!

    override func viewDidLoad() {
        super.viewDidLoad()

        let configuration = WKWebViewConfiguration()
        let contentController = WKUserContentController()

        // 注册 JSBridge 处理器
        contentController.add(self, name: "JSBridge")
        configuration.userContentController = contentController

        webView = WKWebView(frame: self.view.bounds, configuration: configuration)
        self.view.addSubview(webView)

        if let url = URL(string: "https://example.com") {
            webView.load(URLRequest(url: url))
        }
    }

    // 处理来自 H5 的 JSBridge 请求
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        if message.name == "JSBridge" {
            if let body = message.body as? [String: Any] {
                let action = body["action"] as? String
                let params = body["params"] as? [String: Any]

                // 处理不同的 action
                if action == "login" {
                    // 执行登录逻辑并返回结果给 H5
                    let result = ["status": "success", "token": "abc123"]
                    sendResultToH5(result: result)
                }
            }
        }
    }

    // 通过 JSBridge 返回结果给 H5
    func sendResultToH5(result: [String: Any]) {
        let jsonData = try! JSONSerialization.data(withJSONObject: result, options: [])
        let jsonString = String(data: jsonData, encoding: .utf8)!
        let js = "window.JSBridge.handleResult(\(jsonString))"
        webView.evaluateJavaScript(js, completionHandler: nil)
    }
}

解析代码:

•	contentController.add(self, name: "JSBridge"):注册一个名为 JSBridge 的处理器,用于接收 H5 发来的请求。
•	userContentController(_:didReceive:):处理 H5 发来的消息,解析请求参数,并根据 action 执行不同的逻辑,如登录等。
•	sendResultToH5(result:):将处理结果通过 evaluateJavaScript 返回给 H5 页面。
Android 中的 JSBridge 实现

在 Android 中,使用 JavascriptInterface 和 evaluateJavascript 实现 JSBridge 通信,H5 调用原生方法,Android 端处理并返回结果给 H5。

Android 原生处理 JSBridge 请求:
设置 WebView 和 JSBridge 接口:
java 复制代码
public class MyWebViewActivity extends AppCompatActivity {

    WebView webView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_webview);

        webView = findViewById(R.id.webView);
        webView.getSettings().setJavaScriptEnabled(true);
        webView.addJavascriptInterface(new JSBridge(this), "JSBridge");

        // 加载 H5 页面
        webView.loadUrl("https://example.com");
    }

    public class JSBridge {

        Context context;

        JSBridge(Context context) {
            this.context = context;
        }

        // 处理 H5 的登录请求
        @JavascriptInterface
        public void login(String params) {
            // 解析 H5 传过来的参数
            Log.d("JSBridge", "登录请求参数: " + params);

            // 模拟登录处理逻辑
            String result = "{\"status\":\"success\",\"token\":\"abc123\"}";

            // 返回结果给 H5 页面
            runOnUiThread(() -> webView.evaluateJavascript("window.JSBridge.handleResult(" + result + ")", null));
        }
    }
}

解析代码:

•	addJavascriptInterface(new JSBridge(this), "JSBridge"):将 JSBridge 类的实例注入到 WebView,供 H5 页面通过 window.JSBridge 调用。
•	@JavascriptInterface:标注暴露给 H5 调用的方法(如 login)。
•	evaluateJavascript():执行 JavaScript 代码,将结果返回给 H5 页面。

五、常见应用场景

5.1 登录授权

H5 页面通过 JSBridge 或直接调用 App 的登录接口,获取授权信息并返回给 H5。

5.2 支付

H5 页面发起支付请求,App 端调用原生支付 SDK 完成支付,并将支付结果返回给 H5 页面。

5.3 获取设备信息

H5 页面调用 App 接口获取设备的地理位置、摄像头权限、麦克风权限等信息,App 返回这些信息给 H5 页面。

5.4 文件上传或下载

H5 页面通过调用 App 的原生接口,实现文件上传或下载操作。

六、总结

通过本文的讲解,我们了解了如何在 iOS 和 Android 平台上实现内嵌 H5 页面与原生 App 之间的通信与交互。无论是 iOS 的 messageHandlers,还是 Android 的 JavascriptInterface,都能实现双向通信。为了简化跨平台开发,JSBridge 桥接方案可以提供更为优雅和统一的接口。

当我们需要开发混合应用时,灵活使用这些方法,可以让 H5 页面和 App 原生功能无缝对接,提升开发效率。

相关推荐
王哲晓1 小时前
第三十章 章节练习商品列表组件封装
前端·javascript·vue.js
萌面小侠Plus1 小时前
Android笔记(三十三):封装设备性能级别判断工具——低端机还是高端机
android·性能优化·kotlin·工具类·低端机
慢慢成长的码农1 小时前
Android Profiler 内存分析
android
大风起兮云飞扬丶1 小时前
Android——多线程、线程通信、handler机制
android
理想不理想v1 小时前
‌Vue 3相比Vue 2的主要改进‌?
前端·javascript·vue.js·面试
L72561 小时前
Android的Handler
android
清风徐来辽1 小时前
Android HandlerThread 基础
android
酷酷的阿云1 小时前
不用ECharts!从0到1徒手撸一个Vue3柱状图
前端·javascript·vue.js
aPurpleBerry2 小时前
JS常用数组方法 reduce filter find forEach
javascript
HerayChen2 小时前
HbuildderX运行到手机或模拟器的Android App基座识别不到设备 mac
android·macos·智能手机