[关闭]
@Tyhj 2019-03-11T08:09:05.000000Z 字数 3899 阅读 1942

Android使用JsBridge与JavaScript交互

Android


原生方法

其实我觉得原生的方法也还是比较简单的,具体使用可以看Android WebView与JavaScript的交互;JsBridge应该就是简单的封装了一下,让调用更加简单一些吧;

JsBridge

JSBridge是一座用JavaScript搭建起来的桥,一端是web,一端是native。我们搭建这座桥的目的也很简单,让native可以调用web的js代码,让web可以 “调用” 原生的代码

初始化布局

使用JsBridge需要使用BridgeWebView控件,其实这个控件就是重写了WebView,在WebView初始化的时候注入了一些JavaScript,便于我们之后的使用

  1. webView = findViewById(R.id.bridgeWebView);
  2. //加载本地HTML文件
  3. webView.loadUrl("file:///android_asset/test2.html");

HTML代码,放在assets文件下的HTML,test()方法暂时没有实现,里面我写了一个类似Toast的方法,来展示数据

  1. <html>
  2. <head>
  3. <title>js调用android原生代码</title>
  4. <meta http-equiv="Content-Type" content="text/html;charset=gb2312">
  5. <meta id="viewport" name="viewport"
  6. content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,minimal-ui">
  7. </head>
  8. <body>
  9. <br/>
  10. <li><a onclick="test()">点击调用Android的方法</a></li>
  11. <br/>
  12. </body>
  13. </html>
  14. <script>
  15. <!--一个类似ToastJavaScript方法,不用管怎么搞的-->
  16. function toast(msg,duration){
  17. duration=isNaN(duration)?3000:duration;
  18. var m = document.createElement('div');
  19. m.innerHTML = msg;
  20. 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;";
  21. document.body.appendChild(m);
  22. setTimeout(function() {
  23. var d = 0.5;
  24. m.style.webkitTransition = '-webkit-transform ' + d + 's ease-in, opacity ' + d + 's ease-in';
  25. m.style.opacity = '0';
  26. setTimeout(function() { document.body.removeChild(m) }, d * 1000);
  27. }, duration);
  28. }
  29. </script>

JavaScript调用Android方法

Java中使用下面这个方法就可以暴露方法给JavaScript,方法名为submitFromWebdata为JavaScript传进来的数据,通过function.onCallBack()方法返回数据给JavaScript

  1. //注册方法供JavaScript调用
  2. webView.registerHandler("submitFromWeb", new BridgeHandler() {
  3. @Override
  4. public void handler(String data, CallBackFunction function) {
  5. Toast.makeText(JsBridgeActivity.this, "从JavaScript接收到的数据为:" + data, Toast.LENGTH_SHORT).show();
  6. //返回数据给JavaScript
  7. function.onCallBack("Hello from Android");
  8. }
  9. });

使用test()方法,JavaScript中调用这个方法并传入数据进来,这里对返回的数据responseData进行展示

  1. <li><a onclick="test()">点击调用Android的方法</a></li>
  2. <script>
  3. function test(){
  4. WebViewJavascriptBridge.callHandler(
  5. 'submitFromWeb'
  6. , {'data': 'Hello form JavaScript'}
  7. , function(responseData) {
  8. toast(responseData)
  9. }
  10. );
  11. }
  12. </script>

库也提供了一个简单的没有回调的调用方式:

  1. webView.setDefaultHandler(new DefaultHandler());

Js调用的时候也可以不指定方法名:

  1. <script>
  2. function test2(){
  3. window.WebViewJavascriptBridge.send(
  4. {'data': 'Hello form JavaScript default'}
  5. , function(responseData) {
  6. toast(responseData)
  7. });
  8. }
  9. </script>

看了DefaultHandler的源码,暂时没想到有什么用,除非自己重写handler方法,和第一个用法相比的确是少了一个方法名

  1. public class DefaultHandler implements BridgeHandler{
  2. String TAG = "DefaultHandler";
  3. @Override
  4. public void handler(String data, CallBackFunction function) {
  5. if(function != null){
  6. function.onCallBack("DefaultHandler response data");
  7. }
  8. }
  9. }

Android调用JavaScript方法

这个东西看起来和JavaScript调用Android是差不多的,先在JavaScript中注册方法供Android调用,这个脚本放在标签后面就行了,为什么看起来这么复杂呢,因为必须先检测WebViewJavascriptBridge是否存在

  1. <script>
  2. function connectWebViewJavascriptBridge(callback) {
  3. if (window.WebViewJavascriptBridge) {
  4. callback(WebViewJavascriptBridge)
  5. } else {
  6. document.addEventListener(
  7. 'WebViewJavascriptBridgeReady'
  8. , function() {
  9. callback(WebViewJavascriptBridge)
  10. },
  11. false
  12. );
  13. }
  14. }
  15. connectWebViewJavascriptBridge(function(bridge) {
  16. bridge.registerHandler("functionInJs", function(data, responseCallback) {
  17. document.getElementById("show").innerHTML = ("data from Java: = " + data);
  18. if (responseCallback) {
  19. var responseData = "Javascript Says Right back aka!";
  20. responseCallback(responseData);
  21. }
  22. });
  23. })
  24. </script>

接下来在Android中调用就好了

  1. webView.callHandler("functionInJs", "执行JavaScript方法", new CallBackFunction() {
  2. @Override
  3. public void onCallBack(String data) {
  4. Toast.makeText(JsBridgeActivity.this, data, Toast.LENGTH_SHORT).show();
  5. }
  6. });

这其中有一个大坑,我手机是Android 9.0的,我下载了dome完全没问题,然后我按照demo方法在我的代码里面写,发现怎么搞都不行,JavaScript方法没有被调用,直到完全改成和demo一样,还是不行,我又改了gradle里面的各种配置,还是不行,最后我把依赖删除了,集成demo里面的那个library,然后好了

  1. repositories {
  2. // ...
  3. maven { url "https://jitpack.io" }
  4. }
  5. dependencies {
  6. compile 'com.github.lzyzsd:jsbridge:1.0.4'
  7. }

JsBridge的最后一个版本1.0.4(3年前的版本)是有问题的;这个项目在github上有100多个问题,最后代码一次提交是6个月前,感觉不是很靠谱,看的出来大家都是Fork下来自己修改的;

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注