静态注册
原理:根据函数名来建立 java 方法与 JNI 函数的一一对应关系;
实现流程:
编写 java 代码;
利用 javah 指令生成对应的 .h 文件;
对 .h 中的声明进行实现;
弊端:
编写不方便,JNI 方法名字必须遵循规则且名字很长;
编写过程步骤多,不方便;
程序运行效率低,因为初次调用native函数时需要根据根据函数名在JNI层中搜索对应的本地函数,然后建立对应关系,这个过程比较耗时;
动态注册
原理:利用 RegisterNatives 方法来注册 java 方法与 JNI 函数的一一对应关系;
实现流程:
利用结构体 JNINativeMethod 数组记录 java 方法与 JNI 函数的对应关系;
实现 JNI_OnLoad 方法,在加载动态库后,执行动态注册;
调用 FindClass 方法,获取 java 对象;
调用 RegisterNatives 方法,传入 java 对象,以及 JNINativeMethod 数组,以及注册数目完成注册;
动态注册方式:
1:第一步先实现JNI_OnLoad方法(利用 RegisterNatives 方法来注册 java 方法与 JNI 函数的一一对应关系)
static const char* mClassName="com/demo/jnitest/MainActivity";
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)extern "C" JNIEXPORT jint JNICALL
JNI_OnLoad(JavaVM *vm,void *reserved){
LOGI("JNI_OnLoad");
_vm=vm;
JNIEnv *jniEnv;
jint r = vm->GetEnv((void**)&jniEnv, JNI_VERSION_1_6);
if (r!=JNI_OK){
return -1;
}
jclass pJclass = jniEnv->FindClass(mClassName);
if(pJclass==NULL){
printf("cannot get class:%s\n", mClassName);
return -1;
}
//注册
jniEnv->RegisterNatives(pJclass,getMethod, sizeof(getMethod)/sizeof(JNINativeMethod));
return JNI_VERSION_1_6;
}
2:利用结构体 JNINativeMethod 数组记录 java 方法与 JNI 函数的对应关系
static const JNINativeMethod getMethod[]{
{"javaAdd","(II)I",(jint *)C_Add},
};
其中testThread是在Activity页面声明好的native函数。
public native int javaAdd(int a,int b);
方法初始化调用:
extern "C" JNIEXPORT jint JNICALL
C_Add(JNIEnv *env,
jobject jobject1,
jint a,
jint b){
return a+b;
}