WebView基础

2017-10-17  本文已影响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;
            }
        });
上一篇下一篇

猜你喜欢

热点阅读