您的位置:首页 > 移动开发 > Android开发

android 混编JsBridge的原理和实现

2017-11-17 14:56 387 查看
首先我们先要知道js调用Android的方法有以下四种:WebView的JavascriptInterfaceWebViewClient.shouldOverrideUrlLoading()WebChromeClient.onConsoleMessage()WebChromeClient.onJsPrompt()1. JavascriptInterfaceJavascriptInterface是Android官方提供的工js和Native通信方案。其实现如下:实现一个java类,供js调用
public class JavascriptInterface {@JavascriptInterface
public void showToast(String toast) {
Toast.makeText(MainActivity.this, toast, Toast.LENGTH_SHORT).show();
}
}
在webView中注册这个类:
webView.addJavascriptInterface(new JavascriptInterface(), "javascriptInterface");
在js中直接调用这个接口:
function showToast(text){
window.javascriptInterface.showToast(text);
}
但是webView有个安全漏洞:WebView中接口隐患与手机挂马利用。 在Android4.2后,这个漏洞被修复;但是考虑到兼容性的问题,这个方案基本不被采用。2. WebViewClient.shouldOverrideUrlLoading()这个方法是拦截所有webView的跳转,页面可以构造一个特殊格式的Url跳转,shouldOverrideUrlLoading拦截Url后判断其格式,然后Native就能执行自身的逻辑了。
public class CustomWebViewClient extends WebViewClient {@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (isJsBridgeUrl(url)) {
// JSbridge的处理逻辑
return true;
}
return super.shouldOverrideUrlLoading(view, url);
}
}
3. WebChromeClient.onConsoleMessage()在js中执行console.log(), 会进入Android的WebChromeClient.consoleMessage()回调。
public class CustomWebChromeClient extends WebChromeClient {
@Override
public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
super.onConsoleMessage(consoleMessage);
String msg = consoleMessage.message();//Javascript输入的Log内容
}
}
4. WebChromeClient.onJsPrompt()和3类似,在js中执行alert、confirm和prompt这三个方法时,会进入Android的onJsAlert、onJsConfirm和onJsPrompt回调。 由于prompt的使用频率较低,因此通常采用prompt实现js和Native的通信。Android调用jsAndroid调用js接口的方法只有一个:WebView.loadUrl():
webView.loadUrl('javascript: ' + ...);
Android中的JSBridge是H5与Native通信的桥梁,至于demo在http://blog.csdn.net/roshen_android/article/details/73825781已经详细说明了,大家可以下载demo去看看当你下载完,看完demo后你会发现嵌完所有的类后,只需简单的调用BridgeWebview的registerHandler(js调用Native),callHandler(Native调用js)这2个类就能实现H5与Native通信。先来看看registerHandler
/**
* register handler,so that javascript can call it
*
* @param handlerName
* @param handler
*/
public void registerHandler(String handlerName, BridgeHandler handler) {
if (handler != null) {
messageHandlers.put(handlerName, handler);
}
}
可以看到其内部是将js调用native的请求添加到一个
Map<String, BridgeHandler> messageHandlers = new HashMap<String, BridgeHandler>();
中去,然后你会发现messageHandlers最终还是去到
BridgeHandler handler;
if (!TextUtils.isEmpty(m.getHandlerName())) {
handler = messageHandlers.get(m.getHandlerName());
} else {
handler = defaultHandler;
}
if (handler != null){
handler.handler(m.getData(), responseFunction);
}
这就是js调用Native回调回来的,至于这个回调可以看到
public BridgeWebViewClient(BridgeWebView webView) {this.webView = webView;}@Overridepublic boolean shouldOverrideUrlLoading(WebView view, String url) {try {url = URLDecoder.decode(url, "UTF-8");} catch (UnsupportedEncodingException e) {e.printStackTrace();}if (url.startsWith(BridgeUtil.YY_RETURN_DATA)) { // 如果是返回数据webView.handlerReturnData(url);return true;} else if (url.startsWith(BridgeUtil.YY_OVERRIDE_SCHEMA)) { //webView.flushMessageQueue();return true;} else {return super.shouldOverrideUrlLoading(view, url);}}
,下面来看看Native调用js,该调用主要是callHandler
/*** call javascript registered handler** @param handlerName* @param data* @param callBack*/public void callHandler(String handlerName, String data, CallBackFunction callBack) {doSend(handlerName, data, callBack);}
一步一步点下去你会发现最终去到
void dispatchMessage(Message m) {String messageJson = m.toJson();//escape special characters for json stringmessageJson = messageJson.replaceAll("(\\\\)([^utrn])", "\\\\\\\\$1$2");messageJson = messageJson.replaceAll("(?<=[^\\\\])(\")", "\\\\\"");String javascriptCommand = String.format(BridgeUtil.JS_HANDLE_MESSAGE_FROM_JAVA, messageJson);if (Thread.currentThread() == Looper.getMainLooper().getThread()) {this.loadUrl(javascriptCommand);}}
看到红色的字体没,就是Native唯一调用js的方法。-----------------------------------------------------------------------------------------------------------------------------------------------总结了下,JsBridger无非都是为我们搭建了更好的桥梁,让我们更好的优化hybrid的架构。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: