Android WebView 与 Native 交互

Posted xyTianZhao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android WebView 与 Native 交互相关的知识,希望对你有一定的参考价值。

android WebView 与 Native 交互

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

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

先来看一下效果图

Android 与 H5 交互

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

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();
        

    
    

以上是关于Android WebView 与 Native 交互的主要内容,如果未能解决你的问题,请参考以下文章

Android WebView开发:WebView与Native交互

Android WebView 与 Native 交互

Android中使用WebView与JS交互全解析

js与native的交互

React Native WebView处理android硬件按钮

React Native - 如何在 React Native 应用程序中使用 WebView 显示我的网站通知(适用于 Android)