Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >JSBridge 原理

JSBridge 原理

作者头像
全栈程序员站长
发布于 2022-11-15 03:42:15
发布于 2022-11-15 03:42:15
2.3K00
代码可运行
举报
运行总次数:0
代码可运行

大家好,又见面了,我是你们的朋友全栈君。

JSBridge 的起源

近些年,移动端普及化越来越高,开发过程中选用 Native 还是 H5 一直是热门话题。Native 和 H5 都有着各自的优缺点,为了满足业务的需要,公司实际项目的开发过程中往往会融合两者进行 Hybrid 开发。Native 和 H5 分处两地,看起来无法联系,那么如何才能让双方协同实现功能呢?

这时我们想到了 Cordova ,Cordova 提供了一组与设备相关的 API ,是早期 JS 调用原生代码来实现原生功能的常用方案。不过 JSBridge 真正在国内广泛应用是由于移动互联网的盛行。

JSBridge 是一种 JS 实现的 Bridge,连接着桥两端的 Native 和 H5。它在 APP 内方便地让 Native 调用 JS,JS 调用 Native ,是双向通信的通道。JSBridge 主要提供了 JS 调用 Native 代码的能力,实现原生功能如查看本地相册、打开摄像头、指纹支付等。

H5 与 Native 对比

name

H5

Native

稳定性

调用系统浏览器内核,稳定性较差

使用原生内核,更加稳定

灵活性

版本迭代快,上线灵活

迭代慢,需要应用商店审核,上线速度受限制

受网速 影响

较大

较小

流畅度

有时加载慢,给用户“卡顿”的感觉

加载速度快,更加流畅

用户体验

功能受浏览器限制,体验有时较差

原生系统 api 丰富,能实现的功能较多,体验较好

可移植性

兼容跨平台跨系统,如 PC 与 移动端,iOS 与 Android

可移植性较低,对于 iOS 和 Android 需要维护两套代码

JSBridge 的双向通信原理

JS 调用 Native

JS 调用 Native 的实现方式较多,主要有拦截 URL Scheme 、重写 prompt 、注入 API 等方法。

拦截 URL Scheme

AndroidiOS 都可以通过拦截 URL Scheme 并解析 Scheme 来决定是否进行对应的 Native 代码逻辑处理。

Android 的话,Webview 提供了 shouldOverrideUrlLoading 方法来提供给 Native 拦截 H5 发送的 URL Scheme 请求。代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class CustomWebViewClient extends WebViewClient {
  @Override
  public boolean shouldOverrideUrlLoading(WebView view, String url) {
    ......
    // 场景一: 拦截请求、接收 scheme
    if (url.equals("xxx")) {

      // handle
      ...
      // callback
      view.loadUrl("javascript:setAllContent(" + json + ");")
      return true;
    }
    return super.shouldOverrideUrlLoading(url);
  }
}

iOS 的 WKWebview 可以根据拦截到的 URL Scheme 和对应的参数执行相关的操作。代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
    if ([navigationAction.request.URL.absoluteString hasPrefix:@"xxx"]) {
        [[UIApplication sharedApplication] openURL:navigationAction.request.URL];
    }
    decisionHandler(WKNavigationActionPolicyAllow);
}

这种方法的优点是不存在漏洞问题、使用灵活,可以实现 H5 和 Native 页面的无缝切换。例如在某一页面需要快速上线的情况下,先开发出 H5 页面。某一链接填写的是 H5 链接,在对应的 Native 页面开发完成前先跳转至 H5 页面,待 Native 页面开发完后再进行拦截,跳转至 Native 页面,此时 H5 的链接无需进行修改。但是使用 iframe.src 来发送 URL Scheme 需要对 URL 的长度作控制,使用复杂,速度较慢。

重写 prompt 等原生 JS 方法

Android 4.2 之前注入对象的接口是 addJavascriptInterface ,但是由于安全原因慢慢不被使用。一般会通过修改浏览器的部分 Window 对象的方法来完成操作。主要是拦截 alert、confirm、prompt、console.log 四个方法,分别被 Webview 的 onJsAlert、onJsConfirm、onConsoleMessage、onJsPrompt 监听。其中 onJsPrompt 监听的代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public boolean onJsPrompt(WebView view, String origin, String message, String   defaultValue, final JsPromptResult result) {
  String handledRet = parentEngine.bridge.promptOnJsPrompt(origin, message,    defaultValue);
  xxx;
  return true;
}

