@Tyhj
2019-03-11T08:09:05.000000Z
字数 3899
阅读 2293
Android
其实我觉得原生的方法也还是比较简单的,具体使用可以看Android WebView与JavaScript的交互;JsBridge应该就是简单的封装了一下,让调用更加简单一些吧;
JSBridge是一座用JavaScript搭建起来的桥,一端是web,一端是native。我们搭建这座桥的目的也很简单,让native可以调用web的js代码,让web可以 “调用” 原生的代码
使用JsBridge需要使用BridgeWebView控件,其实这个控件就是重写了WebView,在WebView初始化的时候注入了一些JavaScript,便于我们之后的使用
webView = findViewById(R.id.bridgeWebView);//加载本地HTML文件webView.loadUrl("file:///android_asset/test2.html");
HTML代码,放在assets文件下的HTML,test()方法暂时没有实现,里面我写了一个类似Toast的方法,来展示数据
<html><head><title>js调用android原生代码</title><meta http-equiv="Content-Type" content="text/html;charset=gb2312"><meta id="viewport" name="viewport"content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,minimal-ui"></head><body><br/><li><a onclick="test()">点击调用Android的方法</a></li><br/></body></html><script><!--一个类似Toast的JavaScript方法,不用管怎么搞的-->function toast(msg,duration){duration=isNaN(duration)?3000:duration;var m = document.createElement('div');m.innerHTML = msg;m.style.cssText="width: 60%;min-width: 150px;opacity: 0.7;height: 30px;color: rgb(255, 255, 255);line-height: 30px;text-align: center;border-radius: 5px;position: fixed;top: 40%;left: 20%;z-index: 999999;background: rgb(0, 0, 0);font-size: 12px;";document.body.appendChild(m);setTimeout(function() {var d = 0.5;m.style.webkitTransition = '-webkit-transform ' + d + 's ease-in, opacity ' + d + 's ease-in';m.style.opacity = '0';setTimeout(function() { document.body.removeChild(m) }, d * 1000);}, duration);}</script>
Java中使用下面这个方法就可以暴露方法给JavaScript,方法名为submitFromWeb,data为JavaScript传进来的数据,通过function.onCallBack()方法返回数据给JavaScript
//注册方法供JavaScript调用webView.registerHandler("submitFromWeb", new BridgeHandler() {@Overridepublic void handler(String data, CallBackFunction function) {Toast.makeText(JsBridgeActivity.this, "从JavaScript接收到的数据为:" + data, Toast.LENGTH_SHORT).show();//返回数据给JavaScriptfunction.onCallBack("Hello from Android");}});
使用test()方法,JavaScript中调用这个方法并传入数据进来,这里对返回的数据responseData进行展示
<li><a onclick="test()">点击调用Android的方法</a></li><script>function test(){WebViewJavascriptBridge.callHandler('submitFromWeb', {'data': 'Hello form JavaScript'}, function(responseData) {toast(responseData)});}</script>
库也提供了一个简单的没有回调的调用方式:
webView.setDefaultHandler(new DefaultHandler());
Js调用的时候也可以不指定方法名:
<script>function test2(){window.WebViewJavascriptBridge.send({'data': 'Hello form JavaScript default'}, function(responseData) {toast(responseData)});}</script>
看了DefaultHandler的源码,暂时没想到有什么用,除非自己重写handler方法,和第一个用法相比的确是少了一个方法名
public class DefaultHandler implements BridgeHandler{String TAG = "DefaultHandler";@Overridepublic void handler(String data, CallBackFunction function) {if(function != null){function.onCallBack("DefaultHandler response data");}}}
这个东西看起来和JavaScript调用Android是差不多的,先在JavaScript中注册方法供Android调用,这个脚本放在标签后面就行了,为什么看起来这么复杂呢,因为必须先检测WebViewJavascriptBridge是否存在
<script>function connectWebViewJavascriptBridge(callback) {if (window.WebViewJavascriptBridge) {callback(WebViewJavascriptBridge)} else {document.addEventListener('WebViewJavascriptBridgeReady', function() {callback(WebViewJavascriptBridge)},false);}}connectWebViewJavascriptBridge(function(bridge) {bridge.registerHandler("functionInJs", function(data, responseCallback) {document.getElementById("show").innerHTML = ("data from Java: = " + data);if (responseCallback) {var responseData = "Javascript Says Right back aka!";responseCallback(responseData);}});})</script>
接下来在Android中调用就好了
webView.callHandler("functionInJs", "执行JavaScript方法", new CallBackFunction() {@Overridepublic void onCallBack(String data) {Toast.makeText(JsBridgeActivity.this, data, Toast.LENGTH_SHORT).show();}});
这其中有一个大坑,我手机是Android 9.0的,我下载了dome完全没问题,然后我按照demo方法在我的代码里面写,发现怎么搞都不行,JavaScript方法没有被调用,直到完全改成和demo一样,还是不行,我又改了gradle里面的各种配置,还是不行,最后我把依赖删除了,集成demo里面的那个library,然后好了
repositories {// ...maven { url "https://jitpack.io" }}dependencies {compile 'com.github.lzyzsd:jsbridge:1.0.4'}
JsBridge的最后一个版本1.0.4(3年前的版本)是有问题的;这个项目在github上有100多个问题,最后代码一次提交是6个月前,感觉不是很靠谱,看的出来大家都是Fork下来自己修改的;