Android OpenGL:睡眠后疯狂的纵横比

Android OpenGL:睡眠后疯狂的纵横比,android,opengl-es,Android,Opengl Es,如果我按下安卓手机上的电源按钮(或等待它超时),手机进入睡眠状态,醒来后,屏幕纵横比会变得异常 截图: 破碎的 正确的 在GameActivity.onCreate()中 我在GLSURFACHEVIEW中正确地重新加载了所有内容(例如,打到家并返回游戏重新加载纹理等) 我已经在onWindowFocusChanged中打印出了方向,它是横向的(正如预期的那样) 如果不使用setFixedSize(即resolutionScale为100),则不会出现问题。此外,如果游戏前面出现另一个窗口(

如果我按下安卓手机上的电源按钮(或等待它超时),手机进入睡眠状态,醒来后,屏幕纵横比会变得异常

截图:

破碎的

正确的

在GameActivity.onCreate()中

我在GLSURFACHEVIEW中正确地重新加载了所有内容(例如,打到家并返回游戏重新加载纹理等)

我已经在onWindowFocusChanged中打印出了方向,它是横向的(正如预期的那样)

如果不使用setFixedSize(即resolutionScale为100),则不会出现问题。此外,如果游戏前面出现另一个窗口(如“首选项”窗口),然后您返回游戏,则问题就会消失

提前谢谢。自从研究干涸后,我已经随机尝试了大约一个小时。

OpenGL状态和暂停/恢复活动 您还应该意识到,当您的活动暂停/恢复时,您的OpenGL上下文(所有当前状态,如当前颜色、绑定纹理等)将丢失
,因此您可能面临上下文丢失问题。
如果您使用的是GLSurfaceView.Renderer类,则应在onSurfaceCreated(..)方法中重新设置状态。 应该用一些代码更新你的问题

已更新 仅供参考,请参考:(38:14分钟)中的注释和setFixedSize(…)



说明必须从运行SurfaceView窗口的同一线程调用方法setFixedSize(屏幕宽度、屏幕高度)。似乎是从ui线程设置的,而不是调用gl.glViewport(0,0,宽度,高度)所需的渲染线程设置的;或类似于GL10.1的onSurfaceChanged方法。我的假设是,当设备从睡眠中醒来时,一定有什么东西在改变视口,但是当您的应用程序首次启动时,视口会为您初始化,这就是为什么它在您睡眠之前工作正常。

我正在处理这个问题,此时,它似乎是一个与SurfaceHolder.setFixedSize()相关的Android bug

我要做的是:等待游戏加载,按下电源,让屏幕空白,再次按下电源(快速),解锁幻灯片(快速)。顺便说一下,这是HTC Thunderbolt 2.3.4上的内容

以下是事件的正常过程(不使用setFixedSize):

请注意,在onPause之后,我的曲面视图将作为纵向视图重做,而在onResume之后,它将更改回横向视图。我在清单中将screenOrientation设置为横向

现在看看在相同的序列中发生了什么,但现在使用了SurfaceHolder.setFixedSize()来降低分辨率:

现在请注意,在onPause之后,surfaceChanged反映了我指定的固定大小,但是在onResume之后,曲面视图处于纵向(有些出乎意料)但真正缺少的是使用我的固定大小参数进行的surfaceChanged调用。在您询问之前,不要这样做。OnConfiguration Changed()中的setFixedSize()没有任何效果

更新和解决方案: 事实上,解决方案归结为恢复(实际上,从不允许任何更改)我的曲面视图。这是通过在活动的OnConfiguration Changed中的超级调用之后添加以下两行来实现的。(如果设置了以下清单设置)

这可以有效地防止曲面视图尺寸设置为任何其他尺寸(例如纵向)顺便说一句,这正是我在指定screenOrientation=横向时想要的(我在这里看着你,谷歌)


您需要执行三个步骤:

  • AndroidManifest.xml-
    android:configChanges=“键盘|键盘隐藏|屏幕大小|方向”
  • 活动的布局使用
    FrameLayout
  • 在java代码中

    表面上的公共空隙已更改(GL10 gl、int w、int h){ //您需要测试w>h,然后才进行图形初始化 ... }


  • 我解决了这个问题!奇怪的是,这个问题是因为我没有使用具有二维效果的纹理!自从改变了,我就再也没有问题了。没关系,问题又来了。顺便说一下,我所有的线程都做得很正确。我有一个相同的问题,你找到问题的原因了吗?谢谢!自从我第一次发布这个问题已经有很长时间了。但看到解决方案真是太好了!这其实不是解决办法。首先,这是一个肮脏的黑客,当你的GLSurfaceView不是全屏的时候,或者当它是一个复杂的视图层次结构的一部分的时候,它就不起作用了。相反,正如fabspro所指出的:确保每次调用onSurfaceChanged()时都调用glViewport()。这是为全屏视图而做的,所以它在需要时完成了任务(回到'12年)。我不再参与这个有问题的项目,不幸的是,我无法测试你的建议。
        // Grab display info
        DisplayMetrics dm = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(dm);
        ACTUAL_SCREEN_WIDTH = (int) dm.widthPixels;
        ACTUAL_SCREEN_HEIGHT = (int) dm.heightPixels;
        ACTUAL_DENSITY = dm.density;
    
        double scale = ((double) MainMenuActivity.resolutionScale / 100.0);
        SCREEN_WIDTH = (int) (ACTUAL_SCREEN_WIDTH * scale);
        SCREEN_HEIGHT = (int) (ACTUAL_SCREEN_HEIGHT * scale);
        DENSITY = ACTUAL_DENSITY * scale;
    
        // Setup graphics
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        surface_view = new GLSurfaceView(this);
    
        if (SCREEN_WIDTH != ACTUAL_SCREEN_WIDTH
                || SCREEN_HEIGHT != ACTUAL_SCREEN_HEIGHT)
            surface_view.getSurfaceHolder().setFixedSize(SCREEN_WIDTH,
                    SCREEN_HEIGHT);
    
    ----- power button pushed ------
    JavaMain: onPause: called, thread: 1
    ActivityManager: Config changed: { scale=1.0 imsi=310/12 loc=en_US touch=3 keys=1/1/2 nav=1/1 orien=1 layout=34 uiMode=17 seq=1509 skin=default}
    JavaMain: onConfigurationChanged, orientation: 1 thread: 1
    JavaMain: mSView(old): 800x480
    JavaMain: surfaceChanged: width: 480, height:800, thread: 1
    JavaMain: onWindowFocusChanged: called, thread: 1
    (screen is now off)
    ------ power button pushed, and slide-lock undone -----
    JavaMain: onResume: called, thread: 1
    ActivityManager: Config changed: { scale=1.0 imsi=310/12 loc=en_US touch=3 keys=1/1/2 nav=1/1 orien=2 layout=34 uiMode=17 seq=1510 skin=default}
    JavaMain: onConfigurationChanged, orientation: 2 thread: 1
    JavaMain: mSView(old): 480x800
    JavaMain: onWindowFocusChanged: called, thread: 1
    JavaMain: surfaceChanged: width: 800, height:480, thread: 1
    (back in game)
    
    ----- power button pushed -------
    JavaMain: onPause: called, thread: 1
    ActivityManager: Config changed: { scale=1.0 imsi=310/12 loc=en_US touch=3 keys=1/1/2 nav=1/1 orien=1 layout=34 uiMode=17 seq=1513 skin=default}
    JavaMain: onConfigurationChanged, orientation: 1 thread: 1
    JavaMain: mSView(old): 800x480
    JavaMain: surfaceChanged: width: 640, height:384, thread: 1
    JavaMain: onWindowFocusChanged: called, thread: 1
    (screen is now off)
    ------ power button pushed, and slide-lock undone -----
    JavaMain: onResume: called, thread: 1
    ActivityManager: Config changed: { scale=1.0 imsi=310/12 loc=en_US touch=3 keys=1/1/2 nav=1/1 orien=2 layout=34 uiMode=17 seq=1514 skin=default}
    JavaMain: onConfigurationChanged, orientation: 2 thread: 1
    JavaMain: mSView(old): 480x800
    JavaMain: onWindowFocusChanged: called, thread: 1
    (back in game, with a messed up screen as in OP)
    
    android:configChanges="orientation"
    android:screenOrientation="landscape"
    
    public void onConfigurationChanged(Configuration newConfig) {       
        super.onConfigurationChanged(newConfig);
    
        // -- stomp any attempts by the OS to resize my view.
        // -- Hardcoded values for illustration only. In real life
        // -- you'll need to save these when the surface view is originally created
        mSView.getLayoutParams().width = 800;
        mSView.getLayoutParams().height = 480;
    }