1.jni 静态注册
第一步:新建java类:
System.loadLibrary后面会讲到
第二步:通过javah 命令生成.h文件 (固定命令) (包名)
C:\MyNDKTest\mylibrary\build\intermediates\classes\release>javah -jni ndk.example.com.mylibrary.JniTest
注意:找到class文件的包名的上一级目录,否则无法生成.h文件
第三步:将生成的h文件拷贝到jni目录,然后新建一个cpp或者c文件,内容如下:
在jni生成的getMax函数:Java_ndk_example_com_mylibrary_JniTest_getMax
jni函数命名规则: 1 .包名+类名+函数名
2.java包名的“.”改成“_”
3.如果java函数名签名里面多了“_”则在前面加1
比如:java包名com.test 类名Class_getmin
那么生成com_test_Class_1getmin()函数
#include <jni.h> /* Header for class ndk_example_com_mylibrary_JniTest */ #ifndef _Included_ndk_example_com_mylibrary_JniTest #define _Included_ndk_example_com_mylibrary_JniTest #ifdef __cplusplus extern "C" { #endif /* * Class: ndk_example_com_mylibrary_JniTest * Method: getMax * Signature: (II)I */ JNIEXPORT jint JNICALL Java_ndk_example_com_mylibrary_JniTest_getMax (JNIEnv *evn, jobject, jint num1, jint num2){
if(num1>num2) return num1 else return num2; } #ifdef __cplusplus } #endif #endif
第四部:生成jar和so
使用命令gradlew makeJar命令生成jar 和so,参考 https://mp.csdn.net/postedit/79502214
1.jni 动态注册
第一步:定义方法名: JNIEXPORT jint JNICALL getMax(JNIEnv *evn, jobject jobject1, jint num1, jint num2){ LOGD("-------------------------getMax----------------------"); return (num1>num2)?num1:num2; } JNIEXPORT void JNICALL test(JNIEnv *evn, jobject jobject1){ LOGD("-------------------------test----------------------"); } 第二步:定义 JNINativeMethod数组 JNINativeMethod method_table[] = { {"getMax", "(II)I", (int*) getMax}, {"test", "()V", (void*) test} }; 第三步:重写JNI_OnLoad JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved){ jclass myClass; JNIEnv* env = NULL; //注册时在JNIEnv中实现的,所以必须首先获取它 jint result = -1; if((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_4) != JNI_OK) //从JavaVM获取JNIEnv,一般使用1.4的版本 return -1; myClass = (*env)->FindClass(env, className); if(myClass == NULL) { return -1; } int size=sizeof(method_table)/sizeof(method_table[0]); if((*env)->RegisterNatives(env,myClass,method_table,size)<0) { return -1; } return JNI_VERSION_1_4; //这里很重要,必须返回版本,否则加载会失败。 }
完整的C代码如下:
#include <jni.h> #include "stddef.h" #include <android/log.h> static const char *TAG = "Test"; #define LOGI(fmt, args...) __android_log_print(ANDROID_LOG_INFO, TAG, fmt, ##args) #define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, TAG, fmt, ##args) #define LOGE(fmt, args...) __android_log_print(ANDROID_LOG_ERROR, TAG, fmt, ##args) #ifndef _Included_ndk_example_com_mylibrary_JniTest #define _Included_ndk_example_com_mylibrary_JniTest #ifdef __cplusplus extern "C" { #endif JNIEXPORT jint JNICALL getMax(JNIEnv *evn, jobject jobject1, jint num1, jint num2){ LOGD("-------------------------getMax----------------------"); return (num1>num2)?num1:num2; } JNIEXPORT void JNICALL test(JNIEnv *evn, jobject jobject1){ LOGD("-------------------------test----------------------"); } //方法数组,JNINativeMethod的第一个参数是Java中的方法名,第二个参数是函数签名,第三个参数是对应的方法指针。 //Java方法的签名一定要与对应的C++方法参数类型一致,否则注册方法可能失败。 JNINativeMethod method_table[] = { {"getMax", "(II)I", (int*) getMax}, {"test", "()V", (void*) test} }; static const char* const className="ndk/example/com/mylibrary/JniTest"; JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved){ jclass myClass; JNIEnv* env = NULL; //注册时在JNIEnv中实现的,所以必须首先获取它 jint result = -1; if((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_4) != JNI_OK) //从JavaVM获取JNIEnv,一般使用1.4的版本 return -1; myClass = (*env)->FindClass(env, className); if(myClass == NULL) { return -1; } int size=sizeof(method_table)/sizeof(method_table[0]); if((*env)->RegisterNatives(env,myClass,method_table,size)<0) { return -1; } return JNI_VERSION_1_4; //这里很重要,必须返回版本,否则加载会失败。 } #ifdef __cplusplus } #endif #endif