Android JS交互

1,228 阅读2分钟

项目接下来的任务中可能会需要H5与Android交互,用本篇文章记录一下JS交互的实现方案。

用于测试的Hmtl如下:

//Html文件,放在项目中的assets文件夹下
<!DOCTYPE html>
<html lang=zh-CN>
<head>
    <meta charset=utf-8>
    <title>test</title>
    <script>
        function callAndroid(){
           JsInterface.jsCallAndroid('JS测试参数');
        }

        function androidCall(params){
           document.getElementById("div_text").innerHTML = 'receiver js call , param is '+params;
           return 'JS返回参数';
        }

    </script>
</head>
<body>
<div id="div_text" style="width:800px;height:120px;font-size:24px"></div>
<button type="button" style="width:240px;height:88px;font-size:24px" onclick="callAndroid()">
    test_call_android
</button>
</body>
</html>

JS交互分为JS调用Android和Android调用JS,下面分别介绍一下。

JS调用Android

JS调用安卓有三种方法,分别是:

  1. 向WebView添加JavascriptInterface。
  2. 设置WebView的WebViewClent,通过重写shouldOverrideUrlLoading()方法进行处理。
  3. 设置WebView的WebViewChromeClient,通过重写onJsAlert()、onJsConfirm()、onJsPrompt()其中一个方法进行处理。

方法2、3需要前后端制定相应的协议,解析url或者message后根据协议进行处理,比较复杂。所以我个人更倾向于使用方法1。

实现代码如下:

//接口类
public class JsInterface {

    @JavascriptInterface
    public void jsCallAndroid(String params) {
        
    }
}
    
@SuppressLint("SetJavaScriptEnabled")
public class WebViewActivity extends Activity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout_web_view_activity);

        findViewById(R.id.tv_back).setOnClickListener(v -> finish());
        WebView webView = findViewById(R.id.web_view);

        //方法1
        //启用JavaScript
        webView.getSettings().setJavaScriptEnabled(true);
        //向webView添加JavascriptInterface
        webView.addJavascriptInterface(new JsInterface(), "JsInterface");
        
        //方法2
        webView.setWebViewClient(new WebViewClient(){
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
                try {
                    String decodeUrl = URLDecoder.decode(request.getUrl().toString(), StandardCharsets.UTF_8.toString());
                    //根据解析decodeUrl中的内容来进行响应的处理,这里不做演示。
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                return super.shouldOverrideUrlLoading(view, request);
            }
        });
        
        //方法3
        webView.setWebChromeClient(new WebChromeClient() {
            @Override
            public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
                //解析url或者message中的内容来进行响应的处理,这里不做演示。
                return super.onJsAlert(view, url, message, result);
            }

            @Override
            public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
                //解析url或者message中的内容来进行响应的处理,这里不做演示。
                return super.onJsConfirm(view, url, message, result);
            }

            @Override
            public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
                //解析url或者message中的内容来进行响应的处理,这里不做演示。
                return super.onJsPrompt(view, url, message, defaultValue, result);
            }
        });
        
        webView.loadUrl("file:///android_asset/index.html");
    }
}

Android调用JS

Android调用JS有两种方法,分别是:

  1. WebView.loadUrl()
  2. WebView.evaluateJavascript(),此方法在Android 4.4以上才能使用。

由于WebView.evaluateJavascript()在android4.4以上才可以使用,因此可以采用两者结合的方式,代码如下:


public class WebViewActivity extends Activity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout_web_view_activity);
       
        webView = findViewById(R.id.web_view);
        findViewById(R.id.tv_call_js).setOnClickListener(v -> {
            String params = "Android测试参数";
            String loadUrl = "javascript:androidCall('" + params + "')";
            if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
                //此方法没有返回值
                webView.loadUrl(loadUrl);
            } else {
                //此方法可以获取到JS的返回值
                webView.evaluateJavascript(loadUrl, new ValueCallback<String>() { 
                    @Override
                    public void onReceiveValue(String value) {
                        tv_result1.setText("receiver js return , value is " + value);
                    }
                });
            }
        });
    }
}

效果图

测试效果如下图: device-2021-12-25-132531.png