首先我们先要知道

js调用Android的方法有以下四种:
  1. WebView的JavascriptInterface
  1. WebViewClient.shouldOverrideUrlLoading()
  1. WebChromeClient.onConsoleMessage()
  1. WebChromeClient.onJsPrompt()


1. JavascriptInterface
JavascriptInterface是Android官方提供的工js和Native通信方案。其实现如下:
  1. 实现一个java类,供js调用

    public class JavascriptInterface {@JavascriptInterfacepublic void showToast(String toast) {             Toast.makeText(MainActivity.this, toast, Toast.LENGTH_SHORT).show();}
    }
    
  1. 在webView中注册这个类:
webView.addJavascriptInterface(new JavascriptInterface(), "javascriptInterface");

  1. 在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 {@Overridepublic 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 {
@Overridepublic 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调用js
Android调用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;
}@Override
public 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 string
       messageJson = 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的架构。

android 混编JsBridge的原理和实现相关推荐

  1. flutter和Android混编下出现“No implementation found for method xxxx on channel”错误

    flutter和Android混编下出现"No implementation found for method xxxx on channel"错误 这个错误出现的原因是Plugi ...

  2. Android 混编项目打包流程

    本文送给我离职以后缺爱的前端同事们,祝愿他们在没有了打包靠山后可以自食其力,靠自己撑起打包界的一片天 本秘籍分为四步,前三步可实现在已连接的手机上安装并自动显示(即使界面上看见了图标也不要去点!让子弹 ...

  3. android ios 混合编程,React Native与原生(Android、iOS)混编,三端痛点解析

    在做RN混编项目的时候或者面试的时候经常会遇到一些问题,总结起来有以下几种: 1.过多的注册RN组件( AppRegistry.registerComponent() ); 2.从原生跳转指定的RN页 ...

  4. Swift与C++混编 OpenCV初体验 图片打码~

    OpenCV初体验,给图片打码 提到OpenCV,相信大多数人都听说过,应用领域非常广泛,使用C++开发,天生具有跨平台的优势,我们学习一次,就可以在各个平台使用,这个还是很具有诱惑力的. 本文主要记 ...

  5. 详解音频编解码的原理、演进和应用选型等

    本文来自网易云音乐音视频实验室负责人刘华平在LiveVideoStackCon 2017大会上的分享,并由LiveVideoStack根据演讲内容整理而成(本次演讲PPT文稿,请从文末附件下载). 1 ...

  6. Android动态换肤实现原理解析,原理+实战+视频+源码

    前言 本人今年25岁,毕业之后进入一家小型的互联网公司工作,在这原公司呆了3年,直至今年才有了跳槽的想法. 每个程序员 都拥有大厂梦,我也不例外,在小公司待久了,感觉人会荒废掉,太轻松,没有压迫感.因 ...

  7. 从预编译的角度理解Swift与Objective-C及混编机制

    本文从预编译的基础知识入手,由浅至深的介绍了 Objective-C 和 Swift 的工作机制,并通过这些机制来解释混编项目中使用到的技术和各种参数的作用,由此来指导开发者如何进行混编. 写在前面 ...

  8. cocos2d-x与安卓混编实现“更换头像”

    Cocos2dx与安卓混编实现"更换头像" 标签: cocos2d-x安卓 2014-07-13 17:13  1601人阅读  评论(0)  收藏  举报   分类: Cocos ...

  9. 【Android 内存优化】Android 原生 API 图片压缩原理 ( 哈夫曼编码开关 | 哈夫曼编码原理 | libjpeg-turbo 函数库 )

    文章目录 一. 哈夫曼编码开关 二. 哈夫曼编码原理 三. libjpeg-turbo 函数库 四. libjpeg-turbo 函数库下载 [Android 内存优化]图片文件压缩 ( Androi ...

最新文章

  1. 解表化饮什么意思_为什么有人动不动就一身汗,有人再热也不出汗?中医告诉真实原因...
  2. 常看 Shell: 文本文件操作
  3. Javascript数组常见的方法
  4. contourArea函数
  5. 面向对象---类与对象
  6. android网格布局间距,android – 删除回收站视图网格布局中的默认间距
  7. ORA-01795: 列表中的最大表达式数为1000的解决方法
  8. 零基础学python还是c语言-学习python还是c语言?
  9. qt写的一个计算器程序
  10. 台达DVP50MC11T与威纶触摸屏ModbusTCP通信
  11. 符合 Qi 规范的移动设备无线充电解决方案
  12. 华为手机热点无法连接_教大家华为手机开wifi热点共享网络连接不上怎么办
  13. LU分解、矩阵求逆与解线性方程组(matlab代码)
  14. 木瓜移动每日快讯0511:谷歌Chrome引入新隐私功能fenced frame
  15. 用命令提示符打开MySQL并编译sql语句
  16. 尚来古籍——江氏族谱
  17. Androi事件分发( 二),解决事件冲突
  18. 跨国企业在中国 | 3M与美的达成家电领域战略合作;舍弗勒南京公司开建新厂房...
  19. 【ML】MoG与EM:从EM到MoG
  20. 如何找到蓝奏云网盘登录后的ylogin、phpdisk_info?

热门文章

  1. marlin 源码入门2
  2. 6-java安全——java反序列化漏洞利用链
  3. Python实验|磁盘垃圾文件清理器
  4. 小小Python编程故事-小小的成绩单(1)
  5. 存储器扩展连接理解(S3C2410为例)——SDRAM
  6. LVS负载均衡--NAT模式
  7. 通过JDBC连接Oracle数据库时进行查询操作时产生BigDecimal转换异常的处理
  8. GPS信号捕获的MATLAB_FPGA仿真
  9. micropython ble 连接小米温湿度计2 获取数据
  10. js小孩翻书动态实现效果