WebView的那些坑

作者:Qyouu链接:http://www.imooc.com/article/70364来源:慕课网

1) 为什么Webview打开一个页面,播放一段音乐,退出Activity时音乐还在后台播放?

 解决方案 1:

//销毁Webview@Overrideprotected void onDestroy() {    if (mWebview != null) {
        mWebview.loadDataWithBaseURL(null, "", "text/html", "utf-8", null);
        mWebview.clearHistory();
        ((ViewGroup) mWebview.getParent()).removeView(mWebview);
        mWebview.destroy();
        mWebview = null;
    }    super.onDestroy();
}

解决方案 2:

@Overrideprotected void onPause() {
   h5_webview.onPause();
   h5_webview.pauseTimers();   super.onPause();
}@Overrideprotected void onResume() {
   h5_webview.onResume();
   h5_webview.resumeTimers();   super.onResume();
}

2) 怎么用网页的标题来设置自己的标题栏?

解决方案:

WebChromeClient mWebChromeClient = new WebChromeClient() {    
    @Override    
    public void onReceivedTitle(WebView view, String title) {    
        super.onReceivedTitle(view, title);    
        txtTitle.setText(title);    
    }    
};  
mWedView.setWebChromeClient(mWebChromeClient());

注意事项:

   1.可能当前页面没有标题,获取到的是null,那么你可以在跳转到该Activity的时候自己带一个标题,或者有一个默认标题。
   2.在一些机型上面,Webview.goBack()后,这个方法不一定会调用,所以标题还是之前页面的标题。那么
你就需要用一个ArrayList来保持加载过的url,一个HashMap保存url及对应的title.然后就是用WebView.canGoBack()来做判断处理了。

3) 为什么打包之后JS调用失败(或者WebView与JavaScript相互调用时,如果是debug没有配置混淆时,调用时没问题的,但是当设置混淆后发现无法正常调用了)?

解决方案:在proguard-rules.pro中添加混淆。

-keepattributes *Annotation*  
-keepattributes *JavascriptInterface*
-keep public class org.mq.study.webview.DemoJavaScriptInterface{
   public <methods>;
}
#假如是内部类,混淆如下:
-keepattributes *JavascriptInterface*
-keep public class org.mq.study.webview.webview.DemoJavaScriptInterface$InnerClass{
    public <methods>;
}

其中org.mq.study.webview.DemoJavaScriptInterface 是不需要混淆的类名

4) 5.0 以后的WebView加载的链接为Https开头,但是链接里面的内容,比如图片为Http链接,这时候,图片就会加载不出来,怎么解决?

原因分析:原因是Android 5.0上Webview默认不允许加载Http与Https混合内容:

 解决方案:

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
    //两者都可以
    webSetting.setMixedContentMode(webSetting.getMixedContentMode());    //mWebView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);}

参数说明:

   MIXED_CONTENT_ALWAYS_ALLOW 允许从任何来源加载内容,即使起源是不安全的;
   MIXED_CONTENT_NEVER_ALLOW 不允许Https加载Http的内容,即不允许从安全的起源去加载一个不安全的资源;
   MIXED_CONTENT_COMPLTIBILITY_MODE 当涉及到混合式内容时,WebView会尝试去兼容最新Web浏览器的风格;

另外:在认证证书不被Android所接受的情况下,我们可以通过设置重写WebViewClient的onReceivedSslError方法在其中设置接受所有网站的证书来解决,具体代码如下:

webView.setWebViewClient(new WebViewClient() {        
        @Override
        public void onReceivedSslError(WebView view,
                SslErrorHandler handler, SslError error) {            
                    //注意一定要去除这行代码,否则设置无效。
                    //super.onReceivedSslError(view, handler, error);

                    // handler.cancel();// Android默认的处理方式
                    handler.proceed();// 接受所有网站的证书
                    // handleMessage(Message msg);// 进行其他处理
        }
});

5) WebView调用手机系统相册来上传图片,开发过程中发现在很多机器上无法正常唤起系统相册来选择图片。怎么解决?

原因分析:因为Google攻城狮们对setWebChromeClient的回调方法openFileChooser做了多次修改,5.0以下openFileChooser有几种重载方法,在5.0以上将回调方法该为了onShowFileChooser。

 解决方案:为了兼容各个版本,我们需要对openFileChooser()进行重载,同时针对5.0及以上重写onShowFileChooser()方法:

6) WebView调用手机系统相册来上传图片,处理好第六点说的方法,我们打好release包测试的时候却又发现还是没法选择图片了。怎么解决?

原因分析:无奈去翻WebChromeClient的源码,发现openFileChooser()是系统API,我们的release包是开启了混淆的,所以在打包的时候混淆了openFileChooser(),这就导致无法回调openFileChooser()了。

 解决方案也很简单,直接不混淆openFileChooser()就好了。

