Android OpenGL: безумное соотношение сторон после сна - PullRequest
7 голосов
/ 25 августа 2011

Если я нажму кнопку питания на моем телефоне с Android (или подожду, пока он перестанет работать), и телефон перейдет в спящий режим, после пробуждения соотношение сторон экрана изменится.

Снимки экрана:

сломано

http://i.imgur.com/4C6ID.png

правильно

http://i.imgur.com/CNAV0.png

в 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 = (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);

Я корректно перезагружаю все в GLSurfaceView (то есть, возвращаясь домой и возвращаясь к игре, перезагружаю текстуры и т. Д.).

Я распечатал ориентацию в onWindowFocusChanged, и это пейзаж (как и ожидалось).

Проблема не появляется, если я не использую setFixedSize (т. е. если resolutionScale равен 100).Кроме того, проблема исчезает, если перед игрой появляется другое окно (например, окно настроек), а затем вы возвращаете игру.

Заранее спасибо.Я пробовал случайные вещи около часа с тех пор, как иссякли исследования.

Ответы [ 4 ]

6 голосов
/ 24 октября 2012

Я работаю над этой проблемой прямо сейчас, и в этот момент представляется ошибкой Android, связанной с SurfaceHolder.setFixedSize ().

Что я делаю, чтобы получить эти логи, так это: дождитесь загрузки игры, включите питание, дайте экрану погаснуть, снова включите питание (быстро), разблокируйте слайд (быстро).Кстати, это в HTC Thunderbolt 2.3.4.

Вот нормальный ход событий (без использования 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)

Обратите внимание, что после onPause мой вид поверхностипеределан в качестве портрета и после onResume он возвращается обратно в ландшафт.У меня screenOrientation установлен в ландшафт в манифесте.

Теперь посмотрим, что происходит во время той же последовательности, но теперь используется SurfaceHolder.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=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)

Теперь обратите вниманиечто после onPause surfaceChanged отражает заданный мной фиксированный размер, однако при onResume вид поверхности находится в портретной ориентации (что несколько неожиданно). Но чего в действительности не хватает, так это вызова surfaceChanged с моими параметрами фиксированного размера. И, прежде чем вы спросите, никакие действия .setFixedSize () в onConfigurationChanged () не имеют никакого эффекта.

UPDATEИ РЕШЕНИЕ:

Действительно, решение сводилось к восстановлению (фактически, никогда не позволяя никаких изменений) моего вида поверхности.Это достигается добавлением следующих двух строк после супер-вызова в onConfigurationChanged для вашей деятельности.(Как бы то ни было, у вас есть следующий набор настроек манифеста).

android:configChanges="orientation"
android:screenOrientation="landscape"

Это фактически предотвращает установку размеров вида поверхности на что-либо еще (например, портрет). Что, кстати, ЧТО Я ХОЧУ, КОГДА Я УКАЗАЛ screenOrientation = landscape !!! (Я смотрю на тебя здесь, 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;
}
1 голос
/ 22 апреля 2012

Вам нужно вызвать gl.glViewport (0, 0, ширина, высота); или аналог из метода onSurfaceChanged вашего GL10.Renderer. Я предполагаю, что когда устройство выходит из спящего режима, что-то должно изменить область просмотра, однако область просмотра инициализируется для вас при первом запуске приложения, поэтому оно работает должным образом, пока вы не спите.

0 голосов
/ 17 марта 2015

Вам нужно сделать три шага:

  1. AndroidManifest.xml - android:configChanges="keyboard|keyboardHidden|screenSize|orientation"
  2. ваш макет для использования активности FrameLayout
  3. в Javacode

    public void onSurfaceChanged (GL10 gl, int w, int h) {// вам нужно проверить w> h и только после этого выполнить инициализацию вашей графики ...}

0 голосов
/ 25 августа 2011

Состояние OpenGL и приостановка / возобновление деятельности

Вы также должны знать, что ваш контекст OpenGL (все ваши текущие состояния, такие как текущий цвет, связанные текстуры и т. Д.) Будет потерян , когда ваша активность приостановлена ​​ /resumed.
Так, возможно, вы столкнулись с проблемой потери контекста.
Если вы используете класс GLSurfaceView.Renderer, вы должны заново установить ваши состояния снова в методе onSurfaceCreated (..). Следует обновить ваш вопрос с некоторым кодом.

Обновлено Просто для справки вы ссылаетесь на комментарий: http://www.youtube.com/watch?v=cdvaPyq_eBU (38:14 мин) и использование setFixedSize (..)

http://developer.android.com/reference/android/view/SurfaceHolder.html#setFixedSize%28int,%20int%29
гласит, что необходимо вызвать метод setFixedSize (SCREEN_WIDTH, SCREEN_HEIGHT) из того же потока, в котором запущено окно SurfaceView. Кажется, вы устанавливаете его из пользовательского потока , а не из потока визуализации .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...