Android NDKの使い方

Java側でやる事

モジュールをロードする

System.loadLibraryメソッドを使ってライブラリをロードする。

staticでなくてもよいが、netiveメソッドが呼ばれる前にロードする必要がある。

public class MainActivity extends Activity {
    static {
            System.loadLibrary("hello-jni");
    }
}

指定するモジュール名は以下の通り。

 

■gradleを使う場合

./app/build.gradleの[android.ndk]の[moduleName]で指定するモジュール名

model {
    android.ndk {
        moduleName = "hello-jni"
    }
}

android.mkを使う場合

LOCAL_MODULEで指定するモジュール名

LOCAL_MODULE := hello-jni



ネイティブに置き換えるメソッドを作る

 nativeキーワードを使ってメソッドを定義する。 

package aaa.bbb_ccc;

public class MainActivity extends Activity {
    static {
            System.loadLibrary("hello-jni");
    }

    public native String testJNI();
}

C++側でやる事

命名規約

Java側のnativeキーワードで定義されたメソッドをC++側で実装する場合、以下の規約に従う。

Java_[パッケージ名]_[クラス名]_[メソッド名]


※パッケージ名に「.(ピリオド)」がある場合は「_(アンダーバー)」へ置きかえる

パッケージ名に「_(アンダーバー)」がある場合は「_1」へ置きかえる

例)

aaa.bbb_cccパッケージ、Dddクラス、eeeメソッドの場合

  ↓

Java_aaa_bbb_1ccc_Ddd_eee

 

 

ヘッダーファイル

C言語でコーディングする場合は必要ないが、C++の場合は「extern "C"」で宣言する必要がある。

ちなみに「javah.exe」を使ってヘッダーファイルを作成する事も出来る。

#include <jni.h>

#ifdef __cplusplus
extern "C" {
#endif

JNIEXPORT jstring JNICALL Java_aaa_bbb_1ccc_MainActivity_testJNI( JNIEnv* env, jobject thiz );

#ifdef __cplusplus
}
#endif

2つの引数は固定で、3つ目以降が自身で定義した引数になる。

第1引数:JNI関連の関数を使う時に必要なオブジェクト

第2引数:このメソッドを持つJavaのクラスオブジェクト(上記例の場合MainActivity)

 

 

ソースファイル 

#include <jni.h>

jstring Java_aaa_bbb_1ccc_MainActivity_testJNI( JNIEnv* env, jobject thiz )
{
    return env->NewStringUTF("Hello from JNI !");
}