webview总结

作者: 后来Memory | 来源:发表于2019-01-18 13:45 被阅读12次

    一.webview加载白屏或者加载表格界面无法显示

    什么都别管,先把这坨设置丢上去

            pullToRefreshWebView.getSettings().setBlockNetworkImage(false);
            pullToRefreshWebView.getSettings().setJavaScriptEnabled(true);
            pullToRefreshWebView.getSettings().setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
            pullToRefreshWebView.setHorizontalScrollBarEnabled(false);
            pullToRefreshWebView.setHorizontalScrollbarOverlay(false);
            pullToRefreshWebView.getSettings().setBuiltInZoomControls(true);
            pullToRefreshWebView.getSettings().setUseWideViewPort(true);
            pullToRefreshWebView.getSettings().setLoadWithOverviewMode(true);
            pullToRefreshWebView.getSettings().setSavePassword(false);
            pullToRefreshWebView.getSettings().setSupportZoom(false);
            pullToRefreshWebView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
            pullToRefreshWebView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
            pullToRefreshWebView.getSettings().setAppCacheEnabled(true);
            pullToRefreshWebView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
            pullToRefreshWebView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
            pullToRefreshWebView.getSettings().setAllowFileAccess(true);
            pullToRefreshWebView.getSettings().setSaveFormData(false);
            pullToRefreshWebView.getSettings().setLoadsImagesAutomatically(true);
            pullToRefreshWebView.getSettings().setDomStorageEnabled(true);
    

    二.webview与JS的交互
    1. 调用js的方法, 前提设置.setJavaScriptEnabled(true); 必须的

        两种方式:  第一种通过webview.loadurl()  ,  第二种mWebView.evaluateJavascript();
      
        两种方法却别在于第一种会刷新界面,第二种只能在4.4以后使用,并且可以获取JS的返回值!
        
        loadurl()具体使用
    
         String open_id = SpUtils.getString(this, Constant.OPEN_ID, "");
          String userNmae = SpUtils.getString(this, Constant.USER_NAME, "");
          String userHead = SpUtils.getString(this, Constant.USER_HEAD, "");
          userinf_Url = "javascript:appLogin('" + open_id + "'," + "'" + userHead + "','" + userNmae + "')";
    
      appLogin是JS的方法名,open_id ,userHead ,userNmae 是相关参数! 也就是将整个方法拼接成一个字符串
    
      然后再webview加载完毕之后再去调用,pagefinished方法!
    
      @Override
                public void onPageFinished(WebView view, String url) {
                    web.post(new Runnable() {
                        @Override
                        public void run() {
                            web.loadUrl(userinf_Url);
                        }
                    });
                }
    
    在某些动态获取值的时候,在移动端处理完数据之后需要再次传递,重新加载一次webview.reload()接可以再次调用方法!
    也就是loadurl方法在调用JS方法的时候每次都需要刷新界面
    
     方法二此方法需要注意只有在4.4以上才能使用
    
      if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) {
      mWebView.evaluateJavascript("javascript:appLogin()", new ValueCallback<String>() {
        @Override
        public void onReceiveValue(String value) {
                   LoginBean loginBean =  MyApplicaytion,getInstance,gson.fromJson(value,LoginBean.class);
                  //这个地方处理返回值
            }
       });
    

    }

    加载本地html调用本地方法就不在介绍,网上很多!

    3.JS调用本地方法
    通过WebView的addJavascriptInterface()进行对象映射

    1.定义一个与JS对象有映射关系的Android类:AndroidtoJs
    
     public class AndroidtoJs extends Object {
            // 定义JS需要调用的方法
            // 被JS调用的方法必须加入@JavascriptInterface注解
            @JavascriptInterface
            public void login() {
                //此方法就直接跳转到 购买成功的界面,同时还有另外一个方法判断是否需要关闭当前的界面
                if (!Application.iwxapi.isWXAppInstalled()) {
                    Toast.makeText(MainActivity.this, "请先安装微信", Toast.LENGTH_SHORT).show();
                } else {
                    final SendAuth.Req req = new SendAuth.Req();
                    req.scope = "snsapi_userinfo";
                    req.state = "wechat_sdk_demo_test";
                    Application.iwxapi.sendReq(req);
                }
            }
    
            @JavascriptInterface
            public String toString() {
                return "androids";    //JS端通过该参数调用方法
            }
        }
    

    加载本地js方法, html文件放在assets下

      mWebView.loadUrl("file:///android_asset/htmls_two.html");
      way =  "javascript:wxjswap"+"('"+url+"')";
    

    JS端代码

     function 方法名(){
            // 由于对象映射,所以调用test对象等于调用Android映射的对象
                androids.login();
            //注意此处定义的Androids和移动端定义的要一样
             }
    

    上诉交互方是仅仅是在项目中使用到的!更多方式参考这篇文章
    https://www.jianshu.com/p/345f4d8a5cfa

    三 webciew广告拦截
    webview加载界面的时候会出现很多小广告,有运营商的也有一些乱七八糟的!最简单最暴力的方式就是只要不是我们项目域
    名下的统统拦截!
    具体方式如下:
    首先定义一个数组

     <string-array name="legal_domain">
         <item>skin.se.360.cn</item>
         <item>m.gooooal.com</item>
     
     </string-array>
    
      把项目更中用到的所有域名全部写上去!是全部包括图片啥的,如果有一个用到的域名没有写上去可能会导致界面加载不出
      来,也可以在通过查看加载的所有域名来看有没有被漏掉的!
    
      拦截工具类
    
    public class ADFilterTool {
       /**
        * 正则表达式
        */
       private static String PATTERN = " ";
    
       static {
           initPattern();
       }
    
       /**
        * 初始化pattern
        */
       private static void initPattern() {
           PATTERN = getPatternStr();
       }
    
       /**
        * 判断url的域名是否合法
        * <p>
        * 域名是否合法:自己项目中使用的域名,为合法域名;其它域名皆为不合法域名,进行屏蔽
        *
        * @param url
        * @return
        */
       public static boolean hasNotAd(String url) {
           if (TextUtils.isEmpty(url)) {
               LogUtils.e("拦截判断里面获取到的是空的");
               return false;
           }
           if (TextUtils.isEmpty(PATTERN)) {
               initPattern();
           }
           if (Pattern.matches(PATTERN, url)) {
      
               return true;
           }
           return false;
       }
    
       /**
        * 拼接正则表达式
        *
        * @return
        */
       private static String getPatternStr() {
           String[] adUrls = Application.getInstance().getResources().getStringArray(R.array.legal_domain);
           if (null != adUrls && adUrls.length > 0) {
               StringBuffer sb = new StringBuffer("^(https|http)://.*(");
               for (String a : adUrls) {
                   if (null != a && a.length() > 0) {
                       sb.append(a).append("|");
                   }
               }
               return sb.substring(0, sb.length() - 1) + ").*";
           }
           return null;
       }
    }
    

    hasNotAd方法里面可以看到所有加载的域名,当然也可以通过webview的shouldInterceptRequest()方法

    具体使用在webview的shouldInterceptRequest方法调用

     @Override
                public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
                    if (ADFilterTool.hasNotAd(url)) {
                    return super.shouldInterceptRequest(view, url);
                    } else {
                        return new WebResourceResponse(null, null, null);
                    }
                }
    

    上诉方法完美的解决了项目当中的广告页面!

    四:webview重定向,以及地址中包含alipay,weixin等敏感字段时无法加载界面的处理方法!
    我自己的项目中有些直接出现了alipays,weixin 有些则是alipayqr等相关字眼,加载的地址中包含这些字段时Webview就会无
    法加载!,解决方案就是通过重定向到浏览器当中去打开这些界面!

       @Override
                    public boolean shouldOverrideUrlLoading(WebView view, String url) {
                        LogUtils.e("跳转链接:" + url);
                        String newUrl = "";
                        if (url.contains("alipayqr")){
                            newUrl = url.replace("alipayqr", "alipays");
                        }
    
                        LogUtils.e("修改后的跳转链接" + newUrl);
                        if(newUrl.startsWith("alipays://")|| url.contains("weixin://") ){
                            Intent intent = new Intent();
                            intent.setAction(Intent.ACTION_VIEW);
                            if (url.contains("weixin://")){
                                intent.setData(Uri.parse(url));
                            }else {
                                intent.setData(Uri.parse(newUrl));
                            }
                            try {
                                startActivity(intent);
                            }catch (Exception e){
                                ToasUtils.showToast("充值失败,请联系客服");
                            }
    
                            return true;
                        }
                        return super.shouldOverrideUrlLoading(view, url);
                }
    

    五。webview自定义报错界面
    加载页面出错的时候webview原生报错很丑,有些情况下还会出现域名当这些信息我们不想直接向客户展示的时候就需要自
    定义报错界面!

        onReceivedError();通过这个方法来进行处理
    
               @TargetApi(Build.VERSION_CODES.M)
               @Override
               public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
                   view.removeAllViews();
                   Log.e("log","报错拉");
                   rlError.setVisibility(View.VISIBLE);   //自定义的报错界面
                   view.loadUrl("about:blank");
               }
             
    
    
    
               @Override
               public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
                   if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                       return;
                   }
                   Log.e("log","报错拉");
                   rlError.setVisibility(View.VISIBLE);
                   view.removeAllViews();
                   view.loadUrl("about:blank");
               }
    
    
    注意如果不加上view.loadUrl("about:blank");这行代码的话,webview的原生报错界面很多情况下还是会一闪而过!
    

    相关文章

      网友评论

        本文标题:webview总结

        本文链接:https://www.haomeiwen.com/subject/fzhndqtx.html