Android与JS通信

Android调用Js

  • loadUrl()

通过WebView的loadUrl()方法调用Js方法。

mWebView.loadUrl("javascript:callJsDefault()");

 //在android调用js有参的函数的时候参数要加单引号
String param = "\'来自Android的参数\'";
mWebView.loadUrl(String.format("javascript:callJsWithParams(%s)", param));
  • evaluateJavascript()

通过WebView的evaluateJavascript()方法调用Js方法,此方法可以获得Js方法执行后的返回值。

mWebView.evaluateJavascript("javascript:callJsWithReturn(2,3)",
value -> Toast.makeText(MainActivity.this, "Js的计算结果为:" + value, Toast.LENGTH_SHORT).show());

Js调用Android

  • addJavascriptInterface()

创建一个类通过WebView的addJavascriptInterface()方法提供给Js使用,Js通过它调用我们在Android中写好的方法。

public class JsCallAndroid {

    private Context mContext;
    public JsCallAndroid(Context context) {
        mContext = context;
    }
    
    //供Js调用的方法要加JavascriptInterface注解
    @JavascriptInterface
    public void hello(String msg){
        Toast.makeText(mContext,msg,Toast.LENGTH_SHORT).show();
    }
    
    /*...*/
}
//"android"为Js中调用对象的名称
mWebView.addJavascriptInterface(new JsCallAndroid(this), "android");

Js中调用

function callAndroid(){
        // 由于对象映射,所以调用android对象等于调用Android映射的对象
            android.hello("js调用了android中的hello方法!!!");
        }
  • alert()、confirm()、prompt()

通过重写WebChromeClient的onJsAlert()、onJsConfirm()、onJsPrompt()方法响应Js的alert()、confirm()、prompt()调用。

mWebView.setWebChromeClient(new WebChromeClient() {
            @Override
            public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
                AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
                builder.setTitle("Alert")
                        .setMessage(message)
                        .setPositiveButton(android.R.string.ok, (dialog, which) -> result.confirm())
                        .setNegativeButton(android.R.string.cancel, (dialog, which) -> result.cancel())
                        .setCancelable(false)
                        .create()
                        .show();
                return true;
            }

        });

Js代码

function callAndroidAlert(){
            alert("来自Js的提示");
        }
  • shouldOverrideUrlLoading

Js与Android定义一组特殊的URL,然后重写WebViewClient的shouldOverrideUrlLoading()方法,拦截url,解析url包含的数据,针对不同数据做不同操作。

mWebView.setWebViewClient(new WebViewClient() {

            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                if (url.contains("protocol://webview?")) {
                    Map<String, String> dataMap = getUrlDataMap(url);
                    if (dataMap != null) {
                        switch (dataMap.get("operate")) {
                            case "toast":
                                Toast.makeText(MainActivity.this, dataMap.get("msg"), Toast.LENGTH_LONG).show();
                                break;
                            case "startActivity":
                                /*...*/
                                break;
                            default:
                                break;
                        }
                    }
                } else
                    view.loadUrl(url);
                return true;
            }
        });

    /**
     * 获取URl所包含的数据
     * @param url
     * @return 数据的map集合
     */
    private Map<String, String> getUrlDataMap(String url) {
        Map<String, String> map = null;
        try {
            url = URLDecoder.decode(url, "utf-8");
            String substring = url.substring(url.indexOf("?") + 1);
            String[] split = substring.split("&");
            map = new HashMap<>();
            String[] entry;
            for (String s : split) {
                entry = s.split("=");
                map.put(entry[0], entry[1]);
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return map;
    }

Js代码

//这里用一个a标签做示例
<a href="protocol://webview?operate=toast&msg=Js通过url控制Android执行方法">通过url执行方法</a>

扩展方式

Js和Android的交互还可以通过JsBridge来完成,JsBridge是一个开源的第三方库,其作用和名字一样,可以作为Js和Android之间的桥梁进行沟通。使用方法在Github上都有介绍,网上也有挺多博客的,有兴趣的自己搜一下,我就不写了。

本次示例Html代码

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
</head>
<body>
<p id="content"></p>
<p><button type="button" id="button1" οnclick="callAndroid()">点击按钮则调用callAndroid函数</button></p>
<a href="protocol://webview?operate=toast&msg=Js通过url控制Android执行方法">通过url执行方法</a>
<script type="text/javascript">

        var content = document.getElementById("content");

        function callAndroid(){
        // 由于对象映射,所以调用android对象等于调用Android映射的对象
            android.hello("js调用了android中的hello方法!!!");
        }

        function callAndroidAlert(){
            alert("来自Js的提示");
        }

         // Android需要调用的方法
         function callJsDefault(){
            content.innerHTML='Android调用了Js的默认方法';
         }

         function callJsWithParams(params){
            content.innerHTML = "Android调用了Js的带参方法:" + params;
         }

         function callJsWithReturn(a,b){
            return a+b;
         }

    </script>
</body>
</html>

总结

以上所有的Js和Android的交互方法,各有各的特点,其中Js调用Android的方法中,使用拦截Url的方式比较多,因为考虑到要兼顾ios的通用性,拦截Url是两个端实现成本最低的一种,如果不需要考虑ios端,那么随便哪一种都可以。

发布了57 篇原创文章 · 获赞 26 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/Ever69/article/details/104518055