1: 在C++文件中声明Java/kotlin 中Native 类的路径,注册的时候,会用到
注意:将 . g改成 "/ "
const char *NATIVE_CLASS_PATH = "com/ya/jnidynamicregister/NativeMethod";
kotlin 中封装native 函数的代码
class NativeMethod {
external fun getString(nameList: Array<String>, value: Int): String
external fun execJniCallJava()
}
2: C++ 中的 native 函数
jstring getString(JNIEnv *env, jobject thisObj) {
return env->NewStringUTF(string(",,晚安啦,,").c_str());
}
具体如下:
-
声明navite 函数对应数组,数组类型:JNINativeMethod
- JNINativeMethod 的结构体
typedef struct { // 在kotlin class 中声明的native函数名 const char* name; // 函数的签名,用android studio的Kotlin Bytecode 就可以查看,直接copy即可, 免得写错 const char* signature; // 对应的native函数名 void* fnPtr; }JNINativeMethod-
JNINativeMethod 的结构体 * 声明nativeMethods 数组
JNINativeMethod nativeMethods[] = { {"getString", "()V", (void *) getString}, }; -
JNI_OnLoad 中注册 在nativeMethods 数组,具体如下:
- step 1:JNI_OnLoad
jint JNI_OnLoad(JavaVM *vm, void *reserved) { JNIEnv *env = nullptr; LOGD("JNI_OnLoad "); if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) { return -1; } if (env == nullptr) return -1; if (!registerNatives(env)) { return -1; } return JNI_VERSION_1_6; }- step 2:registerNatives()
int registerNatives(JNIEnv *env) { if (!registerNativeMethods(env, NATIVE_CLASS_PATH, nativeMethods, sizeof(nativeMethods) / sizeof(nativeMethods[0]))) { return JNI_FALSE; } return JNI_TRUE; }- step 3:registerNativeMethods()
- 主要就是 jni 中的RegisterNatives() 函数
int registerNativeMethods(JNIEnv *env, const char *className, JNINativeMethod *gMethods, int numMethods) { jclass clazz = env->FindClass(className); if (clazz == nullptr) return JNI_FALSE; if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) { LOGE("registerNativeMethods in error"); return JNI_FALSE; } return JNI_TRUE; }
3: 在android的Activity中调用
// 全局声明
private lateinit var nativeMethod: NativeMethod
// 在onCrete中声明
nativeMethod = NativeMethod()
// 在点击事件中使用
nativeMethod.execJniCallJava()
静态注册和静态注册的区别
-
静态:运行的时候 去so寻找 native 函数
- 个人感觉: 编写,追踪函数调用挺方便的,native 还不爆红,
-
动态: 编译加载so的时候就把函数进行注册,之后的调用可以直接使用
- 个人感觉: 有些面向对象的感觉,将native函数封装在结构体数组里,然后一股脑的交给JVM;
- 代码爆红,有点膈应;