作者: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_NONE
,LAYER_TYPE_SOFTWARE
,LAYER_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
来源:慕课网