1.动态注册的优缺点
需要我们手动建立联系,增加代码量,效率提高
允许自己定义函数名称.(native层的函数名称随便取,不需要遵守格式了)
2.在动态注册中 需要在.c文件中加入2个重要的函数和一个结构体,这三个函数分别是
jint JNI_OnLoad(JavaVM* vm, void* reserved){}
static int registNativeMethod(JNIEnv *env) {}
NINativeMethod nativeMethod 结构体.
在Android中使用 System.loadlibrary()方法加载动态库时,JVM会调用jni库中的JNI_OnLoad()函数, 所以我们可以在这个函数中 设置一些初始化操作.
这个函数不重写的话默认也是有的
在jni.h头文件中可以查看这个函数.
其中返回值jint代表的是动态库 需要的jni版本,如果jvm不识别 则不能加载这个库.
static int registNativeMethod(JNIEnv *env) {} 方法中 参数为JNIEnv指针
NINativeMethod nativeMethod 结构体.
中参数的含义
1.name 为Java代码中native方法的名称
2.signature:为方法的签名
3.fnPtr:是一个函数指针,指向jni层的一个函数,也就是java层和native层建立联系的函数
signature:方法签名的获取方法如下
编译项目后再app/build/intermediates/中 找到javac文件夹
找到对应的类右键单击选择open In->terminal
在命令窗口输入javap -s 则会得到方法签名
开始搬砖,码代码:
1. 设置native方法 (注意这里因为使用动态注册 在动态注册的时候没有使用JNI对应的函数名称[任意命名的] 所以这里方法上会爆红 原因是在.c代码中 找不到对应的函数 我们可以不用管它)
2.在.c代码中加入对应的JNI_OnLoad(),registNativeMethod()方法 以及JNINativeMethod nativeMethod 结构体,内容如下:
extern "C"
JNIEXPORT jint JNICALL
native_txt(JNIEnv *env, jobject clazz, jstring msg) {
const char *p_msg = env->GetStringUTFChars(msg, JNI_FALSE);
__android_log_print(ANDROID_LOG_INFO, "jni-test", "method = %s, msg = %s", __FUNCTION__, p_msg);
return 0;
}
extern "C"
JNIEXPORT jint JNICALL
//这里名字任意命名的
native_static_1text(JNIEnv *env, jclass clazz, jstring msg) {
const char *p_msg = env->GetStringUTFChars(msg, JNI_FALSE);
__android_log_print(ANDROID_LOG_INFO, "jni-test", "method = %s, msg = %s", __FUNCTION__, p_msg);
return 0;
}
static const JNINativeMethod nativeMethod[] = {
{"text", "(Ljava/lang/String;)I", (void *) native_txt},
//第一个参数 java代码中 native方法的名称 第二个是方法签名 最后一个参数是对应上面的函数名称
{"static_text", "(Ljava/lang/String;)I", (void *) native_static_1text}
};
static int registNativeMethod(JNIEnv *env) {
int result = -1;
//注意这里类的全文件 需要 使用/替换.
jclass aclzz = env->FindClass("com/net/jnidynamic/JNIUtils");
if (env->RegisterNatives(aclzz, nativeMethod,
sizeof(nativeMethod) /sizeof(nativeMethod[0])) ==JNI_OK) {
result =0;
}
return result;
}
jint JNI_OnLoad(JavaVM* vm, void* reserved){
JNIEnv *env =NULL;
int result = -1;
if (vm->GetEnv((void **) &env, JNI_VERSION_1_1) ==JNI_OK) {
if (registNativeMethod(env) ==JNI_OK) {
result =JNI_VERSION_1_6;
}
return result;
}
}
结束:
编译出so文件 加入libs文件夹 (步骤省略 同静态注册)
运行程序得到结果