JSBridge是什么?如何使用?
Admin 2021-11-09 群英技术资讯 721 次浏览
这篇文章小编给大家分享的是JSBridge的内容,下文介绍了JSBridge是什么,JSBridge的原理和JSBridge的使用,文中示例介绍的很详细,感兴趣的朋友可以了解看看,下面让我们一起来学习一下吧!
近些年,移动端普及化越来越高,开发过程中选用 Native 还是 H5 一直是热门话题。Native 和 H5 都有着各自的优缺点,为了满足业务的需要,公司实际项目的开发过程中往往会融合两者进行 Hybrid 开发。Native 和 H5 分处两地,看起来无法联系,那么如何才能让双方协同实现功能呢?
这时我们想到了 Codova ,Codova 提供了一组与设备相关的 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 需要维护两套代码 |
JS 调用 Native 的实现方式较多,主要有拦截URL Scheme、重写 prompt 、注入 API 等方法。
拦截 URL Scheme
Android 和 iOS 都可以通过拦截 URL Scheme 并解析 Scheme 来决定是否进行对应的 Native 代码逻辑处理。
Android 的话,Webview提供了shouldOverrideUrlLoading方法来提供给 Native 拦截 H5 发送的URL Scheme请求。代码如下:
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和对应的参数执行相关的操作。代码如下:
- (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 监听的代码如下:
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代理方法。代码示例如下:
-(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 即可。剩下的交给客户端自己去拦截相同的方法,识别相同的参数,进行自己的处理逻辑即可实现多端表现一致。如:
alert("确定xxx?", "取消", "确定", callback());
另外,如果能与 Native 确定好方法名、传参等调用的协议规范,这样其它格式的 prompt 等方法是不会被识别的,能起到隔离的作用。
##### 注入 API
基于Webview提供的能力,我们可以向 Window 上注入对象或方法。JS 通过这个对象或方法进行调用时,执行对应的逻辑操作,可以直接调用 Native 的方法。使用该方式时,JS 需要等到 Native 执行完对应的逻辑后才能进行回调里面的操作。
Android 的Webview提供了 addJavascriptInterface 方法,支持 Android 4.2 及以上系统。
gpcWebView.addJavascriptInterface(new JavaScriptInterface(), 'nativeApiBridge'); public class JavaScriptInterface { Context mContext; JavaScriptInterface(Context c) { mContext = c; } public void share(String webMessage){ // Native 逻辑 } }
JS 调用示例:
window.NativeApi.share(xxx);
iOS 的UIWebview提供了 JavaScriptScore 方法,支持 iOS 7.0 及以上系统。WKWebview提供了 window.webkit.messageHandlers 方法,支持 iOS 8.0 及以上系统。UIWebview在几年前常用,目前已不常见。以下为创建WKWebViewConfiguration和 创建 WKWebView 示例:
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 调用示例:
window.webkit.messageHandlers.share.postMessage(xxx);
Native 调用 JS 比较简单,只要 H5 将 JS 方法暴露在 Window 上给 Native 调用即可。
Android 中主要有两种方式实现。在 4.4 以前,通过 loadUrl 方法,执行一段 JS 代码来实现。在 4.4 以后,可以使用 evaluateJavascript 方法实现。loadUrl 方法使用起来方便简洁,但是效率低无法获得返回结果且调用的时候会刷新 WebView。evaluateJavascript 方法效率高获取返回值方便,调用时候不刷新WebView,但是只支持 Android 4.4+。相关代码如下:
webView.loadUrl("javascript:" + javaScriptString); webView.evaluateJavascript(javaScriptString, new ValueCallback<String>() { @Override public void onReceiveValue(String value){ xxx } });
iOS 在WKWebview中可以通过 evaluateJavaScript:javaScriptString 来实现,支持 iOS 8.0 及以上系统。
// swift func evaluateJavaScript(_ javaScriptString: String, completionHandler: ((Any?, Error?) -> Void)? = nil) // javaScriptString 需要调用的 JS 代码 // completionHandler 执行后的回调 // objective-c [jsContext evaluateJavaScript:@"ZcyJsBridge(ev, data)"]
如何引用
使用规范
H5 调用 Native 方法的伪代码实例,如:
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);
以下简要列出通用方法的抽象,目前基本遵循以下规范进行双端通信。
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 需要对各种情况做兼容,逻辑抽象如下:
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 使用该功能", }); }); } } }
现在大家对于JSBridg是什么以及JSBridg的使用应该都有所了解了,上述示例有一定的借鉴价值,有需要的朋友可以参考学习,希望对大家学习和理解JSBridg有帮助,想要了解更多大家可以关注群英网络其它相关文章。
文本转载自脚本之家
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
本文主要介绍了微信小程序骨架屏的实现示例,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
vuex数据持久化实现有什么方法?对于vue数据持久化的问题,下面小编通过实例来给大家分享一下实现方法,有vuex-persistedstate和vuex-persist这两种方法,下面我们来详细了解一下。
最终效果展示xhr发起请求!DOCTYPE htmlhtml lang=en head meta charset=UTF-8 meta http-equiv=X-UA-Compatible content=IE=edge meta name=viewport content=width=device-
今天来给朋友们来说说看JavaScript适配器模式的相关资料内容,下列文章具有一定的参考价值在里面,希望爱站技术频道小编所带来理论知识点会让你有所感悟。
这篇文章给大家分享的是实现JS和jQuery对象的转换的方法。小编觉得挺实用的,因此分享给大家做个参考,文中的示例代码介绍得很详细,有需要的朋友可以参考,接下来就跟随小编一起了解看看吧。
成为群英会员,开启智能安全云计算之旅
立即注册Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008