Hybrid开发——Native与H5的通信框架JSBridge实现(1)特别说明
什么是JSBridge
⼩伙伴如果如果对于Hybrid并没有什么概念,请先阅读笔者的另外⼀篇⽂章《Hybrid开发——Android与H5的亲密接触》。JSBridge就是⼀个简化Native与JS通信的框架。JSBridge定义了统⼀的通信过程:Native只通过⼀个固定的桥对象调⽤JS,JS也只通过固定的桥对象调⽤Native,具体流程如下图所⽰:
JSBridge定义的通信过程
说明:JS触发原⽣的回调函数的过程其实也是触发⼀个url schema
url sc hem e介绍
· url scheme是⼀种类似于url的链接,是为了⽅便app直接互相调⽤设计的
可以⽤系统的OpenURI打开⼀个类似于url的链接(可拼⼊参数),然后系统会进⾏判断,如果是系统的url scheme,则打开系统应⽤,否则看是否有app注册这种scheme,打开对应app需要注意的是,这种scheme必须原⽣app注册后才会⽣效,如的scheme为(weixin://)
· 本⽂JSBridge中的url scheme则是仿照上述的形式的⼀种⽅式
app不会注册对应的scheme,⽽是由前端页⾯通过某种⽅式触发scheme(如⽤iframe.src),然后Native⽤某种⽅法捕获对应的url触发事件,然后拿到当前的触发url,根据定义好的协议,分析当前触发了那种⽅法。简⽽⾔之就是url => ⽅法(对应关系是JS开发与Android开发商量定义好的)。
为什么要⽤JSBr idge
在笔者的《Hybrid开发——Android与H5的亲密接触》⼀⽂中,我们知道Android已经可以跟JS进⾏交互,那为什么还要这种通过url scheme 的JSBridge⽅式呢,原因⼤致如下:
· Android4.2以下,addJavascriptInterface⽅式有安全漏掉
· iOS7以下, JS⽆法调⽤Native
url scheme交互⽅式是⼀套现有的成熟⽅案,可以完美兼容各种版本,不存在上述问题。⽽且JSBridge将Native与JS的交互⽅式进⾏解耦,提供了⼀个可扩展的,⾼可⽤的,稳定的解决⽅案。
实现⼀个JSBridge
实现步骤⼤致如下:
第⼀步: 设计出⼀个Native与JS交互的全局桥对象
第⼆步: JS调⽤Native功能实现
第三步: Native监听api调⽤
第四步: Native分析url-参数和回调的格式
第五步: Native调⽤JS功能实现
第六步: H5中api⽅法的注册
第⼀步: 设计出⼀个N a tive与JS交互的全局桥对象
我们规定,JS和Native之间的通信必须通过⼀个H5全局对象JSBridge来实现,该全局对象有如下特点:
· 该对象名为“JSBridge”,是H5页⾯中全局对象window的⼀个属性
window.JSBridge = JSBridge
· 该对象有如下⽅法
1、registerHandler( String handlerName, Function handler):供H5调⽤。⽤来注册JS⽅法,Native可通过JSBridge调⽤注册的JS⽅法。调⽤registerHandler⽅法后,被注册的⽅法 handler 会被保存到本地变量 messageHandlers 中。
2、callHandler( String handlerName, JSON data, Function callback):供H5调⽤。H5调⽤原⽣开放的api,调⽤后实际上还是本地通过url scheme触发。调⽤时会将回调 callback 的 id(由callHandler函数⽣成)存放到本地变量responseCallbacks中。
3、_handleMessageFromNative( JSON ):供Native调⽤。原⽣调⽤H5页⾯注册的⽅法,或者通知H5
页⾯执⾏回调⽅法(H5调⽤原⽣⽅法时,会将回调函数作为参数进⾏传递,就是为了让原⽣能在适当的时候通过JSBridge调⽤回调函数,也就是responseCallbacks⾥⾯对应的函数)。
对象功能结构图
第⼆步: JS调⽤N a tive功能实现
上⼀步我们已经定义好了JSBridge对象,H5可以通过callHandler⽅法来调⽤原⽣的API,那么callHandler内部经历了⼀个怎么样的过程呢?接下来我们就来说说callHandler( String handlerName, JSON data, Function callback)函数内部实现过程。
在执⾏callHandler( String handlerName, JSON data, Function callback)时,内部经历了以下步骤:
(1)⾸先判断H5调⽤该⽅法的时候有没有传⼊回调函数。如果有回调函数,则⽣成⼀个回调函数id, 并将id和对应的回调函数添加进⼊回调函。
数的集合 responseCallbacks 中。
(2)通过特定的参数转换⽅法,将传⼊的数据(data), ⽅法名(handlerName)⼀起,拼接成⼀个url scheme
// url scheme的格式如下,基本有⽤信息就是后⾯的callbackId,handlerName与data
// 原⽣捕获到这个scheme后会进⾏分析
var uri = CUSTOM_PROTOCOL_SCHEME://API_Name:callbackId/handlerName?data
(3)使⽤内部早就创建好的⼀个隐藏iframe来触发scheme
//创建隐藏iframe过程
var messagingIframe = ateElement('iframe');
messagingIframe.style.display = 'none';
document.documentElement.appendChild(messagingIframe);
//触发scheme
messagingIframe.src = uri;
注意1:正常来说是可以通过window.location.href达到发起⽹络请求的效果的,但是有⼀个很严重的问题,就是如果我们连续多次修改window.location.href的值,在Native层只能接收到最后⼀次请求,前⾯的请求都会被忽略掉。所以JS端发起⽹络请求的时候,需要使⽤iframe,这样就可以避免这个问题。
注意2:H5调⽤Native时,Native处理完毕后⼀定要及时通知H5进⾏回调,要不然这个回调函数不会⾃动销毁,多了后会引发内存泄漏
第三步: N a tive监听a pi调⽤
在上⼀步中,我们已经成功在H5页⾯中触发scheme,那么Native如何捕获scheme被触发呢?接下来我们以Android为例,说说Android如何捕获url scheme,不过在此之前我们先来简单了解⼏个东西:WebView、WebViewClient、WebChromeClient。
在Android的Webview设计中,不是所有功能都由WebView类来实现的,部分功能由其他的类(WebViewClient、WebChromeClient)来实现,这样⼀来WebView主要专⼼⼲好解析、渲染⼯作就⾏了。
WebViewClient
WebViewClient帮助WebView处理各种通知、请求事件的,具体来说包括:onLoadResource、onPageStart、onPageFinish、onReceiveError、onReceivedHttpAuthRequest;
WebChromeClient辅助WebView处理Javascript的对话框,⽹站图标,⽹站title,加载进度。具体来说包括
WebChromeClient
onCloseWindow(关闭WebView)、onCreateWindow()、onJsAlert (WebView上alert是弹不出来东西的,需要定制你的WebChromeClient处理弹出)、onJsPrompt、onJsConfirm、onProgressChanged、
onReceivedIcon、onReceivedTitle;
在Android中通过 WebViewClient 的 shouldoverrideurlloading 可以捕获到url scheme的触发:
// WebViewClient主要帮助WebView处理各种通知、请求事件
private WebViewClient webViewClient = new WebViewClient() {
@Override // 重写shouldOverrideUrlLoading()⽅法,使得打开⽹页时不调⽤系统浏览器, ⽽是在本WebView中显⽰ public boolean shouldOverrideUrlLoading(WebView view, String url) {
// 原⽣通过解析url进⾏相应处理
}
};
另外,Android中也可以不通过iframe.src来触发scheme,android中可以通过window.prompt(uri, "");来触发scheme,然后Native中通过重写WebViewClient的onJsPrompt来获取uri
第四步:分析ur l-参数和回调的格式
Native接收到Url后,可以按照这种格式将回调参数id、api名、参数提取出来, 然后按如下步骤进⾏:
(1) 根据api名,在本地寻对应的api⽅法, 并且记录该⽅法执⾏完后的回调函数id
(2) 根据提取出来的参数,根据定义好的参数进⾏转化
(3) 原⽣本地执⾏对应的api功能⽅法
(4) 功能执⾏完毕后,到这次api调⽤对应的回调函数id,然后连同需要传递的参数信息,组装成⼀个JSON格式的参数
JSON格式为: {
responseId: 回调id,javascript说明
responseData: 回调数据
}
· responseId(String型)H5页⾯中对应需要执⾏的回调函数的id,在H5中⽣成url scheme时就已经产⽣· responseData(JSON型) Native需要传递给H5的回调数据,是⼀个JSON格式: {
code:(整型,调⽤是否成功,1成功,0失败),
result:具体需要传递的结果信息,可以为任意类型,
msg:⼀些其它
}
(5) 通过JSBridge通知H5页⾯回调
第五步: N a tive调⽤JS功能实现
到了这⼀步,就该Native通过JSBridge调⽤H5的JS⽅法或者通知H5进⾏回调了,具体如下:
JSBridge._handleMessageFromNative(messageJSON);
messageJSON数据格式根据两种不同的类型,有所区别:
Native通知H5页⾯进⾏回调,messageJSON数据格式如下:
{
responseId: 回调id,
responseData: 回调数据
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论