备注:近期在处理js和安卓原生webView交互方式时发现,前端使用的是WebViewJavascriptBridge的一种方式,可以前后端双向交互,之前没有接触过,查找资料发现IOS使用的是IOS WebViewJavascriptBridge,网上很少有安卓这方面的资料,通过在GitHub上查找,发现有开源的安卓的Bridge方式和IOS的使用方式一致。最终使用的是smallbuer优化后的原作者lzyzsd的JsBridge,在此记录下。
JSBridge-Android原理:
不再使用URL SHEME拦截方式,直接采用webview的addJavaScriptInterface,此方法根据Android源码跟踪,是目前采用webview方案js与原生交互效率最高的一种系统实现; 对于API小于17的使用者,1.0.3版本将支持版本降低到14,满足一些朋友的需要,为了安全主要实现方式利用onJsPrompt方法让H5可以和原生进行交互,并且移除了低版本的三个危险漏洞;
dependencies {
implementation 'com.smallbuer:jsbridge:1.0.3'
}
xml中使用时导入具体的包:
<com.smallbuer.jsbridge.core.BridgeWebView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/bridgeWebview"
android:layout_weight="1"
/>
H5中可以自己封装调用名称,适合Vue.js或者存js调用;
window.WebViewJavascriptBridge.callHandler(
'toast' //桥注册的名称ID
, {'msg': '中文测试'} //传递给原生的参数
, function(responseData) { //异步回调接口
console.log('native return->'+responseData);
}
);
外部扩展其他webview,比如X5内核,uc内核等,源码请参考demo中X5WebView实现
备注:这里X5采用的是 com.tencent.smtt.sdk.WebView
(1)新建X5WebView继承X5包内的webview并实现IWebView接口
(2)在X5WebView中新建BridgeTiny并传入X5WebView对应,BridgeTiny作为一个webview的管理类;
// 这里使用时发现部分方法需要在加载前调用,修改为WebViewClient 中的 onPageStarted时加载
// 调试时发现部分手机onPageStarted中无法加载js脚本配置,因此onPageStarted|onLoadResource|shouldOverrideUrlLoading|onPageFinished中都做了添加
(3)在webview执行onPageFinished时,加载js脚本内容用于执行对象的注册;
(4)在webview执行destroy时清空使用内存;
备注:在创建BridgeHandler时没有采用作者的方法去创建每一个handler的class,而是创建了JSBridgeHandler类方便管理,通过具体的方法获取需要注册的BridgeHandler对象。当然这里只适合比较简单的功能,如果遇到需要同webView,activity进行交互的,需要在具体activity页面进行创建。
注意:bridgeTiny = new BridgeTiny(this); 不能放到 X5WebView 的构造方法中初始化,
因为BridgeTiny在创建时已经注册了所有的BridgeHandler,如果存在复杂的需求时,单独添加是无效的,所以应该把方法暴露出来,提供给外部主动调用进行注册。 mMessageHandlers.putAll(Bridge.INSTANCE.getMessageHandlers()); public void initBridgeTiny(){ bridgeTiny = new BridgeTiny(this); }
/**
* 创建 JSBridge 对外提供的 BridgeHandler功能类
*/
public class JSBridgeHandler {
public static final String TAG = "JSBridgeHandler";
public static final String CHAT_SELECT_FILES = "chatSelectFiles";
public static final String CLOSE = "close";
public static final String SET_TITLE = "setTitle";
public static final String GET_SYSTEM_INFO = "getSystemInfo";
public static final String GET_ADDRESS_INFO = "getAddressInfo";
public static BridgeHandler chatSelectFiles(){
return new BridgeHandler(){
@Override
public void handler(Context context, String file_url, CallBackFunction function) {
// ...function.onCallBack(result.toJSONString());
}
};
}
// ...
}
private void initJSBridgeHandler() {
Map<String, BridgeHandler> handlerMap = new HashMap<>();
handlerMap.put(JSBridgeHandler.GET_SYSTEM_INFO,JSBridgeHandler.getSystemInfo());
handlerMap.put(JSBridgeHandler.SET_TITLE,JSBridgeHandler.setTitle());
handlerMap.put(JSBridgeHandler.GET_ADDRESS_INFO,JSBridgeHandler.getAddressInfo());
handlerMap.put(JSBridgeHandler.CLOSE,JSBridgeHandler.close());
handlerMap.put(JSBridgeHandler.CHAT_SELECT_FILES,JSBridgeHandler.chatSelectFiles());
Bridge.INSTANCE.registerHandler(handlerMap);
}