AndroidStudioでJNIサンプルのhello-jniをC++で呼び出すプロジェクトを作る

2015年7月27日

Android もほとんど触ったことがないわけですが、NDK を使わないといけなくなってしまったので勉強中です。
C++ で書いてある自前ライブラリを使いたいので、C++ のライブラリをネイティブプラグイン化しないといけません。
NDK は大半の話が C 言語前提で書かれているので結構困ります。
手始めに、NDKに同梱されているサンプルプロジェクトを C++ に書き換えて、JNI のサンプルプロジェクトを作ってみました。

IDE と NDK は、以下のものを使用しました。
IDE: Android Studio 1.3 beta
NDK: android-ndk-r10e

まずは C 言語のまま、サンプルプロジェクトを JNI で呼び出してみます。

1. Android Studio で新規プロジェクトを作成する

[New Project]
Application name: HelloJniTest
Company domein: example.com
Package name: com.example.hellojnitest

[Target Android Devices]
“Phone and Tablet" にチェック
Minimum SDK: API 21: Android 5.0 (Lolipop)

[Add an activity mobile]
Blank Activity を選択

[Customize the Activity]
デフォルトのまま

2. hello-jni をプロジェクトに追加する
HelloJniTest/app/src/main 直下に android-ndk-r10e/samples/hello-jni 直下にある “jni" フォルダをコピーします。

3. hello-jni のネイティブプラグインを生成する
ターミナルを起動して、HelloJniTest/app/src/main/jni へ移動します。
ターミナルから ndk-build を実行します。
HelloJniTest/app/src/main/libs にビルドされた .so ファイルが追加されます。

4. libs フォルダを HelloJniTest のビルド時に参照するようにする
HelloJniTest/app 直下にある build.gradle を以下のように変更します。
具体的には、sourceSets の部分を追加します。
上の行を入れると、NDK の自動ビルドが行われなくなります。
下の行はビルド時に参照しに行くフォルダを設定しています。
何も書かないと “jniLibs" の方だけ参照されますが、ndk-build で出力されるファイルは “libs" に出力されるので、参照先を追加している感じです。
“jniLibs" のパスも書いていますが、特に読み込むファイルがなければ、書かなくてもいいです。

apply plugin: 'com.android.application'

android {
    compileSdkVersion 22
    buildToolsVersion "23.0.0 rc2"

    defaultConfig {
        applicationId "com.example.hellojnitest"
        minSdkVersion 21
        targetSdkVersion 22
        versionCode 1
        versionName "1.0"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    sourceSets {
        main {
            jni.srcDirs = []
            jniLibs.srcDirs = ["src/main/jniLibs", "src/main/libs"]
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
}

5. アプリ上に表示する部分を作る
android-ndk-r10e/samples/hello-jni/src/com/example/hellojni/HelloJni.java
のソースコードから、import の部分と、class HelloJni の中身だけを、
HelloJniTest/app/src/main/java/com/example/hellojnitest/MainActivity.java のソースコードに上書きします。

6. Android Studio でビルドする
エラーが出ないことを強く祈ります。

7. シミュレータで起動してみる
シミュレータには、"Nexus 5 API 22 x86″ を使用しました。
起動して、「Hello from JNI ! Compiled with ABI x86.」と表示されれば OK です。

というわけでサンプルプロジェクトは無事に起動しました。
今度はサンプルプロジェクトのソースコードを C++ に変更してみます。

1. Android.mk の編集
LOCAL_SRC_FILES := hello-jni.c
の部分を、
LOCAL_SRC_FILES := hello-jni.cpp
に変更します。

2. hello-jni.cpp を追加する
hello-jni.c のファイル名を hello-jni.cpp に変更します。

3. hello-jni.cpp を編集する
関数部分を以下のように書き換えます。

extern "C"
{
    jstring Java_com_example_hellojnitest_MainActivity_stringFromJNI(JNIEnv* env, jobject thiz);
}

jstring Java_com_example_hellojnitest_MainActivity_stringFromJNI(JNIEnv* env, jobject thiz)
{
    // #ifdef 群は,そのまま.

    return env->NewStringUTF("Hello from JNI C++ !  Compiled with ABI " ABI ".");
}

問題なのは、C と C++ では JNIEnv の持っている関数が違うことです。
ここでしばらく悩みました。次からはさっさとソースコードを確認するようにします。

// C:
return (*env)->NewStringUTF(env, “Hello from JNI ! Compiled with ABI " ABI “.");
// C++:
return env->NewStringUTF(“Hello from JNI C++ ! Compiled with ABI " ABI “.");

4. hello-jni のネイティブプラグインを生成する
C の時と同様に、"HelloJniTest/app/src/main/jni" で ndk-build を行います。

5. Android Studio でビルドする
ビルドが通ったら、シミュレータで起動します。

6. シミュレータで起動してみる
使用するシミュレータは、先ほどと同様です。
起動して、「Hello from JNI C++ ! Compiled with ABI x86.」

ということで完成です。
今回は ndk-build を手動で行いましたが、Gradle の設定をすれば Android Studio からも ndk-build を走らせることができます。

おしまい。

スポンサーリンク

Android,NDKandroid,JNI,NDK

Posted by peliphilo