android webview js通讯方式

本文详细介绍了Android WebView与JavaScript进行通信的三种方法:1) 使用`@JavascriptInterface`注解注入Java对象;2) 通过WebView的schema拦截处理;3) 利用`WebChromeClient`的`onJsPrompt`进行JsPrompt弹窗拦截。每种方法都有其特点和适用场景,如js对象注入适合简单交互,schema拦截适用于特定URL请求处理,而JsPrompt则适用于无长度限制的通信。

android webview原生与js进行通讯有以下三种方式:

  一:js对象注入桥接

        通过WebSettings开启JavaScript支持,webSettings.setJavaScriptEnabled(true);然后注入js对象

public class JsInterface {
    public JsInterface() {
    }
    
    @JavascriptInterface
    public String getAppVersion() {
        return "1.0";
    }
}

JsInterface jsInterface = new JsInterface();
webView.addJavascriptInterface(jsInterface, "android");

在js中调用:window.android.getAppVersion();

二:webview的schema拦截方式处理,此种方法有schema的长度限制。

mWebView.setWebViewClient(new WebViewClient() {
            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
            }

            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                if(url.contains("schema://")){
                    HashMap<String, String> hashMap = paramStringToHashMap(url.replace("schema:///jsbridge/?",""));
                    if(hashMap.containsKey("action")){
                        switch (hashMap.get("action")) {
                            case "post":
                                getHttpPostData(view,hashMap.get("callback"),null,context);
                                break;
                            case "database":
                                getDataBaseData(context,view,hashMap.get("callback"),null);
                                break;
                        }
                    }
                } else {
                    view.loadUrl(url);
                }
                return true;
            }

            @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
            @Override
            public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
                WebResourceResponse intercepted = null;
                if (request.getUrl().toString().contains("file:") &&(
                        request.getUrl().toString().endsWith("js") || request.getUrl().toString().endsWith("css")) ) {
                    InputStream localCopy = null;
                    try {
                        localCopy = new FileInputStream(request.getUrl().toString().replace("file:",""));
                    } catch (IOException e) {
                        e.printStackTrace();
                    }

                    intercepted = request.getUrl().toString().endsWith("css")?
                            new WebResourceResponse("text/css", "UTF-8", localCopy)
                            :
                            new WebResourceResponse("text/javascript", "UTF-8", localCopy);
                    if (intercepted != null) {
                        if(request.getUrl().toString().endsWith("css"))
                            intercepted.setMimeType("text/css");
                        else
                            intercepted.setMimeType("text/javascript");
                    }
                }
                return intercepted;
            }

            @Override
            public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
                handler.proceed();
            }
        });


/**
     * todo url字符串转参数集合
     * @param url 地址
     * @return 返回执行的javascript字符串
     */
    public static HashMap<String, String> paramStringToHashMap(String url) {
        HashMap<String, String> hashMap = new HashMap<>();
        String[] array = url.split("&");
        for(String item:array) {
            if(item.indexOf("=") >= 0) {
                String[] valueArray = item.split("=");
                hashMap.put(valueArray[0],valueArray[1]);
            }
        }
        return hashMap;
    }

public static void getHttpPostData(WebView webView,String callBackMethod,JsPromptResult results,Context context) {
        MainModel.getInstance().subscribe1(new CallBack() {
            @Override
            public void sucess(String result) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                    if(results != null)
                        results.confirm(result);
                    webView.evaluateJavascript(executeJsStr(callBackMethod, result),null);
                } else {
                    webView.loadUrl(executeJsStr(callBackMethod, result));
                }
            }

            @Override
            public void failed(String result) {

            }
        },context);
    }

    public static void getDataBaseData(Context context, WebView webView,String callBackMethod,JsPromptResult results) {
        DBHelp.getUser(context, new CallBack() {
            @Override
            public void sucess(String result) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                    if(results != null)
                        results.confirm(result);
                    webView.evaluateJavascript(executeJsStr(callBackMethod, result),null);
                } else {
                    webView.loadUrl(executeJsStr(callBackMethod, result));
                }
            }

            @Override
            public void failed(String result) {

            }
        });
    }

js代码部分:

function invoke(url, action, callback) {
        url += "?action=" + action;
        var callbackName = ''
        if (typeof callback === 'string') {
            callbackName = callback
        } else {
            callbackName = action + Date.now()
            window[callbackName] = callback
        }
        url += '&callback=' + callbackName;
        var iframe = document.createElement('iframe');
        iframe.style.display = 'none';
        iframe.src = url; // 重要!此处会发送连接,会被webviwe捕获到
        var body = document.body;
        body.appendChild(iframe);
        setTimeout(function () {
            body.removeChild(iframe);
            iframe = null;
        });
    }
    invoke('schema:///jsbridge/?','post',function(res){
         console.log("回调成功",res);
         alert(res);
    });

三:JsPrompt弹窗拦截,此种方法没有长度限制。

mWebView.setWebChromeClient(new WebChromeClient() {

            @Override
            public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
                return true;
            }

            @Override
            public void onReceivedTitle(WebView view, String h5Title) {
                super.onReceivedTitle(view, h5Title);
            }

            @Override
            public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
                return super.onConsoleMessage(consoleMessage);
            }

            @Override
            public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {// 此方法先于shouldOverrideUrlLoading执行
                //对message进行处理
                if(message.contains("schema://")){
                    HashMap<String, String> hashMap = paramStringToHashMap(defaultValue);
                    if(hashMap.containsKey("action")){
                        switch (hashMap.get("action")) {
                            case "post":
                                getHttpPostData(view,hashMap.get("callback"),result,context);
                                break;
                            case "database":
                                getDataBaseData(context,view,hashMap.get("callback"),result);
                                break;
                        }
                    }
                    return true;
                } else {
                    return false;
                }
            }
        });

js代码部分

function windowPromote(url,action,callback) {
        var param = "action=";
        param += action;
        var callbackName = ''
        if (typeof callback === 'string') {
            callbackName = callback
        } else {
            callbackName = action + Date.now()
            window[callbackName] = callback
        }
        param += '&callback=' + callbackName;
        window.prompt(url, param);
    }

function callBackMethod(param1) {
        document.getElementById('container').innerHTML = param1;
    }
    windowPromote("schema:///jsbridge/", 'database',callBackMethod);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值