android webview 在项目中的那些坑

来源:互联网 发布:好玩又不要网络的游戏 编辑:程序博客网 时间:2024/05/22 11:55

在项目开发过程中,webview常用于显示网页或h5页面,这样可以实时更新,遇到问题可以迅速修复。由于android碎片化严重,所以webview在每个版本都有修改,因此在开发过程中遇到过各种各样的坑,现在总结一些曾经遇到的坑。


1,加载完成回调不正确。


onPageStarted与onPageFinished次数不一致,如果你在start中进行进度条加载处理,finish中结束,会导致进度条一直不消失。因此可以在onProgressChanged进行处理。当newProgress为100时表示页面加载完成。

对于WebViewClient.onPageFinished()。你永远无法确定当WebView调用这个方法的时候,网页内容是否真的加载完毕了。当前正在加载的网页产生跳转的时候这个方法可能会被多次调用,StackOverflow上有比较具体的解释(How to listen for a Webview finishing loading a URL in Android?), 但其中列举的解决方法并不完美。所以当你的WebView需要加载各种各样的网页并且需要在页面加载完成时采取一些操作的话,可能WebChromeClient.onProgressChanged()比WebViewClient.onPageFinished()都要靠谱一些。
2,文件选择函数修改。


// FILE UPLOAD <3.0
publicvoidopenFileChooser(ValueCallback<Uri> uploadFile) {
chooseFile(uploadFile,null,null);
}

/** * 4.x * @param uploadFile * @param acceptType * @param capture */
publicvoidopenFileChooser(ValueCallback<Uri> uploadFile, String acceptType, String capture) {
chooseFile(uploadFile, acceptType, capture);
}

Android 5.0+ 重写 onShowFileChooser 生效;

3,跨域cookie读取

       什么是跨域,简单的说就是不同的域名,我们都知道在pc上我们用浏览器访问网址,不同的网址都会在本地存储一些cookie信息,这样就可以实现比如自动登录等功能,在pc上不同域名是不能相互读取其他域下的cookie信息的(非web专业开发人员,如果理解有误,欢迎指出)。

       但是在Android上在api 23之前,是可以跨域读取cookie的,比如A域写入一个userId的cookie,B域可以读取该值。但是在23时,系统将该值设置成了false,不再让跨域读取了。如果你的应用有跨域读取需求,怎么办?可以采用如下方式进行开启:

    /**     * 设置跨域cookie读取     */    public final void setAcceptThirdPartyCookies() {        //target 23 default false, so manual set true        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {            CookieManager.getInstance().setAcceptThirdPartyCookies(webView, true);        }    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

       这里我们来看看setAcceptThirdPartyCookies的注释:

Sets whether the {@link WebView} should allow third party cookies to be set. 
Allowing third party cookies is a per WebView policy and can be set 
differently on different WebView instances. 


Apps that target {@link android.os.Build.VERSION_CODES#KITKAT} or below 
default to allowing third party cookies. Apps targeting 
{@link android.os.Build.VERSION_CODES#LOLLIPOP} or later default to disallowing 
third party cookies.

4,http/https混合加载

       在现阶段,很多网站都改成了https进行访问,https可以提升访问网站的安全性,防止信息被窃取,如果所有的网页都是https且网页内的链接也是都是https,那就没有混合加载(文本区域https,图片文件http加载)的问题了。但是很多资源现阶段还没有改变成https访问,往往页面都嵌入了http的链接。这种混合网页如果不进行处理,直接加载是会出现错误的。怎么解决这个问题?

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {  webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);}
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

       这也是一个分版本的函数,在api 23之前,默认是可以混合加载的,但是在23时,默认值改成了MIXED_CONTENT_NEVER_ALLOW,因此如果你有混合加载的需求,设置setMixedContentMode为MIXED_CONTENT_ALWAYS_ALLOW。

5,闪屏

       WebView如果开启了硬件加速,多次打开,会导致界面花屏,或者界面绘制有残留。这个在5.0刚出来的时候发生过多次,但是当时忘记截图了。当时也没有打算要把这些给记录下来。这里我已经复现不了了。如果你遇到了。关闭硬件加速就好了。关闭硬件加速这种情况会好很多,但无法获得很好的浏览体验,你会感觉网页滑动的时候一卡一卡的,不跟手。

6,资源的及时释放和耗电问题

当你的程序调用了WebView加载网页,WebView会自己开启一些线程(?),如果你没有正确地将WebView销毁的话,这些残余的线程(?)会一直在后台运行,由此导致你的应用程序耗电量居高不下。必要时要手动释放

@Override

protectedvoidonDestroy() {

super.onDestroy();

if (webView != null) {

root.removeView(webView);

webView.removeAllViews();

webView.destroy();

}

}

7,webview组件忽略SSL证书验证错误漏洞

漏洞描述

Android WebView组件加载网页发生证书认证错误时,会调用WebViewClient类的onReceivedSslError方法[1],如果该方法实现调用了handler.proceed()来忽略该证书错误,则会受到中间人攻击的威胁,可能导致隐私泄露

测试方法

实现onReceivedSslError的处理,漏洞代码样例:

    ...    mWebView.getSettings().setJavaScriptEnabled(true);        mWebView.addJavascriptInterface(new JsBridge(mContext), JS_OBJECT);        mWebView.loadUrl("http://www.example.org/tests/addjsif/");        mWebView.setWebViewClient(new WebViewClient() {            @Override            public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {                handler.proceed(); // Ignore SSL certificate errors            }        });    ...

如上代码在onReceivedSslError处理时没有进行cancel,还是使用了proceed(),忽略掉了发生的SSL异常。

解决方案

当发生证书认证错误时,采用默认的处理方法handler.cancel(),停止加载问题页面。当然,如果你的项目对安全性要求不高,对体验要求高,可以用proceed()处理忽略。


0 0
原创粉丝点击