iOS 由于安全机制,WKWebView 对 alert、confirm、prompt 等方法做了拦截,如果通过此方式进行 Native 与 JS 交互,需要实现 WKWebView 的三个 WKUIDelegate 代理方法。代码示例如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
-(void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler{

  UIAlertController *alertController = [UIAlertController     alertControllerWithTitle:nil message:message?:@"" preferredStyle:UIAlertControllerStyleAlert];

  [alertController addAction:([UIAlertAction actionWithTitle:@"确认" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {

      completionHandler();

  }])];

  [self presentViewController:alertController animated:YES completion:nil];

}

使用该方式时,可以与 Android 和 iOS 约定好使用传参的格式,这样 H5 可以无需识别客户端,传入不同参数直接调用 Native 即可。剩下的交给客户端自己去拦截相同的方法,识别相同的参数,进行自己的处理逻辑即可实现多端表现一致。如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
alert("确定xxx?", "取消", "确定", callback());

另外,如果能与 Native 确定好方法名、传参等调用的协议规范,这样其它格式的 prompt 等方法是不会被识别的,能起到隔离的作用。

注入 API

基于 Webview 提供的能力,我们可以向 Window 上注入对象或方法。JS 通过这个对象或方法进行调用时,执行对应的逻辑操作,可以直接调用 Native 的方法。使用该方式时,JS 需要等到 Native 执行完对应的逻辑后才能进行回调里面的操作。

Android 的 Webview 提供了 addJavascriptInterface 方法,支持 Android 4.2 及以上系统。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
gpcWebView.addJavascriptInterface(new JavaScriptInterface(), 'nativeApiBridge'); 
public class JavaScriptInterface {
 Context mContext;

  JavaScriptInterface(Context c) {
    mContext = c;
  }

  public void share(String webMessage){      
    // Native 逻辑
  }
}

JS 调用示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
window.NativeApi.share(xxx);

iOS 的 UIWebview 提供了 JavaScriptScore 方法,支持 iOS 7.0 及以上系统。WKWebview 提供了 window.webkit.messageHandlers 方法,支持 iOS 8.0 及以上系统。UIWebview 在几年前常用,目前已不常见。以下为创建 WKWebViewConfiguration 和 创建 WKWebView 示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
WKPreferences *preferences = [WKPreferences new];
preferences.javaScriptCanOpenWindowsAutomatically = YES;
preferences.minimumFontSize = 40.0;
configuration.preferences = preferences;
    

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [self.webView.configuration.userContentController addScriptMessageHandler:self name:@"share"];
   [self.webView.configuration.userContentController addScriptMessageHandler:self name:@"pickImage"];
}
- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    [self.webView.configuration.userContentController  removeScriptMessageHandlerForName:@"share"];
    [self.webView.configuration.userContentController removeScriptMessageHandlerForName:@"pickImage"];
}

JS 调用示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
window.webkit.messageHandlers.share.postMessage(xxx);

Native 调用 JS

Native 调用 JS 比较简单,只要 H5 将 JS 方法暴露在 Window 上给 Native 调用即可。

Android 中主要有两种方式实现。在 4.4 以前,通过 loadUrl 方法,执行一段 JS 代码来实现。在 4.4 以后,可以使用 evaluateJavascript 方法实现。loadUrl 方法使用起来方便简洁,但是效率低无法获得返回结果且调用的时候会刷新 WebView。evaluateJavascript 方法效率高获取返回值方便,调用时候不刷新WebView,但是只支持 Android 4.4+。相关代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
webView.loadUrl("javascript:" + javaScriptString);
webView.evaluateJavascript(javaScriptString, new ValueCallback<String>() {
  @Override
  public void onReceiveValue(String value){
    xxx
  }
});

iOS 在 WKWebview 中可以通过 evaluateJavaScript:javaScriptString 来实现,支持 iOS 8.0 及以上系统。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// swift
func evaluateJavaScript(_ javaScriptString: String, 
  completionHandler: ((Any?, Error?) -> Void)? = nil)
// javaScriptString 需要调用的 JS 代码
// completionHandler 执行后的回调
// objective-c
[jsContext evaluateJavaScript:@"ZcyJsBridge(ev, data)"]

JSBridge 的使用

  • 如何引用
    • 由 H5 引用 在我司移动端初期版本时采用的是该方式,采用本地引入 npm 包的方式进行调用。这种方式可以确定 JSBridge 是存在的,可直接调用 Native 方法。但是如果后期 Bridge 的实现方式改变,双方需要做更多的兼容,维护成本高
    • 由 Native 注入 这是当前我司移动端选用的方式。在考虑到后期业务需要的情况下,进行了重新设计,选用 Native 注入的方式来引用 JSBridge。这样有利于保持 API 与 Native 的一致性,但是缺点是在 Native 注入的方法和时机都受限,JS 调用 Native 之前需要先判断 JSBridge 是否注入成功
  • 使用规范

