Android: NDKを使ってみました(2)

NDK(Android Native Development Kit)を使ってネイティブコードを利用するAndroidアプリケーション(Androidのアプリケーションフレームワークに従ったアプリ)の作り方としては、以下の2通りの方法がある。
参考:
http://developer.android.com/sdk/ndk/overview.html#choosing

 1) JavaのコードからJNI(Java Native Interface)のAPIを介して、C/C++からコンパイルされたシェアードライブラリを呼び出す方法。
   Andorid1.5以降でサポート。

  参考:NDKのsamples/hello-jni

 2) ネイティブアクティビティとして作る方法。アプリはJavaで書く部分はなく、すべてC/C++で書く。
   ただしこの方法ではサービスやコンテントプロバイダにアクセスすることはできない。
   この方法も、DalvikVM上のバイトコードから呼び出されるシェアードライブラリとなる。
   Android 2.3 (API Level 9)以降で動かすことができる。
  
  参考:NDKのdocs/NATIVE-ACTIVITY.HTML
     NDKのsamples/native-activity、NDKのsamples/native-plasma

それ以外に、

 3) アプリケーションフレームワークから独立したスタンドアロンアプリケーション(lsやcatのようなLinuxコマンド)を作ることもできる。
  参考:NDKのdocs/STANDALONE-TOOLCHAIN.html
     NDKのsamples/test-libstdc++

前回の記事では1)のNDKのサンプル hello-jniを試したので、今回は2)のネイティブアクティビティのサンプルをコンパイル、実行してみました。

前回はNDKは7月にリリースされたRevision 6を使いましたが、今回は8月にリリースされたRevision 6bを使いました。
6bはいくつかのバグフィックスだけのようで、6との機能の違いはないようです。
参考:
http://developer.android.com/sdk/ndk/index.html

NDKのdocs/NATIVE-ACTIVITY.HTMLによると、ネイティブアクティビティの作り方は次のようになるようです。

  • コマンド"android create project"か、Eclipseで新規プロジェクトを作り、そのルートディレクトリの直下にjniディレクトリを作る。
    jniディレクトリの下にC/C++で書いたすべてのソースを置く。

  • AndroidManifest.xmlファイルを作成する。ポイントは以下の2点。
     - activityタグのandroid:name属性にandroid.app.NativeActivityを指定する => activity android:name="android.app.NativeActivity"
     - meta-dataタグのandroid:name属性にandroid.app.ライブラリ名を指定する => meta-data android:name="android.app.ライブラリ名"
      (ライブラリ名は、libプリフィックスと.soサフィックスを外す)

  • ネイティブコードにnative_activity.hをincludeし、ANativeActivity_onCreate()関数を実装する。
    アプリが起動するとDalvikVM上のバイトコードからまず最初にこの関数が呼ばれる。
    この関数内に、ANativeActivity->callbacksに必要なポインタを指定し、ANativeActivity->instanceフィールドに必要なデータのアドレスを指定する。

    なお、android_native_app_glue.h(native_activity.hをincludeしている)をincludeし、ANativeActivity_onCreate()関数を実装したヘルパーライブラリandroid_native_app_glue.cが用意されているので、これをそのまま利用するか、必要な変更を加えて利用すると良い。
    android_native_app_glueはandroid_main()を呼び出すように書かれているので、これを利用するアプリはandroid_main()がエントリポイントになる。
    (サンプルのnative-activityもnative-plasmaもこのヘルパーライブラリを使用しています。)

    参考:上記ファイルのパス
     native_activity.h:platforms/android-9/arch-arm/usr/include/android/native_activity.h
     android_native_app_glue.h:sources/android/native_app_glue/android_native_app_glue.h
     android_native_app_glue.c:sources/android/native_app_glue/android_native_app_glue.c

  • jniディレクトリの下にAndroid.mkを作る。

    (例)
    LOCAL_PATH := $(call my-dir)
    include $(CLEAR_VARS)
    LOCAL_MODULE := my_native_module
    LOCAL_SRC_FILES := my_native_code.c
    include $(BUILD_SHARED_LIBRARY)

  • プロジェクトのディレクトリの下でndk-buildコマンドを実行する。 => ndk-buildコマンドについても多少書いたので、よかったらこちらを見てください。
  • Eclipseでプロジェクトのビルド、実行をする。

以下、サンプルのnative-activityとnative-plasmaをビルド、実行した画面です。

  native-activity   native-plasma