サスペンド…そしてレジューム2013/11/11

Androidでは電源ボタンを押すなどサスペンド時に、OpenGLで設定したものがクリアされてしまいます。そこでレジューム(再開)時に再設定しなければいけません。
今までは開始時も含めてレジューム時に全て初期化していましたが、メモリを解放しないまま確保し直すなど行儀の悪いことになっていました。
今回はきちんとサスペンド・レジュームの処理をやってみます。

久々に 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()   再開時
を、それぞれのタイミングで呼んでいます。
サンプルではログを表示しているだけなので、ソースは省略します。


プロジェクト一式は、こちらです。