美文网首页
WebView基础

WebView基础

作者: 拙峰朽木 | 来源:发表于2017-10-17 17:51 被阅读27次

    之前webView的使用很大多局限于显示网页,现在有机会重头梳理下整理成如下笔记:

    基本用法

            //方式1. 加载一个网页:
            mWebView.loadUrl("https://www.baidu.com");
            //方式2:加载apk包中的html页面
            mWebView.loadUrl("file://android_asset/test.html");
            //方式3:加载手机本地的html页面
            mWebView.loadUrl("content://com.example.frc.myapplication/sdcard/test.html");
    
            // 方式4: 加载 HTML 页面的一小段内容
            mWebView.loadData(htmlStr, "text/html", null);
            // 参数说明:
            // 参数1:需要截取展示的内容
            // 内容里不能出现 ’#’, ‘%’, ‘\’ , ‘?’ 这四个字符,若出现了需用 %23, %25, %27, %3f 对应来替代,否则会出现异常
            // 参数2:展示内容的类型
            // 参数3:字节码
    

    WebView 的状态

    //激活WebView为活跃状态,能正常执行网页的响应
    webView.onResume() ;
    
    //当页面被失去焦点被切换到后台不可见状态,需要执行onPause
    //通过onPause动作通知内核暂停所有的动作,比如DOM的解析、plugin的执行、JavaScript执行。
    webView.onPause();
    
    //当应用程序(存在webview)被切换到后台时,这个方法不仅仅针对当前的webview而是全局的全应用程序的webview
    //它会暂停所有webview的layout,parsing,javascripttimer。降低CPU功耗。
    webView.pauseTimers()
    //恢复pauseTimers状态
    webView.resumeTimers();
    
    //销毁Webview
    //在关闭了Activity时,如果Webview的音乐或视频,还在播放。就必须销毁Webview
    //但是注意:webview调用destory时,webview仍绑定在Activity上
    //这是由于自定义webview构建时传入了该Activity的context对象
    //因此需要先从父容器中移除webview,然后再销毁webview:
    rootLayout.removeView(webView); 
    webView.destroy();
    
    

    结合Activity的状态使用:

     @Override
        public boolean onKeyDown(int keyCode, KeyEvent event) {
            //在当前Activity中处理并消费掉该 Back 事件
            if ((keyCode == KEYCODE_BACK) && mWebView.canGoBack()) {
                mWebView.goBack();
                return true;
            }
            return super.onKeyDown(keyCode, event);
        }
    
        @Override
        protected void onResume() {
            super.onResume();
            mWebView.onResume();
        }
    
        @Override
        protected void onPause() {
            super.onPause();
            mWebView.onPause();
        }
    
        @Override
        protected void onStop() {
            super.onStop();
        }
    
        @Override
        protected void onDestroy() {
      if (mWebView != null) {
                //清除网页访问留下的缓存
                //由于内核缓存是全局的因此这个方法不仅仅针对webview而是针对整个应用程序.
    //        mWebView.clearCache(true);
    
                //在关闭了Activity时,如果Webview的音乐或视频,还在播放。就必须销毁Webview
                mWebView.loadDataWithBaseURL(null, "", "text/html", "utf-8", null);
                mWebView.clearHistory();
    
                //但是注意:webview调用destory时,webview仍绑定在Activity上
                //这是由于自定义webview构建时传入了该Activity的context对象
                //因此需要先从父容器中移除webview,然后再销毁webview:
                mRootView.removeView(mWebView);
                mWebView.destroy();
                mWebView = null;
            }
            super.onDestroy();
                }
    

    WebSettings

    获取WebSettings

            //获取WebSettings
            WebSettings webSettings = mWebView.getSettings();
            setWebSettings(webSettings);
    

    一些常用的设置:

    SuppressLint("SetJavaScriptEnabled")
        private void setWebSettings(WebSettings webSettings) {
            webSettings.setJavaScriptEnabled(true);//支持JavaScript
            // Your code should not invoke setJavaScriptEnabled if you are not sure that your app really requires JavaScript support.
            webSettings.setJavaScriptCanOpenWindowsAutomatically(true);//支持通过JS打开新窗口
    
    
            //缓存设置
            webSettings.setAppCacheEnabled(false);///开启 Application Caches 功能
            String cacheDirPath = getFilesDir().getAbsolutePath() + APP_CACAHE_DIRNAME;
            webSettings.setAppCachePath(cacheDirPath);//设置Application Caches 缓存目录 该方法在一个app钟只能调一次
            
           
    
            //自适应屏幕
            webSettings.setUseWideViewPort(true);//将图片调整到适合webview的大小
            webSettings.setLoadWithOverviewMode(true);// 缩放至屏幕的大小
    
            //缩放处理
            webSettings.setSupportZoom(true);//支持缩放
            webSettings.setBuiltInZoomControls(true);//设置内置的缩放控件
            webSettings.setDisplayZoomControls(false);//隐藏原生缩放控件
    
            //others
            webSettings.setLoadsImagesAutomatically(true);//支持自动加载图片
            webSettings.setDefaultTextEncodingName("utf-8");
            webSettings.setDefaultFixedFontSize(18);
            webSettings.setDefaultFontSize(20);
            webSettings.setAllowFileAccess(true);//设置可以访问文件
    
        }
    

    根据网络情况设置加载模式:

            if (NetWorkUtils.isNetworkAvailable(WebViewActivity.this)) {
                webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);
            } else {
                webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
            }
    

    缓存模式如下
    //LOAD_CACHE_ONLY: 不使用网络,只读取本地缓存数据
    //LOAD_DEFAULT: (默认)根据cache-control决定是否从网络上取数据。
    //LOAD_NO_CACHE: 不使用缓存,只从网络获取数据.
    //LOAD_CACHE_ELSE_NETWORK,只要本地有,无论是否过期,都使用缓存中的数据如果没有从网络获取

    当加载 html 页面时,WebView会在/data/data/包名目录下生成 database 与 cache 两个文件夹
    请求的 URL记录保存在 WebViewCache.db,而 URL的内容是保存在 WebViewCache 文件夹下

    WebViewClient

      /**
         * 如果不设置WebViewClient的话,则 WebView 会请求 Activity 管理者选择合适的 URL 处理方式,一般情况就是启动浏览器来加载URL;
         *
         * @param webView webview
         */
        private void setWebViewClient(WebView webView) {
            webView.setWebViewClient(new WebViewClient() {
                @Override
                public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                        view.loadUrl(request.getUrl().toString());
                    }
                    return true;
                }
    
                @Override
                public void onPageStarted(WebView view, String url, Bitmap favicon) {
                    Log.e("web", "load  " + url + "  start");
                    super.onPageStarted(view, url, favicon);
                }
    
                @Override
                public void onPageFinished(WebView view, String url) {
                    Log.e("web", "load  " + url + "  finish");
                    super.onPageFinished(view, url);
                }
    
                @Override
                public void onLoadResource(WebView view, String url) {
                    Log.e("web", "load  " + url + "  onLoadResource");
                    super.onLoadResource(view, url);
                }
    
                @Override
                public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                        Log.e("web", "load  " + request.getUrl().toString() + "  fionReceivedErrornish");
                    }
                    super.onReceivedError(view, request, error);
                }
    
                @Override
                public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
                    handler.cancel();//应用代码更新为在服务器提供的证书符合您的预期时调用 SslErrorHandler.proceed(),否则调用 SslErrorHandler.cancel()。
                    super.onReceivedSslError(view, handler, error);
                }
            });
    
    
        }
    

    里面的几个方法一看命名就知道什么意思了,需要注意的是很多人对
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    view.loadUrl(request.getUrl().toString());
    }
    return true;
    }

    这个方法有误解,大多网上解释为:
    而默认情况下,Android 系统会启动一个应用来处理被点击的链接,一般情况下默认浏览器会被启动来加载目标URL(或弹出浏览器选择菜单),网络上有很多博客都介绍到了,就是采用覆盖 WebViewClient 类的 shouldOverrideUrlLoading 方法来实现。
    实际上:
    1.如果没有提供 WebViewClient 对象,则 WebView 会请求 Activity 管理者选择合适的 URL 处理方式,一般情况就是启动浏览器来加载URL;
    2.如果提供了 WebViewClient 对象且shouldOverrideUrlLoading 方法返回 true,则主机应用(意思应该是 Android 系统)处理URL;
    3.如果提供了 WebViewClient 对象且shouldOverrideUrlLoading 方法返回 false,则当前 WebView 处理URL;
    可参考:http://blog.csdn.net/zhyh1986/article/details/42169159

    还有就是onReceivedSslError在使用时的安全问题

    看下面的Log输出:

    E/web: load  https://www.baidu.com/  start
    E/web: load  https://www.baidu.com/  onLoadResource
    E/web: load  https://hpd.baidu.com/v.gif?tid=365&funcSta=whiteScreenEx&sourceSta=wiseindex&actionSta=start&logid=3393602869&ssid=0&ct=1&cst=9&logFrom=mid_news&logInfo=stability  onLoadResource
    E/web: load  https://m.baidu.com/static/index/plus/plus_logo.png  onLoadResource
    E/web: load  https://gss0.bdstatic.com/5bd1bjqh_Q23odCf/static/wiseindex/iconfont/iconfont_846ac7cd.woff  onLoadResource
    ......
    ......
    .....
    
    E/web: load  https://s.bdstatic.com/common/openjs/bdbanner.js?bd-reform-version=2017101715  onLoadResource
    E/web: load  https://m.baidu.com/static/index/plus/public/tab_news.png  onLoadResource
    E/web: load  https://www.baidu.com/  finish
    
    

    WebChromeClient

    辅助 WebView 处理 Javascript 的对话框,网站图标,网站标题等等。

    可以Android自己处理一些webView的页面交互。

    /**
         * 辅助 WebView 处理 Javascript 的对话框,网站图标,网站标题等等。
         *
         * @param webView webView
         */
        private void setChromeWebView(WebView webView) {
            webView.setWebChromeClient(new WebChromeClient() {
                @Override
                public void onProgressChanged(WebView view, int newProgress) {
                    super.onProgressChanged(view, newProgress);
                }
    
                @Override
                public void onReceivedTitle(WebView view, String title) {
                    Log.e(TAG, "onReceivedTitle: " + title);
                    super.onReceivedTitle(view, title);
                }
    
                @Override
                public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
                    //自己处理javascript的警告框
    //                result.cancel();
    //                result.confirm();
                    return super.onJsAlert(view, url, message, result);
                }
                
                //支持javascript的确认框
                @Override
                public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) {
                    new AlertDialog.Builder(WebViewActivity.this)
                            .setTitle("JsConfirm")
                            .setMessage(message)
                            .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    result.confirm();
                                }
                            })
                            .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    result.cancel();
                                }
                            })
                            .setCancelable(false)
                            .show();
    // 返回布尔值:判断点击时确认还是取消
    // true表示点击了确认;false表示点击了取消;
                    return true;
                }
    
                //支持javascript输入框
                @Override
                public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
                    //自己处理message
    //                result.cancel(); 取消
    //                result.confirm(); 确认
                    return true;
                }
            });
    

    相关文章

      网友评论

          本文标题:WebView基础

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