Estou com um problema na minha aplicação em que toda vez que altero uma configuração da activity, como por exemplo a orientation da tela, a activity reinicia, eu não teria problema se na oncreate da activity eu não tivesse as funções que iniciam os handlers da aplicação.
Minha ideia é alterar dentro da aplicação a orientation manualmente (PORTRAIT/LANDSCAPE), usando a funcão setRequestedOrientation, que nas documentaçoes do android diz que funciona da seguinte forma:
Change the desired orientation of this activity. If the activity is currently in the foreground or otherwise impacting the screen orientation, the screen will immediately be changed (possibly causing the activity to be restarted). Otherwise, this will be used the next time the activity is visible
Mas toda vez que altero, a aplicação reinicia, ou melhor, a activity reinicia, já me deram a ideia de bloquear esta operacao automatica implementando no manifest.xml a seguinte linha de codigo dentro da activity: android:configChanges="orientation", e assim ficaria por conta do usuário a implementacao do que seria feito, e dentro da funcao onConfigurationChanged(), mas não é recomendado e não é seguro.
Então parti para outra possível solução, a função onRetainNonConfigurationInstance(), que retorna um objeto, como o próprio nome já diz, ela salva um objeto toda vez que a activity é destruída, podendo ser recuperada na próxima inicialização pela função getLastNonConfigurationInstance().
Entao fiz o seguinte no meu onCreate:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR); // Inicio a aplicação bloqueando o rotacionamento automatico pelo sensor
boolean isLandscape = getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE; // Aqui é só para alterar o tamanho do frame buffer quando estiver em portrait ou landscape
int frameBufferWidth = isLandscape ? 320 : 240;
int frameBufferHeight = isLandscape ? 240 : 320;
Bitmap frameBuffer = Bitmap.createBitmap(frameBufferWidth,
frameBufferHeight, Config.RGB_565);
float scaleX = (float) frameBufferWidth
/ getWindowManager().getDefaultDisplay().getWidth();
float scaleY = (float) frameBufferHeight
/ getWindowManager().getDefaultDisplay().getHeight();
//Aqui eu inicializo tudo o que vai monitorar a aplicação
renderView = new AndroidFastRenderView(this, frameBuffer);
graphics = new AndroidGraphics(getAssets(), frameBuffer);
fileIO = new AndroidFileIO(this);
audio = new AndroidAudio(this);
input = new AndroidInput(this, renderView, scaleX, scaleY);
// Logo entao eu inicializo o objeto da tela com o ultimo objeto salvo pela onRetain..()
screen = (Screen) getLastNonConfigurationInstance();
if (screen == null) { // Porem se nada foi salvo, a getLastNonConfigurationIstance() retorna um null
screen = getStartScreen(); // E entao eu inicio a primeira tela
}
setContentView(renderView);
PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, "GLGame");
}
E na função onRetainNonConfigurationInstance() implementei o seguinte:
@Override
public Object onRetainNonConfigurationInstance() {
return screen;
}
Basicamente já deveria funcionar normalmente, mas não é isso o que acontece, toda vez que mando rotacionar manualmente, a activity reinicia o objeto aparentemente é recuperado mas como a classe screen depende das classes AndroidGraphics, AndroidAudio etc a tela não inicializa corretamente.
A função que manda rotacionar esta implementada na mesma classa da activity e é a seguinte:
@Override
public void setOrientation(int preferenceOrientation) {
if (preferenceOrientation == Configuration.ORIENTATION_LANDSCAPE) {
if( getRequestedOrientation() != ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
} else if (preferenceOrientation == Configuration.ORIENTATION_PORTRAIT) {
if( getRequestedOrientation() != ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
} else {
if( getRequestedOrientation() != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
}
}
}
Se a opção rotacionar automático do aparelho estiver habilitada e removo a função setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR); do oncreate, toda vez que o aparelho é rotacionado a tela gira, mas não recupera as informações da classe Screen.
Enfim, só quero poder rotacionar a tela sem que tudo seja reinicializado novamente, alguem se habilita?
