天天看點

android+jni+動态加載,Android JNI的初步使用--2 動态加載

Android JNI的初步使用--1

上一篇做了一個jni靜态加載的示例,這一篇來看一下jni的方法的動态加載。

我先展示一下cpp中動态加載的示範代碼:

jstring fun1(JNIEnv *env, jobject jobj) {

std::string hello = "動态注冊";

return env->NewStringUTF(hello.c_str());

}

jstring fun2(JNIEnv *env, jobject jobj) {

std::string hello = "動态注冊";

LOGD("%s", hello.c_str());

return env->NewStringUTF(hello.c_str());

}

static const char *mClassName = "com/hao/minovel/jni/DragCrash";

static const JNINativeMethod mMethods[] = {

//參數一:java方法名

//參數二:()中為調用時需要的傳殘參類型後面為傳回類型

//參數三:jni中對應的方法

{"getString2", "()Ljava/lang/String;", (jstring *) fun1},

{"initDate", "(Lcom/hao/minovel/jni/Test;)Ljava/lang/String;", (jstring *) fun2},

};

//在調用java的load的時候 會調用此方法

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *res) {

JNIEnv *env = NULL; //獲得 JniEnv

int r = vm->GetEnv((void **) &env, JNI_VERSION_1_4);

if (r != JNI_OK) { return -1; }

jclass mainActivityCls = env->FindClass(mClassName); // 注冊 如果小于0則注冊失敗

r = env->RegisterNatives(mainActivityCls, mMethods, 2);//第三個參數為你需要加載的mMethods中的數量

if (r != JNI_OK) { return -1; }

return JNI_VERSION_1_4;

}

在上面的代碼中,我們需要關注的是JNI_Onload中的兩個方法

jclass mainActivityCls = env->FindClass(mClassName); // 注冊 如果小于0則注冊失敗

r = env->RegisterNatives(mainActivityCls, mMethods, 2);//第三個參數為你需要加載的mMethods中的數量

其中mClassName為java中的native方法的類路徑,FindClass方法會通過此路徑擷取到需要加載的類ID;

而RegisterNatives則通過擷取的類ID和方法介紹及方法加載數來注冊native方法。

ps:注冊多個方法時,需要記得修改RegisterNatives方法的第3個參數。

而RegisterNatives方法中的第二個參數mMethods中包含的是需要注冊的ative方法重要資訊,mMethods是一個jni.h中的一個結構體,代碼如下:

typedef struct {

const char* name;//方法名

const char* signature;//方法簽名

void* fnPtr;//jni中的方法名和傳回類型

} JNINativeMethod;

name:java中native方法的方法名。

signature:java方法的簽名。

例如:(I)Ljava/lang/String;表示該方法的是傳入了一個int類型的參數,傳回一個String。具體類型解釋見下面的簽名介紹;

fnPtr:jni中對應的方法。

例如:(jstring *) fun2 對應的就是 cpp中的fun2方法,()為方法的傳回類型。

java中的簽名介紹:

Java類型 相應的簽名 例子

boolean Z

byte B

char C

short S

int I

long L

float F

double D

void V

Object L用"/"分割的完整類名; ex: Ljava/lang/String;

Array [簽名 ex: [I   [Ljava/lang/String;

Method (參數1類型簽名參數2類型簽名...)傳回值類型簽名

我們也可以通過javap指令來擷取方法的簽名;

指令:javap -s -p 類.class

public static native java.lang.String getString2();

descriptor: ()Ljava/lang/String;

public static native java.lang.String initDate(com.hao.minovel.jni.Test);

descriptor: (Lcom/hao/minovel/jni/Test;)Ljava/lang/String;

這個是我擷取的測試兩個方法的簽名。

以上是我對jni動态注冊的了解,歡迎大佬指正。

Android JNI的初步使用--3