赞
踩
手机保持竖屏,进入强制横屏的应用,退出时壁纸被拉伸放大显示。
横屏时进入强制竖屏应用退出时同样会放大。
再次旋转一下手机,可以恢复正常。
壁纸的显示在SystemUI的com/android/systemui/ImageWallpaper.java中,底层使用GLEngine opengl进行渲染和绘制。我们只能在Java代码里添加log,看看调用流程是否有问题。
添加log跟踪相关方法。
相关的类和接口:
com/android/systemui/ImageWallpaper.java
GLEngine
com/android/systemui/glwallpaper/GLWallpaperRenderer.java
com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
frameworks/base/core/java/android/service/wallpaper/WallpaperService.java
1、首先壁纸的更新回调由frameworks/base/core/java/android/service/wallpaper/WallpaperService.java的updateSurface里面触发。
在window resized 和 BaseSurfaceHolder的onUpdateSurface onRelayoutContainer回调更新。这里可以在updateSurface打断点看看横竖屏切换的时候,壁纸的更新流程。
2、在GLEngine的onSurfaceRedrawNeeded方法中添加log,
int mCurrentOri = getDisplayContext().getResources().getConfiguration().orientation;
发现代码中通过此方法判断屏幕方向,并加载壁纸显示。但是在竖屏进去横屏应用退出后,拿到的mCurrentOri 显示仍然时横屏。导致后续更新异常。
并且异常的时候,少回调了onSurfaceChanged方法。updateSurface方法中判断window大小没有发生变化,onSurfaceChanged没有走到。
正常旋转横竖屏,ImageWallpaper的onSurfaceChanged是WallpaperService的updateSurface回调的。(待确认,因为客制化需求,壁纸流程修改比较大,有很多修改引入的bug 非原生bug)
删掉getDisplayContext().getResources().getConfiguration().orientation方法获取横竖屏,改为onConfigurationChanged里获取。
onConfigurationChanged时再次更新壁纸。onConfigurationChanged回调时机比较慢,可以拿到正确的屏幕方向。
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (mGLEngine != null) {
mGLEngine.onConfigurationChanged(newConfig);
}
}
问题:可以拿到正确的屏幕方向,但是因为时机太慢,壁纸还是会先放大,再变为正常图片。存在闪烁现象。
在方案1的基础上,删掉中间多余的回调,在onConfigurationChanged更新壁纸。
问题:回调太慢,会概率性复现壁纸半截黑屏。
这里是因为之前需求开发,其他同事加的updateSurfaceSize(); 更新BaseSurfaceHolder setFixedSize的方法,需要删掉。
在方案2的基础上,添加壁纸渲染器添加添加检测机制,在opengl壁纸绘制之前,对宽高和屏幕方向进行check。
过滤掉卡半截壁纸的错误绘制。
如果壁纸宽>高,但是屏幕是竖屏,跳过此次绘制;
如果壁纸高>宽,但是屏幕是横屏,跳过此次绘制;
onSurfaceRedrawNeeded的drawFrame之前添加过滤:
//检测getSurfaceFrame的大小和屏幕方向是否匹配
boolean frameNoMatchOrientation = false;
Rect frame = getSurfaceHolder().getSurfaceFrame();
if (DEBUG){
Log.w(TAG, "onSurfaceRedrawNeeded frame: "+frame.width()+" : "+frame.height()+" mCurrentOri: "+mCurrentOri);
}
if (frame.height() > frame.width() && mCurrentOri == Configuration.ORIENTATION_LANDSCAPE ){
frameNoMatchOrientation = true;
}else if (frame.width() > frame.height() && mCurrentOri == Configuration.ORIENTATION_PORTRAIT){
frameNoMatchOrientation = true;
}
if (frameNoMatchOrientation){
Log.e(TAG, "onSurfaceRedrawNeeded frame: "+frame.width()+" : "+frame.height()+" mCurrentOri: "+mCurrentOri);
return;
}
drawFrame();//这里负责绘制,注掉这一行,壁纸显示黑屏。里面调用native接口进行绘制。
文章很草率,很多地方没办法写出来。因为客制化的需求,导致之前壁纸更新被修改过。刷新时机和BaseSurfaceHolder setFixedSize都被改过。所以比原生刷新次数多。。。
思路大概是这个思路,在几个壁纸比较关键的类里面,加一些log,看看流程哪里出问题了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。