Android WebView 与 Native 交互

Android WebView 与 Native 交互

Android 开发过程中,难免会用到 WebView 展示一些 H5 页面,这样就免不了需要和 Native 进行一些信息的交互。比如获取当前登陆状态、保存一些值、调起相应页面或者功能等。

这里将 H5Android 交互这块封装成了一个模块,有兴趣可以看下 WNBridge,访问不了的可以下载资源

先来看一下效果图

在这里插入图片描述

Android 与 H5 交互

Android 调用 JS 代码还是比较方便的,直接调用 WebView 的相关方法即可

  • WebView.loadUrl()
  • WebView.evaluateJavascript()

WebView.evaluateJavascript() 是在 Android 4.4 才开始支持的,运行效率比 loadUrl() 高,同时还支持传入一个回调,方便 H5 返回相关信息。

webView.evaluateJavascript("callJsFunction()", new ValueCallback<String>() { 
 	 @Override
    public void onReceiveValue(String value) {
    		
    }
});

H5 与 Android 交互

H5Android 交互,大致有三种方式:

  • 拦截 WebViewClient 相关方法
  • 拦截 WebChromeClient 相关方法
  • 使用 Android 原生的 addJavascriptInterface 接口

在这里插入图片描述

接下来我们就逐个来分析一下这些骚操作。。。

addJavascriptInterface

这种方式是谷歌推荐使用的,也是 Android 原生的方法,可参考 官方文档。不过在 Android 4.2 之前有相关的安全漏洞,具体啥操作导致的漏洞在这就不说了,网上一大堆,可以自己搜索一下。这里简单贴上使用方法

class JsObject {
    @JavascriptInterface
    public String toString() { return "injectedObject"; }
 }
 webview.getSettings().setJavaScriptEnabled(true);
 webView.addJavascriptInterface(new JsObject(), "InjectedObject");
 webView.loadData("", "text/html", null);
 webView.loadUrl("javascript:alert(injectedObject.toString())");
 
 //在 js 代码中直接调用即可
 InjectedObject.toString()

拦截 WebViewClient

我们可以重写 WebViewClient 的以下相关方法进行拦截处理。可以根据定制的协议进行相应的分发调用。这里没有使用这种处理办法,而是将相关协议转换成 onJsPrompt 相关协议进行处理。

  • shouldOverrideUrlLoading()
  • shouldInterceptRequest()

具体实现如下

public static class WNBridgeWebViewClient extends WebViewClient {

        private WNJsInterface jsInterface;

        public WNBridgeWebViewClient(WNJsInterface jsInterface) {
            this.jsInterface = jsInterface;
        }

        @Override
        public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                String promptParams = convertUrl2PromptParams(request.getUrl().toString());
                if (!TextUtils.isEmpty(promptParams)) {
                    WNBridge.handleJsBridge(jsInterface,promptParams);
                    return true;
                }
            }
            return super.shouldOverrideUrlLoading(view, request);
        }

        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            String promptParams = convertUrl2PromptParams(url);
            if (!TextUtils.isEmpty(promptParams)) {
                WNBridge.handleJsBridge(jsInterface,promptParams);
                return true;
            }
            return super.shouldOverrideUrlLoading(view, url);
        }

        @Override
        public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                String promptParams = convertUrl2PromptParams(request.getUrl().toString());
                if (!TextUtils.isEmpty(promptParams)) {
                    WNBridge.handleJsBridge(jsInterface,promptParams);
                    return null;
                }
            }
            return super.shouldInterceptRequest(view, request);
        }

        @Override
        public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
            String promptParams = convertUrl2PromptParams(url);
            if (!TextUtils.isEmpty(promptParams)) {
                WNBridge.handleJsBridge(jsInterface,promptParams);
                return null;
            }
            return super.shouldInterceptRequest(view, url);
        }

        protected String convertUrl2PromptParams(String url) {
            return null;
        }

        protected String generatePromptParams(String method,String jsonParams,String callbackFunction,String transferParams){
            try {
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("method",method);
                jsonObject.put("methodParams",jsonParams);
                jsonObject.put("callbackFunction",callbackFunction);
                jsonObject.put("transferParams",transferParams);
                return jsonObject.toString();
            } catch (JSONException e) {
                e.printStackTrace();
                return null;
            }
        }
    }

拦截 WebChromeClient

我们可以重写 WebChromeClient 的以下相关方法进行拦截处理,重写那个方法都可以,原理都是相同的。然后根据定制的协议进行相应的分发调用。

  • onJsPrompt()
  • onJsAlert()
  • onJsConfirm()

具体实现如下

    public static class WNBridgeWebChromeClient extends WebChromeClient {

        private WNJsInterface jsInterface;

        public WNBridgeWebChromeClient(WNJsInterface jsInterface) {
            this.jsInterface = jsInterface;
        }

        @Override
        public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
            WNBridge.handleJsBridge(jsInterface,message);
            result.cancel();
            return true;
        }

        private void onDestroy(){
            jsInterface.onDestroy();
        }

    }
    
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值