原生与h5的通信机制
**来源:**Notion **原发布时间:**发布日期: 2025-10-15; 创建时间: 2025-10-15 10:56:09.700Z; 最后编辑时间: 2025-10-16 02:22:15.469Z **标签:**Hybrid开发、FE
原文:https://almond-oxygen-ceb.notion.site/h5-28d8b1cc19aa8046b9c9d2288677c43e?pvs=25
我们先来了解一下H5和原生应用之间通信的几种常见方法:
- URLScheme:通过自定义URL协议触发原生功能
- URL参数传递:通过URL查询字符串传递数据
- JSBridge:通过JavaScript接口实现双向通信
- 第三方Hybrid框架:如Cordova、ReactNative等提供的通信机制
- 对内用“JSBridge”,进行深度、复杂的双向沟通。
- 对外用“URLScheme”,作为公开的入口,负责“唤端”(唤起客户端)。

JSBridge
概念和作用
通信桥梁: JSBridge 充当了 Web应用和原生应用之间的通信桥梁。通过 JSBridge,我们可以在 web和原生代码之间进行双向通信,使这两者能够互相调用和传递数据。
原生功能调用: 使用 JSBridge,我们可以在 JavaScript中调用原生应用中的功能。我们可以通过 web来触发原生应用中的特定操作,如打开相机、发送通知、调用硬件设备等。
在Hybrid模式下,H5会需要使用Native的功能,比如打开二维码扫描、调用原生页面、获取用户信息等,同时Native也需要向Web端发送推送、更新状态等。
而JavaScript是运行在单独的 JS Context中(Webview容器)与原生有运行环境的隔离,所以需要有一种机制实现Native端和Web端的双向通信 ,这就是JSBridge:
以JavaScript引擎或Webview容器作为媒介,通过协定协议进行通信,实现Native端和Web端双向通信的一种机制。
通过JSBridge,Web端可以调用Native端的Java接口,同样Native端也可以通过JSBridge调用Web端的JavaScript接口,实现彼此的双向调用。
核心工作原理
JSBridge的核心原理是JavaScript接口注入。
即原生应用将接口注入到WebView的JavaScript环境中,使得H5页面能够直接调用这些接口。
这一过程主要依赖于各平台WebView提供的接口注入能力:
- Android通过
addJavascriptInterface方法注入 - iOS通过
JavaScriptCore框架或WKUserContentController注入
Native -> Web
Android 和 ios各提供了接口方法,来将JS放进解释器中,然后通过解释器来执行这段JS代码。
Android 提供了 evaluateJavascript来执行JS代码,并且可以获取返回值执行回调。
IOS的 WKWebView 也使用 evaluateJavaScript。
Web -> Native
- URL Scheme 拦截 (URL Scheme Interception)
工作原理 :
- **注册 (Registration):**原生App会向操作系统注册一个自己独有的“协议名”,比如
myapp://。这就像在网上注册一个域名一样,http://是大家熟知的协议,而myapp://则是这个App的专属协议. - **触发 (Trigger):**H5页面想要调用原生功能时,并不会真的去调用一个函数,而是尝试发起一个特殊的网络请求,比如改变
iframe的src或者直接window.location.href到一个用这个特殊协议构造的URL。例如:myapp://camera/takePhoto?quality=80 - **拦截 (Interception):**运行H5的
WebView(原生应用里的一个浏览器组件)并不会真的把这个URL当成网页来打开。原生开发者会重写WebView的某个方法(比如安卓的shouldOverrideUrlLoading),这个方法会“捕获”所有H5发出的URL请求. - **解析与执行 (Parse & Execute):**当原生代码捕获到这个请求后,它会检查URL的协议是不是约定好的
myapp://。如果是,它就不会让WebView继续加载,而是自己解析这个URL,比如/camera/takePhoto就对应到相机的拍照功能,?quality=80就是参数。然后原生代码去执行相应的功能。
优缺点:
- **优点:**兼容性好,实现简单直接,是一种非常成熟的方案.
- 缺点:
- **单向通信:**主要是H5向原生发送指令,原生很难将执行结果方便地返回给H5。
- **有长度限制:**URL本身的长度是有限的,不适合传递复杂或大量的数据.
- **性能较差:**创建URL请求再到原生拦截解析,整个链路比直接函数调用要慢.
- JS Bridge 注入JS对象 (JavaScript Injection / JS Bridge)
- 注入 (Injection):
- 当原生App初始化
WebView并加载H5页面时,原生代码会直接向WebView的JavaScript环境中“注入”一个全局的JS对象。比如,注入一个名为myAppBridge的对象到window下。 - 原生app中,会创建一个“联络员”对象
myAppBridge,里面定义了可以给h5调用的各种方法 - 在创建
WebView并加载h5页面之前,原生APP会调用一个系统函数如myWebView.addJavascriptInterface(new WebAppInterface(), "myAppBridge");将myAppBridge注入到即将创建的h5中 - h5一创建好就有联络员
myAppBridge了,可以用这个对象直接调用里面的各种方法了,其实就是调用原生APP的方法了。 - **H5调用 (H5 Call):**H5页面加载后,就可以像调用任何其他本地JS对象一样,直接调用这个被注入的对象上的方法。例如:
window.myAppBridge.takePhoto(
{ quality: 80 },
(result) => { /* 这是回调函数,处理返回结果 */ }
);
- **原生处理 (Native Handling):**这个
myAppBridge对象上的每个方法都与一段原生代码绑定。当H5调用takePhoto时,实际上是触发了与之绑定的原生代码去执行。 - **双向通信与回调 (Bidirectional & Callback):**原生代码执行完任务(比如拍完照),可以再调用H5传递过来的回调函数,将结果(比如图片路径)作为参数传回去。这就轻松地实现了双向通信.
优缺点:
- 优点:
- **双向通信:**H5和原生可以方便地互相调用,传递数据。
- **性能更好:**接近于原生的函数调用,比URL拦截快。
- **功能强大:**支持传递复杂的JS对象和回调函数,没有数据长度限制。
- 缺点:
- 注入时机不确定,H5在调用前需要检查Bridge对象是否已经注入成功.
前者是不是后者的降级?
在不同的场景下,关系有所不同:
- 在App内部:对于需要H5和原生进行频繁或复杂交互的场景,URLScheme可以被看作是JSBridge的一种降级或非常基础的实现方式。实际上,有些早期的JSBridge实现,其底层就是通过URL Scheme来传递命令的. 但现代的JSBridge通常有更高效的实现。
- 从App外部:当H5页面运行在外部浏览器(比如Safari或Chrome)中时,此时没有注入的JSBridge对象。在这种情况下,URLScheme就成了从外部网页唤起App的唯一手段。例如,一个营销网页上的“在App中打开”按钮,点击后就会尝试跳转到一个
myapp://...的链接,来尝试拉起已经安装在手机上的App.如果App没有安装,这个跳转通常会失败,开发者可以设置一个超时逻辑,然后跳转到应用商店.
总结:
| | | | | | | | | | | | | |
因此,说前者是后者的降级是有道理的,尤其是在App内部需要功能丰富的通信时。但从外部唤起App的场景看,URLScheme又扮演着不可或缺的角色。
URL Scheme
外部浏览器与APP的交互。也可以作hybrid交互,比JS低级一点,因为是单向的。
一般来说客户端通信,端内首选JSBridge,如果判定为端外,就降级为urlscheme.
工作原理 (How it Works):
- **注册 (Registration):**原生App会向操作系统注册一个自己独有的“协议名”,比如
myapp://。这就像在网上注册一个域名一样,http://是大家熟知的协议,而myapp://则是这个App的专属协议. - **触发 (Trigger):**H5页面想要调用原生功能时,并不会真的去调用一个函数,而是尝试发起一个特殊的网络请求,比如改变
iframe的src或者直接window.location.href到一个用这个特殊协议构造的URL。例如:myapp://camera/takePhoto?quality=80 - **拦截 (Interception):**运行H5的
WebView(原生应用里的一个浏览器组件)并不会真的把这个URL当成网页来打开。原生开发者会重写WebView的某个方法(比如安卓的shouldOverrideUrlLoading),这个方法会“捕获”所有H5发出的URL请求. - **解析与执行 (Parse & Execute):**当原生代码捕获到这个请求后,它会检查URL的协议是不是约定好的
myapp://。如果是,它就不会让WebView继续加载,而是自己解析这个URL,比如/camera/takePhoto就对应到相机的拍照功能,?quality=80就是参数。然后原生代码去执行相应的功能。
优缺点:
- **优点:**兼容性好,实现简单直接,是一种非常成熟的方案.
- 缺点:
- **单向通信:**主要是H5向原生发送指令,原生很难将执行结果方便地返回给H5。
- **有长度限制:**URL本身的长度是有限的,不适合传递复杂或大量的数据.
- **性能较差:**创建URL请求再到原生拦截解析,整个链路比直接函数调用要慢.