JSBridge是什么
顾名思义:就是JavaScript(H5)与Native通信的桥梁,在H5开发中经常有操作客户端的需求,比如获取App信息,打开/关闭一个WebView,吊起支付面板等等,但这些功能只能在Native中实现,因此诞生JSBridge,通过JSBridge与Native通信,赋予了JavaScript操作Native的能力,同时也给了Native调用JavaScript的能力。
![783d2a3974ddf71ee82b0f6773a15123.png](https://i-blog.csdnimg.cn/blog_migrate/8c85c0757e2134ebaf6286195a49ec30.jpeg)
JSBridge与Native间通信原理
在H5中JavaScript调用Native的方式主要用两种
1.注入API,注入Native对象或方法到JavaScript的window对象中(可以类比于RPC调用)。
2.拦截URL Schema,客户端拦截WebView的请求并做相应的操作(可以类比于JSONP)。
下面将以Android端的JSBridge通信为例,讲解这两种方式的实现原理(本人比较菜,只会Java不会Swift和OC)。
注入API
通过WebView提供的接口,向JavaScript的window中注入对象或方法(Android使用addJavascriptInterface()方法),让JavaScript调用时相当于执行相应的Native逻辑,达到JavaScript调用Native的效果。
对于Android实现方式如下,核心代码在于
![c109616f4475ee6f29dafe5109ccca0b.png](https://i-blog.csdnimg.cn/blog_migrate/bce2018452ab1c6b820cc5cfb2903f8b.jpeg)
示例如下
在Android的main页面放一个Webview
![550cfde28f588b1e44798f412b632d8d.png](https://i-blog.csdnimg.cn/blog_migrate/45008ff30939710508be67f72a68cc46.jpeg)
然后Android端对应的代码如下
![622f58a3b5d7a592d104e589dffa714c.png](https://i-blog.csdnimg.cn/blog_migrate/0767d232ebefe6297d87db4217975026.jpeg)
对于JavaScript侧,则可以直接调用Native端注入的InjectNativeObjec对象的方法
![24e796c3f69674f2817e389739d22c49.png](https://i-blog.csdnimg.cn/blog_migrate/9d9eb1f5adbc5ba53eb75dc95d388bc5.jpeg)
实际效果如下,其中login按钮点击调用Native端openNewPage方法并传相应的参数给客户端。
![96405f9235216160de76912159e52c40.gif](https://i-blog.csdnimg.cn/blog_migrate/f9e2bed4bedff2d34fc7431ded949e30.gif)
缺陷: Android4.2及以下的版本使用addJavascriptInterface方法有漏洞
该漏洞源于程序没有正确限制使用WebView.addJavascriptInterface方法,远程攻击者可通过使用Java Reflection API利用该漏洞执行任意Java对象的方法,简单的说就是通过addJavascriptInterface给WebView加入一个JavaScript桥接接口,JavaScript通过调用这个接口可以直接操作本地的Java接口。
在Android4.2以上提供@JavascriptInterface注解来规避该漏洞,但对于4.2以下版本则没有任何方法。所以使用该方法有一定的风险和兼容性问题。
拦截URL Schema
H5端通过iframe.src或localtion.href发送Url Schema请求,之后Native(Android端通过shouldOverrideUrlLoading()方法)拦截到请求的Url Schema(包括参数等)进行相应的操作。
通俗点讲就是,H5发一个普通的https请求可能是: https://daydream.com/?a=1&b=1, 而与客户端约定的JSBridge Url Schema可能是: Daydream://jsBridgeTest/?data={a:1,b:2},客户端可以通过schema来区分是JSBridge调用还是普通的https请求从而做不同的处理。
其实现过程原理类似于JSONP
1.首先在H5中注入一个callback方法,放在window对象中
![614025b4766e531bab0ebe5c8cb10bbb.png](https://i-blog.csdnimg.cn/blog_migrate/aae38f2f9b97ebe39450b5abe2d510aa.jpeg)
然后把callback的名字通过Url Schema传到Native
2.Native通过shouldOverrideUrlLoading(),拦截到WebView的请求,并通过与前端约定好的Url Schema判断是否是JSBridge调用。
3.Native解析出前端带上的callback,并使用下面方式调用callback
![5f57adcaeb9743aacde000b0129196f4.png](https://i-blog.csdnimg.cn/blog_migrate/1106bca2ccd7c9d0fbb1f369f503acca.jpeg)
或者
![cf7d57db00eba2d3dac481fc8eddf3ab.png](https://i-blog.csdnimg.cn/blog_migrate/1cfe5c3cf4c6f0f885550185166fd665.jpeg)
通过上面几步就可以实现JavaScript到Native的通信。下面可以看看处理Url Schema的拦截的shouldOverrideUrlLoading方法的相关例子
![883ba08b4a4e16ee7afcbc7698547f9e.png](https://i-blog.csdnimg.cn/blog_migrate/6a7006f4676784323aa24495af5d8f9e.jpeg)
示例
Android页面布局
![bae102aea2ffecedc17b94c003d46502.png](https://i-blog.csdnimg.cn/blog_migrate/797c493a0077947c05a9c7be8a2b5265.jpeg)
Android端代码如下
![68957c6b1bf8f5095cbdb253baf10587.png](https://i-blog.csdnimg.cn/blog_migrate/e30f9c55f9e3043badf5ab85e65df287.jpeg)
![37b05be776deca75cfb049245e7ca121.png](https://i-blog.csdnimg.cn/blog_migrate/a741a505c108c4fd7c907dc6f7b00687.jpeg)
JavaScript侧
window上挂载的方法在Native中可以使用webView.loadUrl() / webView.evaluateJavascript()调用
![a55b56a15390c87c0dbb48119881df79.png](https://i-blog.csdnimg.cn/blog_migrate/67059792fbdff1ebbfc5920cd2bcf3f7.jpeg)
基于JSONP原理可以定义JSBridge类
![4a374df3f1e3ba51b6d357de38031e3d.png](https://i-blog.csdnimg.cn/blog_migrate/cb7b81018a7e8361bd6661a39295f6dd.jpeg)
JavaScript使用例子
![f775605494286a1ee2eb276b71b67b3e.png](https://i-blog.csdnimg.cn/blog_migrate/59601389b8182027e486c8c6143fea25.jpeg)
效果如下
![7db7f81e8b9a388f1a992ce46da9277b.gif](https://i-blog.csdnimg.cn/blog_migrate/13d99b9a5bcf34561b20673a8ede4580.gif)
缺陷: 使用URL Schema有一定的长度问题,url过长可能会导致丢失; 一次JSBridge调用耗时可能比较长,创建请求需要一定的时间。
总结
本文简单介绍了JSBridge以及在Android端的通信,通过相应的分析与代码实现可以发现JSBridge原理其实并没有那么难,因此希望本文能对读者对JSBridge有一定的理解,最后生活不止有前端,还有客户端在等着咱o(T^T)o