日別アーカイブ: 2011年2月7日

Android NDK と NativeActivity

Android OS 2.3、API Level 9 から NativeActivity が利用出来るようになります。
画面の初期化やイベントの取得も Java コードを通らずに C/C++ だけで
記述することが可能です。

とは言え実際にアプリケーションを記述する手段はこれまでとほとんど変わりません。
jni フォルダに C/C++ コードを置いて ndk-build を使います。
生成されるバイナリも従来同様 Dynamic Link Library (dll) ~.so です。

・今までの NDK (jni)
  Java 上で dll をロードし、interface class を経由して呼び出し

・NativeActivity
  システムが直接 dll をロードし dll 内のエントリポイントを直接呼び出す

●エントリポイントの指定

最初に呼ばれる関数名を AndroidManifest.xml に記述します。

・Java コードを含まないことを宣言
   のアトリビュートに android:hasCode=”false”

・dll 名の指定
   宣言内に で指定する。
  例えば libappmain.so の場合


・エントリポイント名の指定
  例えば関数 Main_onCreate() から開始する場合


これで Activity の起動時に libappmain.so 内の Main_onCreate() が
直接呼び出されるようになります。

●イベント

Java と全く同様に NativeActivity も onStart, onResume, onPause, onStop,
onDestroy, onRestart 等のイベントが呼ばれます。
あらかじめイベントごとに Callback 関数を登録しておく必要があります。

onCreate のみ特別で、Callback ではなく Activity 起動時のエントリ関数として
AndroidManifest.xml に記述します。
AndroidManifest.xml に func_name の記述がない場合は関数名
ANativeActivity_onCreate() とみなします。
この関数の実体はアプリケーション側で記述しておく必要があります。

(1) onCreate で AndroidManifest.xml に記述した関数が呼ばれる
(2) onCreate 内部で他のイベントの Callback 関数を登録する
(3) 各イベントで Callback 関数が呼ばれる

●android_native_app_glue

ndk の sample/native-activity や NativeActivity の Reference に
掲載されてるコードは android_native_app_glue を使っています。
これはサンプルに含まれる Utility Library です。
内部では下記の動作を行っています。

1. 各イベントごとの Callback 関数を登録する
2. NativeActivity 用のスレッドを生成する
3. イベントを格納するキューを作る
4. ユーザー定義関数 android_main() をスレッドから呼び出す

つまり、これにより android_main をイベント待ちのループとして記述できる
ようになります。Win32 API とかでよくあるスタイルです。

●static 領域の初期化

NativeActivity でも従来の jni 経由の NDK (dll) 呼び出しと全く同じです。
Activity が onDestroy で破棄されても dll 自体はしばらくメモリ上に
常駐する可能性があります。
この場合再び onCreate しても static 変数の値が初期化されずに以前の値を
残しています。

onCreate 時に自分で初期化するか前回試したような dll の分離が必要となります。

参考ページ
NativeActivity

関連エントリ
Android NDK の初期化と dll の分離
Android アプリケーションとプロセス