1.对于Android调用JS代码的方法有2种:
通过WebView的loadUrl()

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/html">
    <head>
        <meta charset="UTF-8">
        <title>Test</title>
    </head>
    <body>
        <p>这是html内容</p>
    </body>
    <script>
        // Android需要调用的方法
        function callJS() {
            alert("Android调用了JS的callJS方法");
        }
    </script>
</html>
mWebView.loadUrl("javascript:callJS()");

通过WebView的evaluateJavascript()
优点:该方法比第一种方法效率更高、使用更简洁。
(1)因为该方法的执行不会使页面刷新,而第一种方法(loadUrl )的执行则会。
(2)Android 4.4(即>=19)后才可使用。

// 只需要将第一种方法的loadUrl()换成下面该方法即可
mWebView.evaluateJavascript("javascript:callJS()", new ValueCallback<String>() {
    @Override
    public void onReceiveValue(String value) {
        // 此处为JS返回的结果
    }
});

总结:
在这里插入图片描述

2.对于JS调用Android代码的方法有3种:
通过WebView的addJavascriptInterface() 进行对象映射
步骤一:定义一个与JS对象映射关系的Android类:WebViewJsBridge.java

public class WebViewJsBridge {

    @JavascriptInterface
    public void hello(String msg) {
        Log.d("WebViewJsBridge", msg);
    }
}

步骤二: WebViewJsBridge类对象映射到JS的Android对象

 // WebViewJsBridge类对象映射到JS的Android对象
        mWebView.addJavascriptInterface(new WebViewJsBridge(), "Android");

步骤三:js调用Android

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/html">
    <head>
        <meta charset="UTF-8">
        <title>Test</title>
    </head>
    <body>
        <p>这是html内容</p>
        <button type="button" id="button1" onclick="callAndroid1()">CallAndroid方式1</button>
    </body>
    <script>
        function callAndroid1(){
            // 由于对象映射,所以调用Android对象等于调用Android映射的对象
            Android.hello("js调用了android中的hello方法");
        }
    </script>
</html>

通过WebViewClient的shouldOverrideUrlLoading() 方法回调拦截url
(1)Android通过WebViewClient的回调方法==shouldOverrideUrlLoading()==拦截url
(2)解析该url的协议
(3)如果检测到是预先约定好的协议,就调用相应方法

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/html">
    <head>
        <meta charset="UTF-8">
        <title>Test</title>
    </head>
    <body>
        <p>这是html内容</p>
        <button type="button" id="button2" onclick="callAndroid2()">CallAndroid方式2</button>
    </body>
    <script>
        function callAndroid2(){
            // 约定的url协议为:js://webview?arg1=111&arg2=222
            document.location = "js://webview?arg1=111&arg2=222";
        }
    </script>
</html>
public class MainActivity extends AppCompatActivity {

    private WebView mWebView;
    private Button button;

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

        mWebView =(WebView) findViewById(R.id.webview);
        button = (Button) findViewById(R.id.button);

        WebSettings webSettings = mWebView.getSettings();
        // 设置与JS交互的权限
        webSettings.setJavaScriptEnabled(true);
        // 设置允许JS弹窗
        webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
        // 先载入JS代码,格式规定为:file:///android_asset/文件名.html
        mWebView.loadUrl("file:///android_asset/Test.html");
        // 复写WebViewClient类的shouldOverrideUrlLoading方法
        mWebView.setWebViewClient(new WebViewClient() {

            // 该重载方法不建议使用了,7.0系统以上已经摒弃了
            // shouldOverrideUrlLoading(WebView view, String url)此方法,
            // 如果要拦截URL,需要做兼容性处理,重写
            // shouldOverrideUrlLoading(WebView view, WebResourceRequest request)方法,
            // 获取得到的可正常使用的URL
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                return super.shouldOverrideUrlLoading(view, url);
            }

            @Override
            public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
                // 根据协议的参数,判断是否是所需要的url
                // 一般根据scheme(协议格式) & authority(协议名)判断(前两个参数)
                // 假定传入进来的url="js://webview?arg1=111&arg2=222"(同时也是约定好的需要拦截的)
                Uri uri;
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                    uri = request.getUrl();
                } else {
                    uri = Uri.parse(request.toString());
                }
                // 如果url的协议 = 预先约定的 js 协议,就解析往下解析参数
                if (uri.getScheme().equals("js")) {
                    // 如果 authority = 预先约定协议里的webview,即代表都符合约定的协议
                    // 所以拦截url,下面JS开始调用Android需要的方法
                    if (uri.getAuthority().equals("webview")) {
                        //执行JS所需要调用的逻辑
                        Log.d("TAG","JS调用了Android的方法");
                        // 可以在协议上带有参数并传递到Android上
                        HashMap<String, String> params = new HashMap<>();
                        Set<String> collection = uri.getQueryParameterNames();
                        String result = "Android回调给JS的数据为useid=123456";
                        view.loadUrl("javascript:returnResult(\"" + result + "\")");
                    }
                    return true;
                }
                return super.shouldOverrideUrlLoading(view, request);
            }
        });
    }
}