-keepclassmembers class * extends android.webkit.WebChromeClient{   public void openFileChooser(...);
}

7)怎么在 WebView 中长按保存图片?


1. 给 WebView添加监听

mWebview.setOnLongClickListener(new View.OnLongClickListener() {    @Override
    public boolean onLongClick(View v) {
    }
});

2. 获取点击的图片地址

先获取类型,根据相应的类型来处理对应的数据。

//首先判断点击的类型WebView.HitTestResult result = ((WebView) v).getHitTestResult();int type = result.getType();//获取具体信息,图片这里就是图片地址String imgurl = result.getExtra();

type有这几种类型:

  • WebView.HitTestResult.UNKNOWN_TYPE 未知类型

  • WebView.HitTestResult.PHONE_TYPE 电话类型

  • WebView.HitTestResult.EMAIL_TYPE 电子邮件类型

  • WebView.HitTestResult.GEO_TYPE 地图类型

  • WebView.HitTestResult.SRC_ANCHOR_TYPE 超链接类型

  • WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE 带有链接的图片类型

  • WebView.HitTestResult.IMAGE_TYPE 单纯的图片类型

  • WebView.HitTestResult.EDIT_TEXT_TYPE 选中的文字类型

3. 操作图片

你可以弹出保存图片,或者点击之后跳转到显示图片的页面。

最后整理一下代码:

mWebView.setOnLongClickListener(new View.OnLongClickListener() {    
    @Override
    public boolean onLongClick(View v) {
        WebView.HitTestResult result = ((WebView)v).getHitTestResult();        
        if (null == result)           
            return false;        
        int type = result.getType();        
        if (type == WebView.HitTestResult.UNKNOWN_TYPE)            
            return false;        
        // 这里可以拦截很多类型,我们只处理图片类型就可以了
        switch (type) {            
                case WebView.HitTestResult.PHONE_TYPE: // 处理拨号
                break;            
                case WebView.HitTestResult.EMAIL_TYPE: // 处理Email
                break;            
                case WebView.HitTestResult.GEO_TYPE: // 地图类型
                break;           
                case WebView.HitTestResult.SRC_ANCHOR_TYPE: // 超链接
                break;            
                case WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE:                                                        
                break;            
                case WebView.HitTestResult.IMAGE_TYPE: // 处理长按图片的菜单项
                // 获取图片的路径
                String saveImgUrl = result.getExtra();                
                // 跳转到图片详情页,显示图片
                Intent i = new Intent(MainActivity.this, ImageActivity.class);
                i.putExtra("imgUrl", saveImgUrl);
                startActivity(i);                
                break;            
                default:                
                break;
        }
    }
});

8) WebView 开启硬件加速导致的问题?

WebView有很多问题,比如:不能打开pdf,播放视屏也只能打开硬件加速才能支持,在某些机型上会崩溃。
下面看一下硬件加速, 硬件加速 分为四个级别:

  • Application级别

     <application android:hardwareAccelerated="true"...>
  • Activity级别

     <activity android:hardwareAccelerated="true"...>
  • window级别(目前为止,Android还不支持在Window级别关闭硬件加速。)

    getWindow().setFlags(
        WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
        WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
  • View级别

     view.setLayerType(View.LAYER_TYPE_HARDWARE, null);

WebView开启硬件加速导致屏幕花屏问题的解决:

原因分析:
4.0以上的系统我们开启硬件加速后,WebView渲染页面更加快速,拖动也更加顺滑。但有个副作用就是,当WebView视图被整体遮住一块,然后突然恢复时(比如使用SlideMenu将WebView从侧边滑出来时),这个过渡期会出现白块同时界面闪烁。

解决方案:
在过渡期前将WebView的硬件加速临时关闭,过渡期后再开启,代码如下:

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
        webview.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    }

Android 4.0+ 版本中的EditText字符重叠问题:
做的软件,在一些机器上,打字的时候,EditText中的内容会出现重叠,而大部分机器没有,所以感觉不是代码的问题,一直没有头绪。

出现原因:JellyBean的硬件加速bug,在此我们关掉硬件加速即可。
解决方案:在EditText中加入一句:

android:layerType=”software”

图片无法显示:
做的程序里有的时候会需要加载大图,但是硬件加速中 OpenGL对于内存是有限制的。如果遇到了这个限制,LogCat只会报一个Warning: Bitmap too large to be uploaded into a texture (587x7696, max=2048x2048)这时我们就需要把硬件加速关闭了。
但开始我是这样处理的,我关闭了整个应用的硬件加速:
<application  
    android:allowBackup="true"  
    android:icon="@drawable/ic_launcher"  
    android:hardwareAccelerated="false"  
    android:label="@string/app_name"  
    android:theme="@style/AppTheme" >

