鏈接:https://pan.baidu.com/s/1zB9r5WwuTMIPNMlYl5HlvA
提取碼:5ndl
在瞭解動態註冊之前,先來看下靜態註冊,如下
在你編寫java的native方法後,立即根據相應規則編寫對應的native實現函數,這種native實現方式叫做靜態註冊,即在編譯期間,就確定了對應關係。還有一種就是在運行期間,才確定java的native方法和native實現函數的對應,這種對應方式就叫做動態註冊。
現在就用代碼來演示這個動態註冊的過程。
先在MainActivity中,編寫2個native
在myJNIFunction.cpp中編寫JNI_OnLoad
int JNI_OnLoad(JavaVM *vm,void *re){
return JNI_VERSION_1_2;
}
注意:
JNI_OnLoad這個函數的名字和參數都是固定的,不要寫錯了,該函數會被自動調用
它什麼時候被調用呢?
在MainActivity中,加載動態庫時,如下,就會自動調用JNI_OnLoad
System.loadLibrary("native-lib");
我們具體的註冊過程,就是在JNI_OnLoad中完成的,下面就來完善註冊代碼吧
先編寫JNINativeMethod
static const JNINativeMethod method[] = {
{"dynamicJavaTest","()V",(void*)dynamicTest},
{"dynamicJavaTest2","(I)I",(void*)dynamicTest2},
};
JNINativeMethod是一個結構體,裏面有3個屬性
typedef struct {
const char* name;
const char* signature;
void* fnPtr;
} JNINativeMethod;
name:
java層的native方法名字
signature:
java層的native方法簽名
fnPtr:
java層native所對應的JNI函數
現在前2個參數都有了,那麼接下來就創建java層native方法對應的JNI函數吧
dynamicJavaTest 對應 dynamicTest 代碼如下
void dynamicTest(){
LOGE("JNI dynamicTest");
}
dynamicJavaTest2 對應 dynamicTest2 代碼如下
jint dynamicTest2(JNIEnv *env, jobject instance,jint i){
LOGE("JNI dynamicTest2:%d",i);
return 100;
}
到此JNINativeMethod 配置 已經完畢,JNINativeMethod 確定了對應關係。接下來繼續在JNI_OnLoad中,完善註冊過程.
獲取JNIEnv
JNIEnv *env = 0; // 獲得JNIEnv
int r = vm->GetEnv((void**)&env,JNI_VERSION_1_2);
if (r != JNI_OK){// 小於0 失敗 ,等於0 成功
return -1;
}
通過JNIEnv獲取java的native方法所在類的class
static const char *mClassName = "com/example/jnistudy/MainActivity";
jclass jcls = env->FindClass(mClassName);
開始註冊
env->RegisterNatives(jcls,method, sizeof(method)/ sizeof(JNINativeMethod));
RegisterNatives第三個參數是註冊的個數,這裏是通過sizeof(method)/ sizeof(JNINativeMethod)動態計算的,實際上就是2個。
完整代碼如下
void dynamicTest(){
LOGE("JNI dynamicTest");
}
jint dynamicTest2(JNIEnv *env, jobject instance,jint i){
LOGE("JNI dynamicTest2:%d",i);
return 100;
}
int JNI_OnLoad(JavaVM *vm,void *re){
static const JNINativeMethod method[] = {
{"dynamicJavaTest","()V",(void*)dynamicTest},
{"dynamicJavaTest2","(I)I",(void*)dynamicTest2},
};
JNIEnv *env = 0; // 獲得JNIEnv
int r = vm->GetEnv((void**)&env,JNI_VERSION_1_2);
if (r != JNI_OK){// 小於0 失敗 ,等於0 成功
return -1;
}
//獲得 class對象
static const char *mClassName = "com/example/jnistudy/MainActivity";
jclass jcls = env->FindClass(mClassName);
//註冊
env->RegisterNatives(jcls,method, sizeof(method)/ sizeof(JNINativeMethod));
return JNI_VERSION_1_2;
}
到此,動態註冊過程已經完畢,現在就來開始測試吧
在MainActivity中調用dynamicJavaTest
運行結果如下
在MainActivity中調用dynamicJavaTest2
運行結果如下
、 Android JNI學習10-AndroidStudio3.6 在JNI中創建JNI線程,並且實現在JNI線程中調用java層的方法