Android JNI學習09-AndroidStudio3.6 在JNI中動態註冊java層的方法

鏈接: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層的方法

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章