随后我就发现,虽然图片可以显示了,但是ListView和WebView等控件显得特别的卡,这说明硬件加速对于程序的性能提升是很明显的。所以我就改为对于Activity的关闭。

<activity  
    android:name="icyfox.webviewimagezoomertest.MainActivity"  
    android:label="@string/app_name"  
    android:hardwareAccelerated="false"

9) ViewPager里非首屏WebView点击事件不响应是什么原因?

如果你的多个WebView是放在ViewPager里一个个加载出来的,那么就会遇到这样的问题。ViewPager首屏WebView的创建是在前台,点击时没有问题;而其他非首屏的WebView是在后台创建,滑动到它后点击页面会出现如下错误日志:
 E/webcoreglue﹕ Should not happen: no rect-based-test nodes found
解决方案:
这个问题的办法是继承WebView类,在子类覆盖onTouchEvent方法,填入如下代码:

@Overridepublic boolean onTouchEvent(MotionEvent ev) {    
    if (ev.getAction() == MotionEvent.ACTION_DOWN) {
        onScrollChanged(getScrollX(), getScrollY(), getScrollX(), getScrollY());
    }    
    return super.onTouchEvent(ev);
}

10) WebView白屏是什么原因?

解决方案:
WebView设置setLayerType(View.LAYER_TYPE_SOFTWARE,null); 示例代码如此下:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
    setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}

相关源码分析:
WebView继承View,View中有三种layer type分别为LAYER_TYPE_NONELAYER_TYPE_SOFTWARELAYER_TYPE_HARDWARE

  • 1.LAYER_TYPE_NONE:表明视图没有多余渲染层。

  • 2.LAYER_TYPE_SOFTWARE:表明视图有一个软件渲染层。无论是否开启硬件加速,都会有一张
    Bitmap(software layer),并在上面对 WebView 进行渲染。
    好处:在进行动画,使用software可以只画一次ViewTree,很省。
    不适合使用场景:View树经常更新时不要用。尤其是在硬件加速打开时,每次更新消耗的时间更多。因为渲染完这张Bitmap后还需要再把这张Bitmap渲染到hardware layer上面去。

  • 3.LAYER_TYPE_HARDWARE:表明视图有一个硬件渲染层。硬件加速关闭时,作用同software。硬件加速打开时会在FBO(Framebuffer Object)上做渲染,在进行动画时,View树也只需要画一次。

LAYER_TYPE_SOFTWARE 和 LAYER_TYPE_HARDWARE的区别:

1.前者是渲染到Bitmap,后者是渲染到FB上。
2.hardware可能会有一些操作不支持(出现白屏)。

LAYER_TYPE_SOFTWARE 和 LAYER_TYPE_HARDWARE的相同:

都是开了一个buffer,把View画到这个buffer上面去。

11)给GLSurfaceView设置为software或者hardware后,发现没有画面了是什么原因?

问题分析:GLSurfaceView和WebView默认LayerType都是NONE。

解决方案:给GLSurfaceView的LayerType设置为LAYER_TYPE_NONE就可以了。


作者:Qyouu
链接:http://www.imooc.com/article/70364
来源:慕课网

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在加载 WebView 时,有一些注意事项可以帮助提高用户体验和保证应用的安全性。以下是一些需要注意的事项: 1. 加载进度条:在 WebView 加载页面的过程中,显示一个加载进度条可以让用户知道页面正在加载,并提供一种视觉反馈。你可以使用 Android 的 ProgressBar 或者自定义视图来实现。 2. 错误处理:WebView 可能会遇到网络错误、页面加载错误等问题,你应该处理这些错误,并向用户提供相应的提示信息,例如显示一个错误页面或者弹出一个对话框。 3. 缓存:WebView 默认会缓存已加载的页面,这样可以提高页面加载速度并减少网络流量。你可以根据需要设置缓存策略,例如只缓存静态资源或者禁用缓存。 4. 安全性:WebView 是一个容易受到攻击的组件,你需要采取一些安全措施来保护应用和用户的数据。例如,禁用 JavaScript 或者限制 JavaScript 的执行权限,防止跨域脚本攻击;验证加载的网页是否来自可信任的源;避免使用明文传输敏感数据等。 5. 用户交互:当 WebView 加载外部网页时,用户可能会与网页进行交互,例如点击链接或者填写表单。你可以通过 WebViewClient 和 WebChromeClient 来拦截网页的跳转、表单提交等操作,并根据需要进行处理。 以上是一些常见的注意事项,根据具体的需求和场景,可能还有其他需要注意的地方。在开发过程中,你可以参考 Android 官方文档和相关教程来获取更多关于 WebView 的使用技巧和最佳实践。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值