このサイトでは、分析、カスタマイズされたコンテンツ、および広告に Cookie を使用します。このサイトを引き続き閲覧すると、Cookie の使用に同意するものと見なされます。
Hi, Developers,
straightapps.com
作成日 January 30, 2018、最終更新日 June 8, 2019(様式変更)
トップページ > Android 開発トップ > android_main 関数(メインループ)

Android 開発

ここでは、android_main 関数のメインループ処理を検討しています。

android_main 関数(ループ前)」では、関数の最初の部分について、検討しました。
android_main 関数(ループ前2)」では、その続きを、メインループ前まで検討しました。
ここでは、続くメインループの部分を検討しています。

ご利用に際しては、必ずプライバシーポリシー(免責事項等)をご参照ください。
また、本サイトが初めての方は、まずこのページの注意事項をご覧ください。

android_main 関数(メインループ前半)

投稿 January 30, 2018, 最終更新 July 30, 2018(様式変更)

ここまでに、Visual C++ 2015 で、新しく Android ネイティブアプリを作成したときに作成される main.cpp の android_main 関数、メインループの前までを検討しました。
ここでは、while (1) で囲まれているメインループ部を見てみます。

while (1) {
	// 保留中のすべてのイベントを読み取ります。
	int ident;
	int events;
	struct android_poll_source* source;

	// アニメーションしない場合、無期限にブロックしてイベントが発生するのを待ちます。
	// アニメーションする場合、すべてのイベントが読み取られるまでループしてから続行します
	// アニメーションの次のフレームを描画します。
	while ((ident = ALooper_pollAll(engine.animating ? 0 : -1, NULL, &events, (void**)&source)) >= 0) {

		// このイベントを処理します。
		if (source != NULL) {
			source->process(state, source);
		}

		// センサーにデータがある場合、今すぐ処理します。
		if (ident == LOOPER_ID_USER) {
			if (engine.accelerometerSensor != NULL) {
				ASensorEvent event;
				while (ASensorEventQueue_getEvents(engine.sensorEventQueue, &event, 1) > 0) {
					LOGI("accelerometer: x=%f y=%f z=%f",
						event.acceleration.x, event.acceleration.y, event.acceleration.z);
				}
			}
		}

		// 終了するかどうか確認します。
		if (state->destroyRequested != 0) {
			engine_term_display(&engine);
			return;
		}
	}

	if (engine.animating) {
		(中略;次のブロックで詳細を見ます)
	}
}

while (1) 内の最初の while 関数、ALooper_pollAll 関数でイベントを取得します。 Windows でいう PeekMessage のイメージだと思っています。

データがあることを確認してから呼び出す source->process 関数は、 android_native_app_glue.c ( NativeActivity とシステムをつなぐコードを格納した自動生成コード ) process_cmd 関数を経由して、 struct android*onAppCmd に指定された関数を呼び出すようになっています。
android_main 関数の最初の部分で、

state->onAppCmd = engine_handle_cmd;

としていますので、main.cpp に実装されている
static void engine_handle_cmd(struct android_app* app, int32_t cmd)
が呼び出されることになります。

ここでは触れませんが、struct android_app* app は、いつでも重要な構造体データです。 第2引数の cmd はコマンドで、 APP_CMD_START ならアプリが起動された、 APP_CMD_INIT_WINDOW ならウィンドウが初期化された、 というように通知されますので、適切な処理を実行します。
自動生成されたコードに記述されている以外にも、いくつかの定義があります。 種類は、これらのシンボルの定義位置を参照すれば、すぐにわかります。
APP_CMD_ を処理するのが基本だとは思いますが、 Android Developers の NativeActivity のページを見ると、もう少しわかりやすくなるかもしれないと、思わなくもありませんが、(今は)特には困らないと考えています。

続く ident == LOOPER_ID_USER の中は、 センサーの初期化で ASensorManager_createEventQueue 関数 で作成したキュー ( ASensorManager_createEventQueue(engine.sensorManager, state->looper, LOOPER_ID_USER, NULL, NULL) ) の処理です。 センサーの情報を取得して、logcat(ログ)に、information として出力する、ということです。 logcat が使いにくいので、私はログファイルに記録してみましたが、当然たくさんのログが書き込まれました。

state->destroyRequested に非0がセットされると、終了処理に入ります。 return する前に、確保したメモリの解放等、自分の終了処理を行うのが良いのではないでしょうか。

その時点のすべてのイベントを処理したら、while ループを抜けて、先に進みます。

▲ページ先頭へ

android_main 関数(メインループ後半)

投稿 January 30, 2018, 最終更新 July 30, 2018(様式変更)

while (1) ループの続きの部分についても確認します。

	if (engine.animating) {
		// イベントが完了したら次のアニメーション フレームを描画します。
		engine.state.angle += .01f;
		if (engine.state.angle > 1) {
			engine.state.angle = 0;
		}

		// 描画は画面の更新レートに合わせて調整されているため、
		// ここで時間調整をする必要はありません。
		engine_draw_frame(&engine);
	}

engine.animating は、メインループ開始直前に 1 に設定していますので、起動時は必ず 1 です。 ですので、あえて 0 にしない限りは、この条件にヒットします。 なお、自動生成されたコードでは、アプリが非アクティブになるとき 0 にしていますので、この部分(描画処理)が実行されなくなります。 再びアクティブになったとき、これを 1 にしないと画面が更新されませんが、自動生成されたコードには、それがないようでした。

engine.state.angle は単なる変数であって、画面を描画するときに絵が動いて見えるようにする目的です。 0.00〜1.00 まで、0.01 きざみで変更されている、というだけです。
そして engine_draw_frame 関数を呼び出して、描画を行っています。 この関数は、main.cpp で、次のように定義・実装されています。

static void engine_draw_frame(struct engine* engine)

Android ネイティブアプリでは、毎フレーム、バッファに完全に描画を行って、 eglSwapBuffers 関数を呼び出しで実際に画面に表示する、 ということを繰り返しているようです。
古い Windows プログラマとしては、画面用バッファを常に保持して、変更が必要な部分のみを書き変えて・・・ という手順でないのに驚きますが、十分高速であるようですから、すごいです。

▲ページ先頭へ

関連トピックス

android_main 関数(ループ前)
ネイティブアプリ プロジェクトの基本、android_main 関数について検討しています。最初の部分を扱っています。

android_main 関数(ループ前2)
ネイティブアプリ プロジェクトの基本、android_main 関数について検討しています。このページの前の部分です。


その他のおすすめ

おすすめ記事はありません。

JavaScriptが無効です
▲ページ先頭へ


© 2017-2021 StraightApps.com 無断転載を禁じます。No reproduction without permission.