サスペンド…そしてレジューム ― 2013/11/11
Androidでは電源ボタンを押すなどサスペンド時に、OpenGLで設定したものがクリアされてしまいます。そこでレジューム(再開)時に再設定しなければいけません。
今までは開始時も含めてレジューム時に全て初期化していましたが、メモリを解放しないまま確保し直すなど行儀の悪いことになっていました。
今回はきちんとサスペンド・レジュームの処理をやってみます。
久々に java側のソースです。
BaseActivity.java
終了・一時停止・再開時に native側の関数を呼んでいるだけですが、再開時だけ少し変えています。
Androidでは一旦電源ボタンを押してサスペンドし、もう一度ボタンを押すとレジュームで onResume()が呼ばれますが、このとき画面はロック状態になっています。
ゲームなどでは画面が見えないのに動いてしまっては都合が悪いので、ロック状態の場合は解除を待ってからアプリを再開させています。
native側のソースです.
SysMain.cpp
ポーズ時の処理で描画管理を終了させています。
テクスチャキャッシュをクリアしていますので、テクスチャのVRAMからの削除はシステムに任せられます。
アプリ側の処理は、
・init_app() 開始時
・quit_app() 終了時
・pause_app() 一時停止時
・resume_app() 再開時
を、それぞれのタイミングで呼んでいます。
サンプルではログを表示しているだけなので、ソースは省略します。
プロジェクト一式は、こちらです。
今までは開始時も含めてレジューム時に全て初期化していましたが、メモリを解放しないまま確保し直すなど行儀の悪いことになっていました。
今回はきちんとサスペンド・レジュームの処理をやってみます。
久々に java側のソースです。
BaseActivity.java
/********** 終了 **********/ @Override protected void onDestroy() { super.onDestroy(); quitNative(); // native部終了 executor.shutdown(); } /************** 一時停止 **************/ @Override protected void onPause() { super.onPause(); if ( future != null ) { // 定期実行停止 future.cancel(false); future = null; synchronized (renderer) { pauseNative(); // native部一時停止 } } surface_view.onPause(); } /********** 再開 **********/ @Override protected void onResume() { super.onResume(); if ( ((KeyguardManager)getSystemService(Context.KEYGUARD_SERVICE)).inKeyguardRestrictedInputMode() ) { registerReceiver(receiver, new IntentFilter(Intent.ACTION_USER_PRESENT)); // スクリーンロック解除待ち } else { surface_view.onResume(); } } private UnLockReceiver receiver = new UnLockReceiver(); // スクリーンロック解除検知用 private class UnLockReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { unregisterReceiver(receiver); // レシーバー登録を解除 surface_view.onResume(); } }
終了・一時停止・再開時に native側の関数を呼んでいるだけですが、再開時だけ少し変えています。
Androidでは一旦電源ボタンを押してサスペンドし、もう一度ボタンを押すとレジュームで onResume()が呼ばれますが、このとき画面はロック状態になっています。
ゲームなどでは画面が見えないのに動いてしまっては都合が悪いので、ロック状態の場合は解除を待ってからアプリを再開させています。
native側のソースです.
SysMain.cpp
/************ 初期化 ************/ JNIEXPORT int JNICALL Java_sys_BaseActivity_initNative(JNIEnv* env, jobject, jint width, jint height, jobject mgr) { LOGI("initNative (&d, &d)", width, height); asset_manager = AAssetManager_fromJava(env, mgr); // asset読み込みマネージャー assert(asset_manager != NULL); Renderer::init(width, height); // 描画管理初期化 if ( !init_flag ) { init_app(); // アプリメイン初期化 init_flag = TRUE; } else { resume_app(); // アプリメイン再開 } return FRAME_PERIOD; } /********** 終了 **********/ JNIEXPORT void JNICALL Java_sys_BaseActivity_quitNative(JNIEnv*, jobject) { LOGI("quitNative"); quit_app(); // アプリメイン終了 init_flag = FALSE; } /************** 一時停止 **************/ JNIEXPORT void JNICALL Java_sys_BaseActivity_pauseNative(JNIEnv*, jobject) { LOGI("pauseNative"); if ( init_flag ) { pause_app(); // アプリメイン一時停止 } Renderer::quit(); // 描画管理終了 }
ポーズ時の処理で描画管理を終了させています。
テクスチャキャッシュをクリアしていますので、テクスチャのVRAMからの削除はシステムに任せられます。
アプリ側の処理は、
・init_app() 開始時
・quit_app() 終了時
・pause_app() 一時停止時
・resume_app() 再開時
を、それぞれのタイミングで呼んでいます。
サンプルではログを表示しているだけなので、ソースは省略します。
プロジェクト一式は、こちらです。
最近のコメント