前言
大家好,我是抹茶。
在Hybrid APP中,H5和Native需要相互配合,最终实现整个流程的闭环,在这两者中间起到桥梁作用的就是JSBridge。
在比较流行的JSBridge中,主要是通过API注入和拦截URL请求来达到native端和webview端相互通信的效果的。
本文将介绍API注入方式。
如下图所示,Native原生(Android或ios)会将JSBridge注入到window全局对象上。
H5会通过形如window.JSBridge.functionName(name,data,callback)的方式调用原生的api。
整体流程图
我们梳理一下整个的通信流程,如下图所示
结合这个流程,我们需要思考以下问题:
- Native如何向H5注入JSBridge
- H5如何调用原生的API
- Native如何得知H5调用了哪些api,传递了哪些信息?
- Native如何将结果通知H5
我们一个一个问题的解决过去。
具体步骤
1. Native如何向H5注入JSBridge?
首先,Hybird H5是运行在原生应用内嵌浏览器控件WebView中的,Android是WebView,IOS是UIWebView或WKWebView。
以Android为例,要实现javascript可以调用Android方法,在webView容器中注入一个Java代理。
// 安卓侧代码
class JavaProxy{
@JavascriptInterface //注意这里的注解。出于安全的考虑,4.2 之后强制要求,不然无法从 Javascript 中发起调用
public void javaFn(){
//xxxxxx
};
}
webView.addJavascriptInterface(new JavaProxy();, "JSBridge");
这样就在webView容器中的全局作用域,增加了一个JSBridge属性,也就是拥有了window.JSBridge对象。
2. H5如何调用原生的API?
在javascript中,可以通过JSBridge.javaFn()调用Java侧的方法。
// H5侧代码
JSBridge.javaFn()
Android可以在JSBridge身上注入更多的方法,如下
// 安卓侧代码
javaProxy.register("getPackageName", new JavaHandler(){
@Override
public void handle(String message, final ValueCallback<String> callback){
//xxxxx
}
})
然后,H5就可以通过JSBridge.getPackageName调用最新注册的方法了。
3. Native如何得知H5调用了哪些api,传递了哪些信息?
如上面的流程,可以通过具体的函数名得知是调用了哪个函数,传递的信息可以通过函数参数的方式实现。
4. Native如何将结果通知H5?
// 安卓侧代码
// 供javascript调用的接口
javaProxy.register("getPackageName", new JavaHandler(){
@Override
public void handle(String message, final ValueCallback<String> callback){
// 处理从 JavaScript 传递过来的参数
System.out.println("Received message from JavaScript: " + message);
// 调用 JavaScript 的回调函数并传递参数
webView.post(() -> {
// 在webView容器里执行JS代码,执行相应的回调函数
webView.evaluateJavascript("javascript:callback('" + response + "')", null);
});
}
})
可以看到通过webView.evaluateJavascript("javascript:callback('" + response + "')")可以执行javascript侧的代码,从而实现js侧的回调函数被执行。
这样,API注入的整体流程就完成了。
url拦截的方式见文章JSBridge原理解析——以WebviewJavascriptBridge实现方式为例,本来想自己写一些这部分,但是这文章真的很系统了,比我研究深入。
总结
JSbridge的本质是通过webView容器向window全局对象上注入一些数据的方法,通过调用这些方法,native侧可以感知到,通过执行javascript的回调函数,使H5侧收到数据。