通过WebChromeClient的onJsAlert()、onJsConfirm()、onJsPrompt() 方法回调拦截JS对话框alert()、confirm()、prompt() 消息
在这里插入图片描述

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/html">
    <head>
        <meta charset="UTF-8">
        <title>Carson_Ho</title>
    </head>
    <body>
        <p>这是html内容</p>
        <button type="button" id="button3" onclick="callAndroid2()">CallAndroid方式3</button>
    </body>
    <script>
        function callAndroid3(){
            // 调用prompt()
            var result=prompt("js://webview?arg1=111&arg2=222");
            alert("demo " + result);
        }
    </script>
</html>
public class MainActivity extends AppCompatActivity {

    private WebView mWebView;
    private Button button;

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

        mWebView =(WebView) findViewById(R.id.webview);
        button = (Button) findViewById(R.id.button);

        WebSettings webSettings = mWebView.getSettings();
        // 设置与JS交互的权限
        webSettings.setJavaScriptEnabled(true);
        // 设置允许JS弹窗
        webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
        // 先载入JS代码,格式规定为:file:///android_asset/文件名.html
        mWebView.loadUrl("file:///android_asset/Test.html");
        // 由于设置了弹窗检验调用结果,所以需要支持js对话框
        // WebView只是载体,内容的渲染需要使用WebViewChromClient类去实现
        // 通过设置WebChromeClient对象处理JavaScript的对话框
        // 设置响应JS的Alert()函数
        mWebView.setWebChromeClient(new WebChromeClient() {
            // 拦截输入框(原理同方式shouldOverrideUrlLoading)
            // 参数message:代表promt())的内容(不是url)
            // 参数result:代表输入框的返回值
            @Override
            public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
                // 根据协议的参数,判断是否是所需要的url(原理同方式2)
                // 一般根据scheme(协议格式) & authority(协议名)判断(前两个参数)
                //传入进来的 url="js://webview?arg1=111&arg2=222"(同时也是约定好的需要拦截的)
                Uri uri = Uri.parse(message);
                // 如果url的协议 = 预先约定的 js 协议,就解析往下解析参数
                if ( uri.getScheme().equals("js")) {
                    // 如果 authority = 预先约定协议里的webview,即代表符合约定的协议
                    // 所以拦截url,下面JS开始调用Android需要的方法
                    if (uri.getAuthority().equals("webview")) {
                        // 执行JS所需要调用的逻辑
                        System.out.println("js调用了Android的方法");
                        // 可以在协议上带有参数并传递到Android上
                        HashMap<String, String> params = new HashMap<>();
                        Set<String> collection = uri.getQueryParameterNames();
                        //参数result:代表消息框的返回值(输入值)
                        result.confirm("Android回调给JS的数据为useid=123456");
                    }
                    return true;
                }
                return super.onJsPrompt(view, url, message, defaultValue, result);
            }

            // 拦截JS的警告框
            @Override
            public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
                return super.onJsAlert(view, url, message, result);
            }
            // 拦截JS的确认框
            @Override
            public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
                return super.onJsConfirm(view, url, message, result);
            }
        });
    }
}
Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