webview之JSB通信原理
1、前言
在这个移动互联网盛行的时代,移动应用的开发就需求量剧增,早期的移动端应用大都使用原生开发(android,ios),而现在的移动开发技术选型上基本都是混合开发(Hybrid),混合开发是一种开发模式,指使用多种开发模型开发App,通常会涉及到两大类技术:原生Native、Web H5。
2、WebView
A View that displays web pages.
webView是移动端(原生)提供的运行web的环境,它是一种嵌入式浏览器,原生应用可以用它来展示网络内容。可与页面JavaScript交互,实现混合开发。
1、web的主要元素
1、html
超文本标记语言, 是一种用来结构化 Web 网页及其内容的标记语言。网页内容可以是:一组段落、一个重点信息列表、也可以含有图片和数据表。
<!DOCTYPE html>
<html><head><title>This is a title</title></head><body><p>Hello world!</p></body>
</html>
html通过HTMLDocmentParser解析之后然后通过HTMLTreeBuilder生成一个Document树
2、css
CSS 是一种样式规则语言,可将样式应用于 HTML 内容, 例如设置背景颜色和字体,在多个列中布局内容。也可用于创建布局 , 例如将一个单列文本变成包含主要内容区域和存放相关信息的侧边栏区域的布局。
h1 {color: red;font-size: 5em;
}
css通过CSSParser进行解析如下图
3、JS
javaScript是一种脚本语言,可以用来创建动态更新的内容,控制多媒体,制作图像动画。
const para = document.querySelector('p');para.addEventListener('click', updateName);function updateName() {let name = prompt('输入一个新的名字:');para.textContent = '玩家1:' + name;
}
JavaScript运行在javaScript engine中,比如Chrome的v8 engine的执行流程如下
详细流程图。javaScript代码会先被解析生成一棵抽象语法树,然后通过解释器解释生成bytecode
2、web的渲染流程
2、webview工作原理
web通过loader加载,然后HTML parser进行解析
webview通过webkit来渲染web页面
在Android中渲染流程如下,在ui线程进行绘制的时候,如果有web内容,会调用到webkit thread线程来遍历web 的doc文件,然后生成一个display list,交给ui线程中的display list中进行渲染。
3、Webview vs native
WebView | Native | |
---|---|---|
加载速度 | 差 | 好 |
交互完备 | 差 | 好 |
迭代更新 | 好 | 差 |
开发成本 | 好 | 差 |
原生支持 | 差 | 好 |
2、JSBridge基本概念
1、实现 Native端和 web 端双向通信的一种机制。
在Hybrid开发模式下,H5页面经常需要使用到Native的功能,比如打开二维码扫描、调用本地相册、获取用户信息等,同时Native也需要向Web端发送推送、更新状态等。
2、以 javascript 引擎或 webView 容器为媒介。
webview容器在原生中是一个容器控件,可以加载url或者 web页面,而JavaScript是运行在单独的JS Context中(Webview容器、JSCore等),与原生有运行环境的隔离,所以需要有一种机制实现Native端和Web端的双向通信。
3、通过约定的协议进行通信。
3、JSBridge 的通信原理
Web端和Native可以类比于Client/Server模式,Web端调用原生接口时就如同Client向Server端发送一个请求类似,JSB在此充当类似于HTTP协议的角色。
实现JSBridge主要是两点:
- 将Native端原生接口封装成JavaScript接口
- 将Web端JavaScript接口封装成原生接口
1、Native to Web
Native 调用 JS 比较简单,只要 H5 将 JS 方法暴露在 Window 上给 Native 调用即可。
JavaScript作为解释性语言,最大的一个特性就是可以随时随地地通过解释器执行一段JS代码,所以可以将拼接的JavaScript代码字符串,传入JS解析器执行就可以,JS解析器在这里就是webView。
- Android 4.4之前只能用loadUrl来实现,并且无法执行回调
val jsCode = String.format("window.showWebDialog('%s')", text)
webView.loadUrl("javascript: " + jsCode)
- Android 4.4之后提供了evaluateJavascript来执行JS代码,并且可以获取返回值执行回调;
String jsCode = String.format("window.showWebDialog('%s')", text);
webView.evaluateJavascript(jsCode, new ValueCallback<String>() {@Overridepublic void onReceiveValue(String value) {//拿到返回值后进行处理}
});
Android 版本 | API | 特点 |
---|---|---|
低于4.4 | WebView.loadUrl | 无法执行回调 |
高于4.4 | WebView.evaluateJavascript | 可以拿到 JS 执行完毕的返回值 |
- iOS的UIWebView使用stringByEvaluatingJavaScriptFromString;
NSString *jsStr = @"执行的JS代码";
[webView stringByEvaluatingJavaScriptFromString:jsStr];
- iOS的WKWebView使用evaluateJavaScript;
[webView evaluateJavaScript:@"执行的JS代码" completionHandler:^(id _Nullable response, NSError * _Nullable error) {}];
iOS 版本 | API | 特点 |
---|---|---|
低于8.0 | UIWebView.stringByEvaluatingJavaScriptFromString | 无法执行回调 |
高于8.0 | WKWebView.evaluateJavaScript | 可以拿到 JS 执行完毕的返回值 |
2、Web to Native
方案 | 调用方法 | 速度 | 注意事项 |
---|---|---|---|
注入api | addJavascriptInterface | 较快 | Android < 4.2 存在安全漏洞 |
url拦截 | shouldOverrideUrlLoading | 最慢 | |
JS回调时机 | onJsPrompt | 较快 | |
日志输出 | console.log | 最快 | scheme://dddd |
1、注入 API
将Native的相关接口注入到JS的Context(window)的对象中,一般来说这个对象内的方法名与Native相关方法名是相同的,Web端就可以直接在全局window下使用这个暴露的全局JS对象,进而调用原生端的方法。
1、 客户端定义js映射对象
public class AndroidToJS {// 定义JS需要调用的方法// 被JS调用的方法必须加入@JavascriptInterface注解@JavascriptInterfacepublic void callAndroid(String msg){Log.e("zw","JS调用了Android的callAndroid(),msg : " + msg);}}
2、注入js方法
webView.addJavascriptInterface(new AndroidToJS(),"android");
3、前端调用
window.NativeBridge.callAndroid('hello');
4、优缺点
优点:通信时间短,调用方便。
缺点:使用 webView.addJavascriptInterface 方法进行注入。此方法存在漏洞,在 Android4.2 以上提供 @javascriptInterface 注解来规避该漏洞,但对于4.2以下版本则没有任何方法。所以使用该方法有一定的风险和兼容性问题。
2、scheme拦截
客户端和前端定义scheme规范,前端加载scheme,客户端会拦截scheme,如果scheme格式符合规范,客户端会解析scheme中的参数,获取对应的方法和参数名,然后调起客户端原生方法。
1、前端加载scheme
通过iframe.src发起一个请求,客户端webview能拦截这个请求,做相应的处理。
a标签和location.href都可以做到,但是a灵活性欠缺,需要交互动作触发;location.href连续调用时,后一个请求会覆盖前一个。
var iframe = document.createElement('iframe');
iframe.style.width = '1px';
iframe.style.height = '1px';
iframe.style.display = 'none';
iframe.src = 'jsbridge://getNetwork?callback=networkInfo';
document.body.appendChild(iframe);
// 100毫秒后移除
setTimeout(function() { iframe.remove();
}, 100);
2、android 重写shouldOverrideUrlLoading
在webview中重写shouldOverrideUrlLoading根据定义的scheme原则进行拦截
public boolean shouldOverrideUrlLoading(WebView view,String url) {if(isValidScheme()){//拦截处理schemereturn handleScheme()} return false;
}
3、优缺点
优点:兼容性好,安卓和 IOS 的各个版本都能支持此功能。
缺点:调用时延比较高 200 - 400ms,在安卓上表现明显;URL scheme 长度有限,内容过多可能会丢失字符;不支持同步返回结果,所有信息传送都需要调用 iframe 请求,使用 callback 得到返回的数据。
3、JS回调时机
1、Confirm
客户端可以拦截confirm。iOS的UIWebview不支持。使用场景相对较多,不适合用来做jsb。
1、前端调用
window.confirm('bytedance://app.toast?title=hello')
2、alert
客户端可以拦截alert。iOS的UIWebview不支持。但是alert使用场景较多,不适合用来做jsb。
1、前端调用
window.alert('bytedance://app.toast?title=hello')
3、Prompt
客户端可以拦截prompt,参数同上。iOS的UIWebview不支持。可自定义返回值,多用于安卓jsb方案。
1、前端调佣
window.prompt('bytedance://app.toast?title=hello')
2、Android端拦截
/ Java: 重载 onJsPrompt 方法,提取 prompt 内容判断是否需要拦截class MyWebViewClient extends WebChromeClient {@Overridepublic boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {if (message.startsWith("bridge://")) {// 解析 // 后面的 action 和参数,调用相关的函数result.confirm("Yes!");}return true;}}webView.setWebViewClient(new MyWebViewClient());
4、日志输出
客户端可以拦截console.log,参数同上。安卓和iOS通用。
1、前端调用
console.log('bytedance://app.toast?title=hello')
2、Android端拦截
WebView.setWebChromeClient(new WebChromeClient() {public void onConsoleMessage(String message, int lineNumber, String sourceID) {return true;}
});
4、jsb权限管理
1、jsb权限管理目的
由于第三方应用的存在,为保证端能力调用安全性,防止恶意网页随意获取用户隐私信息,甚至造成用户财产损失等,需要对三方调用jsb的能力进行管理。
2、jsb权限分类
jsb权限分成三种类型:
1、priavte
只有内置的域名才可以访问。
2、protected
默认的jsb都是这种类型,除一方应用之外的域名调用时都会进行权限校验,只有有该权限的jsb才能调用成功。
3、 public
公开的jsb,所有域名的url都可以访问,不涉及到隐私信息和安全问题,不进行权限校验,如op.config。
3、jsb权限管理流程
下面是权限设计的主要流程,每一个非public 类型的jsb调用的时候都会先进行权限校验,只要权限校验成功后才真正调起bridge,执行bridge后给前端回调,如果校验失败则直接返回错误code同时回调给前端。
参考文档
1、https://www.alibabacloud.com/blog/in-depth-profiling-of-jsbridge_112504
2、https://developer.android.com/reference/android/webkit/WebView
3、https://docs.google.com/presentation/d/1boPxbgNrTU0ddsc144rcXayGA_WF53k96imRH8Mp34Y/edit#slide=id.ga884fe665f_64_60
4、https://juejin.cn/post/6847009771673878542
5、https://docs.google.com/presentation/d/1ZRIQbUKw9Tf077odCh66OrrwRIVNLvI_nhLm2Gi__F0/pub?slide=id.p
6、https://www.w3schools.com/html/
7、https://www.educba.com/introduction-to-javascript
8、https://chromium.googlesource.com/chromium/src/+/master/android_webview/docs/java-bridge.md
webview之JSB通信原理相关推荐
- Hybrid与h5使用webview+JSBridge实现通信原理简析
目录 一.概念了解: webview - 承载和渲染网页的容器 JSBridge - 封装(了一系列js与native互通数据)的js方法 二.简易流程图: 三.详解流程: 第一步: 设计出一个Nat ...
- React-Native系列Android——Native与Javascript通信原理(一)
React-Native最核心的是Native与Javascript之间的通信,并且是双向通信.Native层到Javascript层,Javascript层到Native层.虽说是两个方向,但实现上 ...
- java中JSB_深入解析Cocos Creator JSB绑定原理以及应用实践
背景 一直以来,ABCmouse 项目中的整体 JS/Native 通信调用结构都是基于 callStaticMethod evalString 的方式.通过 callStaticMethod 方法我 ...
- JSBridge通信原理
JSBridge是个啥 直接来重点,记住:JSBridge 是一个很简单的东西,更多的是一种形式.一种思想,为了解决 H5 和 Native 的双向通信. 就像我们刚接触 ajax 时,也很懵逼.其实 ...
- Binder跨进程通信原理(三):Binder IPC实现原理
1. 动态内核可加载模块 && 内存映射 正如上一章所说, 跨进程通信是需要内核空间做支持的. 传统的 IPC 机制如 管道, Socket, 都是内核的一部分, 因此通过内核支持来实 ...
- Binder跨进程通信原理(一):动态内核加载模块
先上一张Binder 的工作流程图.(如果不清晰,可以 复制图片链接到浏览器 或 保存到本地 查看,我经常都是这样看图的哈) 一开始上手,陌生的东西比较多,But,其实并不复杂.喔,流程图是用 Pro ...
- 传统的Linux中IPC通信原理
在了解 Binder 跨进程通信原理之前, 我们先了解一下 Linux 传统的进程间通信的概念和基本原理, 这样有助于我们更好的理解 Binder 的通信原理. 这个部分基本都是理论, 基础不是很好的 ...
- HwBinder原理总结-Android10.0 HwBinder通信原理(十一)
摘要:本节主要来进行Android10.0 HwBinder的原理总结 阅读本文大约需要花费14分钟. 文章首发微信公众号:IngresGe 专注于Android系统级源码分析,Android的平台设 ...
- HwBinder驱动篇-Android10.0 HwBinder通信原理(十)
摘要:本节主要来讲解Android10.0 HwBinder驱动的流程 阅读本文大约需要花费24分钟. 文章首发微信公众号:IngresGe 专注于Android系统级源码分析,Android的平台设 ...
最新文章
- MySQL Cluster 日常维护
- 网吧网管在自杀前的遗书
- Git中.gitignore忽略文件(maven项目)
- nginx限制ip,只允许域名访问
- Oracle数据库之多行函数
- 微机计算机原理姚向华课后答案,微型计算机操作系统
- 算法设计 - LCS 最长公共子序列最长公共子串 LIS 最长递增子序列
- Halcon学习路线——Blob分析(2)
- 总结(5)--- Numpy和Pandas库常用函数
- 绥化二中高考成绩查询2021,2014绥化中考
- 谷歌地图地名显示繁体字_Google Earth显示中文地名啦!
- linux主目录下的文件夹改回英文
- windows hotkey
- 学习笔记5(类和对象)
- 2017最新苹果 APPLE ID注册流程
- 机器学习之L1正则化和L2正则化(附源码解析)
- Python与金融:为什么将Python用于金融
- 不重启显示新增硬盘(虚拟机)
- omv检查硬盘坏道_技术员们有福了,关于怎么用MHDD修复硬盘坏道,现在免费给大家了!!!...
- 齿轮振动信号的数字滤波处理-含Matlab代码