美文网首页前端vue学习
Android webview 与 js(Vue) 交互

Android webview 与 js(Vue) 交互

作者: solocoder | 来源:发表于2018-11-17 11:20 被阅读0次

    js 与原生交互分为两种情况:js 调用原生方法,原生调用 js 方法。

    本文将对这两种情况分别讲解,H5 端用 vue 实现。

    一、前期准备(Vue项目准备)

    本文的 H5 端用Vue 实现,所以在正式开始前先把 Vue 项目环境准备好。

    项目写好后,执行 npm run serve 命令启动项目,启动成功后会在命令行看到两个地址:

    http://localhost:8080/http://10.0.0.188:8080/

    10.0.0.188 是我本机的 ip 地址,每个人的不一样。

    在电脑的浏览器访问的话哪个都行,但在手机或模拟器访问的话需要用第二个带 ip 地址的,且要保证手机跟电脑连接同一个 wifi 或在同一网段。

    注意:这里用的是 vue-cli 3.0,运行命令跟 vue-cli 2.X 有所区别。详情请自行查询官方文档。

    启动成功后在 Android 项目中将 http://10.0.0.188:8080/ 地址配置给 WebView 即可

    Intent intent = new Intent(getActivity(), ProgressWebviewActivity.class);
    intent.putExtra("url", "http://10.0.0.188:8080/");
    startActivity(intent);
    

    到此,在手机中就可以访问 Vue 项目了。

    二、Android 原生调用 JS 中的方法

    Android 调用 JS 有两种方式,都是通过 WebView 的方法:

    1. webview.loadUrl()
    2. webview.evaluateJavascript()

    二者区别:

    1. loadUrl() 会刷新页面,evaluateJavascript() 则不会使页面刷新,所以 evaluateJavascript() 的效率更高

    2. loadUrl() 得不到 js 的返回值,evaluateJavascript() 可以获取返回值

    3. evaluateJavascript() 在 Android 4.4 之后才可以使用

    要实现的效果:

    如下图,页面上有一行文字 ”哈哈“,要在 WebView 页面加载完的时候通过 Android 原生代码将这行字改为 ”我通过原生方法改变了文字“ + Android 传递过来的参数,并给 Android 返回一个字符串 ”js调用成功“。

    2.1 Vue 代码

    先看 Vue 中代码怎么写

    mounted() {
        //将要给原生调用的方法挂载到 window 上面
        window.callJsFunction = this.callJsFunction
    },
    data() {
        return {
            msg: "哈哈"
        }
    },
    methods: {
        callJsFunction(str) {
            this.msg = "我通过原生方法改变了文字" + str
            return "js调用成功"
        }
    }
    

    methods 中定义一个供 Android 调用的方法 callJsFunction(str) , 并可接收一个参数 str,然后改变页面中的文字。

    如果只是在 methods 中定义方法,原生调用会找不到这个方法。所以要在页面加载的时候将方法挂载在 window 上,这样 WebView 就可以拿到此方法了。注意,这步很重要一定要写!

    注意一个细节,this.callJsFunction 后面不要加括号 (),加括号相当于直接调用了。

    总结起来 Vue 中要做的事情就两步:

    1. methods 中定义方法
    2. mounted 中将方法挂载在 window

    2.2 Android 中代码

    需要等页面加载完在 WebViewonPageFinished 方法中写调用逻辑,否则不会执行。

    2.2.1 loadUrl() 实现

    tbsWebView.setWebViewClient(new WebViewClient() {
                @Override
                public boolean shouldOverrideUrlLoading(WebView view, String url) {
                    view.loadUrl(url, headerMap);
                    return true;
                }
    
                @Override
                public void onPageFinished(WebView webView, String s) {
                    super.onPageFinished(webView, s);
                    //安卓调用js方法。注意需要在 onPageFinished 回调里调用
                    tbsWebView.post(new Runnable() {
                        @Override
                        public void run() {
                            tbsWebView.loadUrl("javascript:callJsFunction('soloname')");
                        }
                    });
                }
            });
        }
    });
    

    如果不需要传参数,把参数去掉即可 tbsWebView.loadUrl("javascript:callJsFunction()");

    2.2.2 evaluateJavascript() 实现

    其他地方跟loadUrl()一样,只是把 tbsWebView.loadUrl("javascript:callJsFunction('soloname')"); 替换掉

    @Override
    public void onPageFinished(WebView webView, String s) {
        super.onPageFinished(webView, s);
        //安卓调用js方法。注意需要在 onPageFinished 回调里调用
        tbsWebView.post(new Runnable() {
            @Override
            public void run() {
                tbsWebView.evaluateJavascript("javascript:callJsFunction('soloname')", new ValueCallback<String>() {
                    @Override
                    public void onReceiveValue(String s) {
                        Logger.d("js返回的结果: " + s);
                    }
                });
            }
        });
    }
    

    可以看到页面更新了,第二种方法也拿到了返回的结果。

    三、JS 调用 Android 原生方法

    对于JS调用Android代码的方法有3种:

    1. 通过 WebViewaddJavascriptInterface() 进行对象映射
    2. 通过 WebViewClientshouldOverrideUrlLoading()方法回调拦截 url
    3. 通过 WebChromeClientonJsAlert()onJsConfirm()onJsPrompt()方法回调拦截JS对话框alert()confirm()prompt() 消息

    对比: 第一种最简洁,但在 Android 4. 2 以下存在漏洞;第二种和第三种使用复杂,但不存在漏洞问题。

    由于目前的设备系统版本基本都在 4.2 以上,所以用第一种就可以了,简单快捷。时间有限本文只实现第一种,第二种和第三种就不实现了,想了解的可以参考 这篇文章

    3.1 效果展示

    要实现的效果就是点击 H5 页面上的按钮,弹出 Android 原生的 Toast

    3.2 Vue 代码

    methods: {
      showAndroidToast() {
        $App.showToast("哈哈,我是js调用的")
      }
    }
    

    methods 中定义方法 showAndroidToast() , 点击页面上按钮 "调用Android原生Toast" 时调用。

    3.3 Android 代码

    新建类 JsJavaBridge

    public class JsJavaBridge {
    
        private Activity activity;
        private WebView webView;
    
        public JsJavaBridge(Activity activity, WebView webView) {
            this.activity = activity;
            this.webView = webView;
        }
    
        @JavascriptInterface
        public void onFinishActivity() {
            activity.finish();
        }
    
        @JavascriptInterface
        public void showToast(String msg) {
            ToastUtils.show(msg);
        }
    }
    

    然后通过 WebView 设置 Android 类与 JS 代码的映射

    tbsWebView.addJavascriptInterface(new JsJavaBridge(this, tbsWebView), "$App");
    

    这里将类 JsJavaBridge 在 JS 中映射为了 $App,所以在 Vue 中可以这样调用 $App.showToast("哈哈,我是js调用的")

    以上就是 Android 与 JS 的互相调用。


    作者正在写一个有趣的开源项目 coderiver,致力于打造全平台型全栈精品开源项目。

    coderiver 中文名 河码,是一个为程序员和设计师提供项目协作的平台。无论你是前端、后端、移动端开发人员,或是设计师、产品经理,都可以在平台上发布项目,与志同道合的小伙伴一起协作完成项目。

    coderiver 河码 类似程序员客栈,但主要目的是方便各细分领域人才之间技术交流,共同成长,多人协作完成项目。暂不涉及金钱交易。

    计划做成包含 pc端(Vue、React)、移动H5(Vue、React)、ReactNative混合开发、Android原生、微信小程序、java后端的全平台型全栈项目,欢迎关注。

    项目地址:https://github.com/cachecats/coderiver

    您的鼓励是我前行最大的动力,欢迎点赞,欢迎送小星星✨ ~

    相关文章

      网友评论

        本文标题:Android webview 与 js(Vue) 交互

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