android-ndk-r5からNativeActivityが使えるようになったので試しに使ってみました。
NativeActivityのリファレンス
を見つつ、サンプルプログラム(native-activity)を削っていって必須部分を試してみたら、
最小だと思われるプログラムは以下のようになりました。
NativeActivityは2通りの実装方法があるようですが、今回はnativeから android_native_app_glue を使うだけで動くらしい楽な方。
まずjava側の準備としてeclipseで空のプロジェクトを作って AndroidManifest.xml に以下の内容を追加。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="net.ekesete.NDKr5_Test"
android:versionCode="1"
android:versionName="1.0">
<application android:label="@string/app_name" android:hasCode="false">
<activity android:name="android.app.NativeActivity"
android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden">
<meta-data android:name="android.app.lib_name"
android:value="native-activity" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="9" />
</manifest>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="net.ekesete.NDKr5_Test"
android:versionCode="1"
android:versionName="1.0">
<application android:label="@string/app_name" android:hasCode="false">
<activity android:name="android.app.NativeActivity"
android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden">
<meta-data android:name="android.app.lib_name"
android:value="native-activity" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="9" />
</manifest>
これでjavaソースは無しでもよくなります。
ndk側はsample/native-activityのmain.cを書き換えて
#include <jni.h>
#include <android/log.h>
#include <android_native_app_glue.h>
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "native-activity", __VA_ARGS__))
void android_main(struct android_app* state) {
int count=0;
// Make sure glue isn't stripped.
app_dummy();
while(1)
{
LOGI("logtest %d",count);
count++;
if(count == 30)
{
break;
}
}
return;
}
#include <android/log.h>
#include <android_native_app_glue.h>
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "native-activity", __VA_ARGS__))
void android_main(struct android_app* state) {
int count=0;
// Make sure glue isn't stripped.
app_dummy();
while(1)
{
LOGI("logtest %d",count);
count++;
if(count == 30)
{
break;
}
}
return;
}
というのを作ってみました。
コードの内容的には見て分かるとおり単にadbのログに数字を吐くだけです。
android_main()の中にある
app_dummy();
を呼ばないとライブラリ(.soファイル)のロードエラーになりました。
とりあえずmain関数で呼んでおく必要があるようです。
全く中を見ていませんが、こいつはアクティビティとダミーの画面を出してくれるだけの関数のようで、
ソース内部で描画しないと真っ黒な画面が出たままになります。
#narive-activityの元のサンプルソースはOpenGLを使って何かしてます。
ループを抜けると、コード上は終了ですが、ログに
android_app_destroy!
と出ても、画面はそのまま残ります。
終わらせる方法を実装しないといけないみたいです。
[2011.4.2 追記]
終了しないのは当然で、一通りは知り終わった後の終了処理をしていないのと、
backキー契機の場合はキーを押した情報がアプリまで届いていないためです。(app_glueまでは来てるみたい。)
後ほど android_native_app_glue を使った場合にどう動いているのかわかった部分から別エントリーとしてあげる予定。