当前位置:   article > 正文

竖屏下进入强制横屏应用,退出时壁纸被拉伸放大_安卓平板壁纸竖屏变大了

安卓平板壁纸竖屏变大了
问题现象

手机保持竖屏,进入强制横屏的应用,退出时壁纸被拉伸放大显示。
横屏时进入强制竖屏应用退出时同样会放大。
再次旋转一下手机,可以恢复正常。

问题分析

壁纸的显示在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)

方案1:

删掉getDisplayContext().getResources().getConfiguration().orientation方法获取横竖屏,改为onConfigurationChanged里获取。

onConfigurationChanged时再次更新壁纸。onConfigurationChanged回调时机比较慢,可以拿到正确的屏幕方向。

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        if (mGLEngine != null) {
            mGLEngine.onConfigurationChanged(newConfig);
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

问题:可以拿到正确的屏幕方向,但是因为时机太慢,壁纸还是会先放大,再变为正常图片。存在闪烁现象。

方案2:

在方案1的基础上,删掉中间多余的回调,在onConfigurationChanged更新壁纸。
问题:回调太慢,会概率性复现壁纸半截黑屏。
这里是因为之前需求开发,其他同事加的updateSurfaceSize(); 更新BaseSurfaceHolder setFixedSize的方法,需要删掉。

方案3:

在方案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接口进行绘制。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
结尾

文章很草率,很多地方没办法写出来。因为客制化的需求,导致之前壁纸更新被修改过。刷新时机和BaseSurfaceHolder setFixedSize都被改过。所以比原生刷新次数多。。。
思路大概是这个思路,在几个壁纸比较关键的类里面,加一些log,看看流程哪里出问题了。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/332450
推荐阅读
相关标签
  

闽ICP备14008679号