WebView基础

之前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;
            }
        });
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,519评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,842评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,544评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,742评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,646评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,027评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,513评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,169评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,324评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,268评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,299评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,996评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,591评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,667评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,911评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,288评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,871评论 2 341

推荐阅读更多精彩内容

  • WebView·开车指南 目录 WebView简介 WebView基本使用 WebView常用方法 WebSett...
    小庄bb阅读 3,483评论 3 25
  • WebView·开车指南 目录 WebView简介 WebView基本使用 WebView常用方法 WebSett...
    南城的人阅读 4,736评论 0 19
  • WebView·开车指南 2016-08-31BugDev 北京市东城区首席Bug布道师开山之作,一整月交通事故血...
    53c021c38a1d阅读 824评论 0 1
  • Tips 由于WebView的用法实在太多,如果您只是想查询某个功能的使用——建议Ctrl+F(Commad+F)...
    BugDev阅读 7,732评论 11 109
  • 0. 前言 前面有被用户投诉 APP 流量消耗厉害: 于是乎考虑了流量方面的问题。暂时 APP 中涉及流量的几个方...
    zyl06阅读 23,869评论 5 62