1. Java が C++ を呼び出す
C++ がネイティブ メソッドを登録した後、対応する C++ ライブラリを Java クラスにロードすることを忘れないでください。
static { System.loadLibrary(“ネイティブライブラリ”); }
1. ネイティブ関数を静的に登録する
Java クラスでネイティブ メソッドを宣言すると、AndroidStudio はそのメソッドが未定義であることを通知し、その上にマウスを置くと、生成された JNI 関数が表示されます。
クリックすると、native-lib.cpp に対応するネイティブ メソッドが自動的に生成され、それをメソッドに実装するだけです。
2. 動的登録
また、Java クラスでネイティブ メソッドを宣言します。
宣言後、native-lib.cpp にメソッドを自分で実装します。
extern "C" JNICALL void TestJni(){
}
実装後にメソッドを登録します。
static JNINativeMethod getMethods[] = {
{
"nativeTestJni","()V",(void*)TestJni},
{
"nativeGetOffer","()Ljava/lang/String;", reinterpret_cast<void*>(getOffer)},
};
static int registerNativeMethods(JNIEnv* env, const char* className,JNINativeMethod* getMethods,int methodsNum){
jclass clazz;
//找到声明native方法的类
clazz = env->FindClass(className);
if(clazz == NULL){
return JNI_FALSE;
}
//注册函数 参数:java类 所要注册的函数数组 注册函数的个数
if(env->RegisterNatives(clazz,getMethods,methodsNum) < 0){
return JNI_FALSE;
}
return JNI_TRUE;
}
extern "C" jint JNIEXPORT
JNICALL JNI_OnLoad(JavaVM* jvm, void* reserved) {
JNIEnv* env = NULL;
if (jvm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
return -1;
}
assert(env != NULL);
//注册函数 registerNatives ->registerNativeMethods ->env->RegisterNatives
const char* className = "com/begoit/testjni/MainActivity";
if(!registerNativeMethods(env,className,getMethods, sizeof(getMethods)/ sizeof(getMethods[0])))
return -1;
//返回jni 的版本
return JNI_VERSION_1_6;
}
注:
1. JNINativeMethod の最初のパラメータは、登録するネイティブ メソッドの名前であり、Java クラスで定義されたメソッド名と一致している必要があります。
2. JNINativeMethod の 2 番目のパラメータは、ネイティブ メソッドのパラメータと戻り値です。括弧内のパラメータはパラメータ、括弧の外は戻り値です。複数のパラメータを指定できます。Java タイプに対応するシグネチャ
ava タイプ タイプ シグネチャ
Java タイプ | 型署名 |
---|---|
ブール値 | Z |
バイト | B |
文字 | C |
短い | S |
整数 | 私 |
長さ | J |
浮く | F |
ダブル | D |
親切 | L 完全修飾名。String など。その署名は Ljava/lang/util/String です。 |
配列 | [タイプ署名、[B |
3. className は登録する Java クラスです。形式に注意してください。
2. C++ が Java を呼び出す
extern "C"
JNIEXPORT void JNICALL
Java_com_begoit_xiurtcserver_XiuRTCService_OnProcessCameraData(JNIEnv *env, jobject thiz) {
// TODO: implement OnProcessData()
jclass myClass = env->FindClass("com/begoit/xiurtcserver/CameraProcessor");
if (myClass == nullptr) {
LOGE("can not find CameraProcessor class");
return;
}
LOGI("find CameraProcessor class");
method = env->GetMethodID(myClass, "TestJni", "()V");
LOGI("find GetMethodID TestJni");
jclass xiurtc = env->GetObjectClass(thiz);
LOGI("GetObjectClass XiuRTCService");
jfieldID fid = env->GetFieldID(xiurtc, "cameraProcessor",
"Lcom/begoit/xiurtcserver/CameraProcessor;");
LOGI("GetFieldID cameraProcessor");
jobject camera = env->GetObjectField(thiz, fid);
LOGI("GetObjectField cameraProcessor");
env->CallVoidMethod(camera, method);
LOGI("CallVoidMethod");
}
説明:
1. XiuRTCService クラスに CameraProcessor 型の CameraProcessor があり、
CameraProcessor には関数 TestJni があります。
2. XiuRTCService クラスで定義されたネイティブ メソッド OnProcessCameraData。
上記の関数は、XiuRTCService の CameraProcessor オブジェクトの TestJni メソッドを呼び出すように実装できます。