H5 调用 Native 方法的伪代码实例,如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
params = {
  api_version: "xxx", // API 版本
  title: "xxx", // 标题
  filename: "xxx", // 文件名称
  image: "xxx", // 图片链接
  url: "xxx", // 网址链接
  success: function (res) {
    xxx; // 调用成功后执行
  },
  fail: function (err) {
    if (err.code == '-2') {
      fail && fail(err); // 调用了当前客户端中不存在的 API 版本
    } else {
      const msg = err.msg; //异常信息
      Toast.fail(msg);
    }
  }
};
window.NativeApi.share(params);

以下简要列出通用方法的抽象,目前基本遵循以下规范进行双端通信。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
window.NativeApi.xxx({
  api_version:'',
  name: "xxx",
  path: "xxx",
  id: "xxx",
  success: function (res) {
    console.log(res);
  },
  fail: function (err) {
    console.log(err);
  }
});

由于初期版本选择了由 H5 本地引用 JSBridge,后期采用 Native 注入的方式。现有的 H5 需要对各种情况做兼容,逻辑抽象如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
reqNativeBridge(vm, fn) {
  if (!isApp()) {
    // 如果不在 APP 内进行调用
    vm.$dialog.alert({
      message: "此功能需要访问 APP 才能使用",
    });
  } else {
    if (!window.NativeApi) {
      // 针对初期版本
      vm.$dialog.alert({
        message: "请更新到最新 APP 使用该功能",
      });
    } else {
      // 此处只针对“调用了当前客户端中不存在的 API 版本”的报错进行处理
      // 其余种类的错误信息交由具体的业务去处理
      fn && fn((err) => {
        vm.$dialog.alert({
          message: "请更新到最新 APP 使用该功能",
        });
      });
    }
  }
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/234399.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年11月2日 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
前端工程师所需要了解的WebView
| 导语 现如今,在做移动端 H5 开发时,少不了与 Native 之间进行交互。而在Native中,H5的承载容器为 WebView,其核心是使用 WebView 控件实现加载 url。
秋风的笔记
2021/03/29
2.3K0
前端工程师所需要了解的WebView
JS Bridge 通信原理
之前介绍了移动端开发的相关技术,这一篇主要是从 Hybrid 开发的 JS Bridge 通信讲起。
尹光耀
2022/03/22
5K0
JS Bridge 通信原理
JSBridge 技术原理分析
PhoneGap(Codova 的前身)作为 Hybrid 鼻祖框架,是一个开源的移动开发框架,允许你用标准的web技术-HTML5,CSS3和JavaScript做跨平台的Hybird WebUI开发,应该是最先被开发者广泛认知的 JSBridge 的应用场景。而对于 JSBridge 的应用在国内真正兴盛起来,则是因为杀手级应用微信的出现。
玄姐谈AGI
2021/11/23
1.9K0
H5和移动端通信
弹窗包括:alert、confirm、prompt, 和url拦截类似都在回调方法中处理
无忧366
2022/10/21
1.4K0
JSBridge深度剖析
概述 做过混合开发的人都知道Ionic和PhoneGap之类的框架,这些框架在web基础上包装一层Native,然后通过Bridge技术的js调用本地的库。 在讲JSBridge技术之前,我们来看一下传统的实现方式。 Android端 Native调JS native调用js比较简单,只要遵循:”javascript: 方法名(‘参数,需要转为字符串’)”的规则即可。 在4.4之前,调用的方式: // mWebView = new WebView(this); mWebView.lo
xiangzhihong
2018/02/06
3.9K0
JSBridge深度剖析
看完就懂的Hybrid框架设计方案
本篇文章探讨“基于 Webview,如何在 App 内实现带离线包能力的 H5”。在当下这个主题似乎有些过时,但 H5 技术以其良好的跨端一致性,长期来看会占据一席之地,希望整理一个较完整的方案,从基本的实现原理到业务具体应用,让不了解的同学对“离线 H5"有一个较完整的视角。
腾讯云开发者
2024/04/12
2.6K0
看完就懂的Hybrid框架设计方案
Hybrid App技术解析 -- 原理篇
引言 随着 Web 技术和移动设备的快速发展,Hybrid 技术已经成为一种最主流最常见的方案。一套好的 Hybrid架构方案 能让 App 既能拥有极致的体验和性能,同时也能拥有 Web技术 灵活的
前端教程
2018/07/27
1.7K0
Hybrid App技术解析 -- 原理篇
WKWebView 那些坑
QQ空间开发团队
2017/08/15
17.6K2
JSBridge小科普
做Hybird APP开发的同学,应该对JSBridge不陌生,它用于H5页面和Native(Android或者iOS)通信。常用的三方库如Dsbridge系列(https://github.com/wendux/DSBridge-Android)。那么,你知道JSBridge到底是如何在两端进行通信的吗?
娜姐
2020/09/22
2.9K0
JSBridge小科普
H5如何与原生App通信?
为了提高开发效率,开发人员往往会使用原生app里面嵌套前端h5页面的快速开发方式,这就要涉及到h5和原生的相互调用,互相传递数据,接下来就实践项目中的交互方式做一个简单的记录分享,废话不多说,直接上正文:
用户9253515
2021/12/17
6.2K0
JSB 原理与实践
我们开发的 h5 页面运行在端上的 WebView 容器之中,很多业务场景下 h5 需要依赖端上提供的信息/能力,这时我们需要一个可以连接原生运行环境和 JS 运行环境的桥梁 。 这个桥梁就是 JSB,JSB 让 Web 端和 Native 端得以实现双向通信。
用户6835371
2021/08/05
1.4K0
技术 | Hybrid载体的变化(一)
时至今日,我都在想“微信小程序”为什么不能做成Web式,而是要去加那么一层隔离,终归其原因,还是随着时间向前走,Hybrid的载体也发生了变化,不然该卡的还是一样卡的一逼。从iOS的角度上来说载体从UIWebView变成了WKWebView,Android有着他们自研的X5当然原生的内核,如果你用着Android7.0也不见得会卡,这才是小程序能出来的根本原因,没有载体,一切都是空谈。
icepy
2019/06/24
9100
oc和js交互_js调用api
UIWebView 在 iOS12 中已经被废弃,同时WKWebView在iOS8中已经出现。所以无特殊情况的话,我们一般应该也是用不到前者了! UIWebView 相比于 WKWebView 的使用上会简单很多。
全栈程序员站长
2022/11/01
67.6K0
深入小程序系列之一:小程序核心原理及模拟
小程序是一种新的移动应用程序格式,是一种依赖 Web 技术,但也集成了原生应用程序功能的混合解决方案。
凡泰极客
2020/03/09
2K0
深入小程序系列之一:小程序核心原理及模拟
JSBridge原理解析—以WebviewJavascriptBridge实现方式为例
JSBridge 是一种 webview 侧和 native 侧进行通信的手段,webview 可以通过 jsb 调用 native 的能力,native 也可以通过 jsb 在 webview 上执行一些逻辑。
zz_jesse
2021/07/12
1.8K0
JSBridge原理解析—以WebviewJavascriptBridge实现方式为例
浅谈Hybrid
随着 Web 技术和移动设备的飞速发展,各种 APP 层出不穷,极速的业务扩展提高了团队对开发效率的要求,这个时候使用 IOS/Andriod 开发一个 APP 似乎成本有点过高了,而 H5 的低成本、高效率、跨平台等特性马上被利用起来形成了一种新的开发模式:Hybrid APP。
前端森林
2020/04/23
7.1K0
浅谈Hybrid
iOS下JS与OC互相调用(六)--WKWebView + WebViewJavascriptBridge
上一篇文章介绍了UIWebView 如何通过WebViewJavascriptBridge 来实现JS 与OC 的互相调用,这一篇来介绍一下WKWebView 又是如何通过WebViewJavascriptBridge 来实现JS 与OC 的互相调用的。WKWebView 下使用WebViewJavascriptBridge与UIWebView 大同小异。主要是示例化的类不一样,一些与webView 相关的API调用不一样罢了。
Haley_Wong
2018/08/22
4.9K0
iOS下JS与OC互相调用(六)--WKWebView + WebViewJavascriptBridge
WebViewJavascriptBridge
Web 页面中的 JS 与 iOS Native 如何交互?JS 和 iOS Native 就好比两块没有交集的大陆,如果想要使它们相互通信就必须要建立一座“桥梁”。
全栈程序员站长
2022/11/19
1.3K0
WebViewJavascriptBridge
WebGL与APP之间的通讯方
WebGL 是在 Web 浏览器环境中运行的 JavaScript API,而“APP”通常指的是原生移动应用(iOS/Android App)或混合应用。WebGL 与 APP 之间的通讯方式,核心在于如何在 Web 环境(WebGL 运行其中)与原生环境之间建立桥梁。
数字孪生开发者
2025/05/23
370
WebGL与APP之间的通讯方
JsBridge实现JavaScript和Java的互相调用
前端网页JavaScript(下文简称Js)和Java互相调用在手机应用中越来越常见,JsBridge是最常用的解决方案。 1. Js调用Java,Java调用Js 在Android开发中,能实现Js调用Java,有4种方法: 1.JavascriptInterface 2.WebViewClient.shouldOverrideUrlLoading() 3.WebChromeClient.onConsoleMessage() 4.WebChromeClient.onJsPrompt() 1.1 Javas
QQ音乐技术团队
2018/01/30
2.5K0
JsBridge实现JavaScript和Java的互相调用
相关推荐
前端工程师所需要了解的WebView
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验