美文网首页Android 基础知识我爱编程
WebView加载本地html、js,以及两者通信

WebView加载本地html、js,以及两者通信

作者: 一只在时光里流浪的大懒猫 | 来源:发表于2018-05-17 14:58 被阅读0次

    有这么一个需求:提高二维码的扫描速度(二维码自产自销)。方向有很多,比如从设备解码能力方面考虑(这是废话貌似);从二维码的复杂度方面考虑,即在数据量确定的情况下,如何有效地降低二维码复杂度,以提高设备扫码速度;从所使用的SDK方面考虑,zxing、zbar、qrcod,其实现方式不同,比如zxing是c++写的,zbar是c写的,而且,还可以考虑到它们扫描算法的不同。

    在android上,似乎google的zxing用的比较多,所以我选用了zxing。对于这个需求,我是从降低二维码复杂度的方面考虑的,也就是说,降低或者直接去除二维码的容错率。由于我这边的需求,二维码的生成扫描都是在设备上进行的,不存在二位码损坏的情况。zxing的查了下,其容错率,似乎只能设置到最低级别L,并不能完全去除,要不就去改源码。我使用的studio,gradle依赖的方式,改源码似乎不太理想。

    最后,剑走偏锋,决定使用网页端的Jquery二维码插件,因为我发现,这个工具可以设置correctLevel为0。这个方式,就需要使用WebView,去加载本地html及js,然后两者通信了。好的,废话不多说,下面开始。

    一、WebView加载本地html、js

    步骤如下:
    1.建立assets文件夹,并放入html,js文件。


    文件位置.png

    2.webview所在activity中:

    webView.loadUrl("file:///android_asset/code.html");
    // WebView允许js执行
    webView.getSettings().setJavaScriptEnabled(true);
    

    3.code.html中如何引用js,代码不多,整个贴出来好了,也可以顺便看下js是如何创建二维码的:

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8">
            <title></title>
        </head>
    
        <body>
            <table align="center" style="margin-top:20px">
                <tr>
                    <td>
                        <div id="qrcode"></div>
                    </td>
                </tr>
            </table>
        </body>
    
        <script type="text/javascript" src="file:///android_asset/js/jquery-1.10.2.min.js"></script>
        <script type="text/javascript" src="file:///android_asset/js/jquery.qrcode.min.js"></script>
    
        <script>
            jQuery(function(){
                            // 数据是调用activity中的方法获取到的,注意这里的 Native,下文中用到
                var data = window.Native.getData();
                jQuery("#qrcode").qrcode({
                    width:300,
                    height:300,
                    text:data,
                    correctLevel:0
                });
            })
        </script>
    
    </html>
    

    备注:
    我用的是android7.0的扫码设备,以上代码可以良好运行。但是网上有说,低版本js会不执行的,搜了下解决办法,加载网页可更改如下:

    String local = "file:///android_asset";
    String data = getFromAssets("code.html");
    webView.loadDataWithBaseURL(local, data, "text/html", "utf-8",  null);
    
        public String getFromAssets(String fileName) {
            String result = "";
            try {
                InputStream in = getResources().getAssets().open(fileName);
                // 获取文件的字节数
                int lenght = in.available();
                // 创建byte数组
                byte[] buffer = new byte[lenght];
                // 将文件中的数据读到byte数组中
                in.read(buffer);
                // 注意gradle中加入依赖 compile 'org.apache.httpcomponents:httpcore:4.4.4'
                result = EncodingUtils.getString(buffer, "UTF-8");
            } catch (Exception e) {
                e.printStackTrace();
            }
            return result;
        }
    
    

    二、Activity与html通信

    webview的方法addJavascriptInterface,可以向html注入一个java对象,这样,在js中就可以调用java方法了,具体使用如下:
    1.首先需要一个java对象,

    public class JSCallManager {
        private String data;
        public JSCallManager(String data) {
            this.data = data;
        }
    
        @JavascriptInterface
        public String getData() {
            return data;
        }
    }
    

    这里说明一下,@JavascriptInterface注解,在Android <=4.1.2 (API 16),WebView使用WebKit浏览器引擎,并未正确限制addJavascriptInterface的使用方法,在应用权限范围内,攻击者可以通过Java反射机制实现任意命令执行。在Android >=4.2 (API 17),WebView使用Chromium浏览器引擎,并且限制了Javascript对Java对象方法的调用权限,只有声明了@JavascriptInterace注解的方法才能被Web页面调用。(引用自https://www.jianshu.com/p/6309d243e4c0)。

    2.webview中如何使用

     webView.addJavascriptInterface(new JSCallManager(jsonData), "Native");
     webView.setWebChromeClient(new WebChromeClient());
    

    3.在js中方法如何调用

    var data = window.Native.getData();
    

    知道了如何使用了,那我这边就可以直接将json数据传给html,然后jquery插件根据json创建二维码了.这部分代码就不贴了,都一样。

    注意:
    这里的Native,需要与上一步骤中的addJavascriptInterface方法中传入的第二个参数相匹配。
    android4.2下,有一个安全漏洞,解决方法,可以看此链接https://blog.csdn.net/zhouyongyang621/article/details/47000041

    另,如何在java中调用js代码,步骤如下:
    1.在js中

    //在android代码中调用此方法
    function showInfoFromJava(msg){
       alert("来自客户端的信息:"+msg);
    }
    

    2.在activity中

        //在java中调用js代码
        public void sendInfoToJs() {
            String msg = "999";
            //调用js中的函数:showInfoFromJava(msg)
            webView.loadUrl("javascript:showInfoFromJava('" + msg + "')");
        }
    

    以上,参考自:https://blog.csdn.net/maiwc/article/details/54915134

    OK,到这里就完事儿了。现在来捋一下:
    1.webview加载本地html、js。几个关键点,先是文件的位置,然后是html中怎样加载javascript,最后是webview如何加载html(加载html这里感觉会有坑,虽然我没遇到,小伙伴们注意了~)。
    2.activity与html的相互通信。2个方面,一是如何向html中注入java对象,js中怎样调用该对象昂的方法;二是activity中如何调用js。
    两者如何通信掌握了,有些东西就很好办了。比如现在要实现一个功能,点击网页中的一个返回按钮,如何关闭当前activity?很好办,注入java对象时,顺便把context传进来,这样js调用该对象方法,在方法中就可以直接context.finish()了。

    相关文章

      网友评论

        本文标题:WebView加载本地html、js,以及两者通信

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