本文主要记录jni动态注册的步骤,这里使用Android studio 的ndk-build,关于使用cmake的,有时间再写
1、在src/main/java/下新建一个java类,类似如下:
public class testUtils {
static {
System.loadLibrary("testJNI"); //加载so,在mk文件中指定
}
//声明对应的native方法
public static native void setFileName(String fileName);
}
2、在src/main/下新建一个jni folder,将Android.mk 和 对应的 cpp/h文件导入或创建到该文件夹中
3、cpp中编写动态注册的代码,类似如下:
void setFileName(JNIEnv *env, jclass thiz, jstring filename){
MY_LOG_INFO("[+] set file name: %s",filename);
}
//指定相对应的包名和类名
static const char *classPathName = "com/abc/test/test";
//动态注册的方法结构体
static JNINativeMethod methods[]= {
{"setFileName","(Ljava/lang/String;)V",(void*)setFileName }
};
//注册native方法函数
static int registerNativeMethods(JNIEnv* env, const char* className,
JNINativeMethod* gMethods, int numMethods){
jclass clazz;
clazz = env->FindClass(className);
if (clazz == NULL)
return JNI_FALSE;
if (env->RegisterNatives(clazz, gMethods, numMethods)<0)
return JNI_FALSE;
return JNI_TRUE;
}
//注册native函数
static int registerNatives(JNIEnv *env){
if (!registerNativeMethods(env, classPathName,
methods, sizeof(methods)/sizeof(methods[0]))) {
return JNI_FALSE;
}
return JNI_TRUE;
}
接着在JNI_OnLoad中,调用注册函数:
extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
JNIEnv *env = NULL;
if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK){
return -1;
}
if (registerNatives(env) != JNI_TRUE){
return -1;
}
return JNI_VERSION_1_4;
}
4、打开terminal,cd src/main/jni文件夹中,然后执行ndk-build
如果没有出错则会生成libs/obj两个文件夹
此时,回去看java类中的setFilename方法,依旧是红色,显示无法找到定义,所以需要进行下面最为关键的一步。
5、接着最为关键的一步:
(1)在项目名称的右键点击Link C++ Project with Gradle
(2)然后选择ndk-build
(3)指定Android.mk文件路径,就在src/main/jni路径下
(4)确定即可