美文网首页二楼后座android
Android使用JsBridge与JavaScript交互

Android使用JsBridge与JavaScript交互

作者: Tyhj | 来源:发表于2019-03-11 16:12 被阅读58次

原生方法

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

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>

JavaScript调用Android方法

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

        //注册方法供JavaScript调用
        webView.registerHandler("submitFromWeb", new BridgeHandler() {
            @Override
            public void handler(String data, CallBackFunction function) {
                Toast.makeText(JsBridgeActivity.this, "从JavaScript接收到的数据为:" + data, Toast.LENGTH_SHORT).show();
                //返回数据给JavaScript
                function.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";
    
    @Override
    public void handler(String data, CallBackFunction function) {
        if(function != null){
            function.onCallBack("DefaultHandler response data");
        }
    }
}

Android调用JavaScript方法

这个东西看起来和JavaScript调用Android是差不多的,先在JavaScript中注册方法供Android调用,这个脚本放在</body>标签后面就行了,为什么看起来这么复杂呢,因为必须先检测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() {
            @Override
            public 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下来自己修改的;

项目源码:https://github.com/tyhjh/WebViewH.git

相关文章

网友评论

    本文标题:Android使用JsBridge与JavaScript交互

    本文链接:https://www.haomeiwen.com/subject/imybpqtx.html