If I hit the power button on my android phone (or wait for it to time out) and the phone goes to sleep, after waking back up, the screen aspect ratio is all out of wack.
Screenshots:
broken
correct
in GameActivity.onCreate()
// 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 = (in开发者_Python百科t) (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);
I am reloading everything correctly in GLSurfaceView (i.e. hitting home and going back to the game reloads the textures, etc).
I've printed out the orientation in onWindowFocusChanged, and it is landscape (as expected).
The problem does not appear if I do not use setFixedSize (i.e. if resolutionScale is 100). Also, the problem disappears if another window appears in front of the game (like the preferences window) and then you return the game.
Thanks in advance. I've been trying random things for about an hour since research dried up.
I am working on this issue right now, and at this moment it appears to be an Android bug related to SurfaceHolder.setFixedSize().
What I do to get these logs is this: wait for game to load, push power, let screen go blank, push power again (quickly), unlock slide (quickly). This is on HTC Thunderbolt 2.3.4, by the way.
Here is the normal course of events (without using setFixedSize):
----- 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)
Notice, that after onPause, my surface view is redone as portrait and after onResume it is changed back to landscape. I have screenOrientation set to landscape in the manifest.
Now look what happens during the same sequence but now SurfaceHolder.setFixedSize() is used (to reduce resolution):
----- 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)
Now notice that, after onPause, surfaceChanged reflects the fixed size that I had specified, however upon onResume the surface view is in portrait orientation (somewhat unexpected). But what is really missing, is the surfaceChanged call with my fixed size parameters. And before you ask, no doing .setFixedSize() in onConfigurationChanged() does not have any effect.
UPDATE AND SOLUTION:
Indeed, the solution came down to restoring (actually, never allowing any changes to) my surface view. This is accomplished by adding the following two lines after the super call in onConfigurationChanged for your activity. (Asumming you have the following manifest setting set).
android:configChanges="orientation"
android:screenOrientation="landscape"
This effectively prevents the surface view dimensions from ever being set to anything else (such as portrait). Which, incidentally, IS WHAT I WANTED WHEN I SPECIFIED screenOrientation=landscape !!! (I'm looking at you here, Google)
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;
}
You need to call gl.glViewport(0, 0, width, height); or similar from the onSurfaceChanged method of your GL10.Renderer. My assumption is that when the device wakes from sleep, something must be altering the viewport, however the viewport is initialised for you when your app is first launched, which is why it works properly until you sleep.
OpenGL state and pausing/resuming activities
You should also be aware, that your OpenGL context (all your current states like current color,binded textures etc.) will be lost when your activity is paused/resumed.
So maybe you are facing a context loss problem.
If you are using a GLSurfaceView.Renderer class you should re-set your states again in the onSurfaceCreated(..) method.
Should update your question with some code.
Updated Just for reference you refer the comment in: http://www.youtube.com/watch?v=cdvaPyq_eBU (38:14 min) and the usage of setFixedSize(..)
http://developer.android.com/reference/android/view/SurfaceHolder.html#setFixedSize%28int,%20int%29
states that you must call the method setFixedSize(SCREEN_WIDTH,SCREEN_HEIGHT) from the same thread running the SurfaceView's window. Seems you are setting it from your ui thread and not the rendering thread.
You need do three steps:
- AndroidManifest.xml -
android:configChanges="keyboard|keyboardHidden|screenSize|orientation"
- your layout for activity use
FrameLayout
in java code
public void onSurfaceChanged(GL10 gl, int w, int h) { // you need test w > h and only then do your graphics initialization ... }
精彩评论