昨天拿到JNI的Android工程Demo,然后把demo整合到開發的主線工程上,發現調用JNI方法一直拋同一個異常
java.lang.UnsatisfiedLinkError: XXXclass.XXXmethod()
我以為是JNI的so庫有問題,但是demo運行時正常的,我無法找到原因的所在。我可以確認的我自己的問題,今天上午問到另外一個寫C的同事,向他描述了我的情況。然后他問我是不是包名不一致的原因,我恍然大悟。確實在我移植到主線上的工程時,將定於調用JNI的包名改掉了。而so庫在編譯的時候,是有指定調用的包名的,這個就可以解釋為何demo運行正常。只需要保證android工程調用JNI的包名與so庫定義的包名類名方法名一致就可以了。
下面簡單介紹一下JNI的 .h文件的內容
#ifndef _Included_packagename_classname //packagename 指的是android工程中的包名 classname指的是android工程中定義JNI的類,該類包含調用JNI的方法 #define _Included_packagename_classname #ifdef __cplusplus extern "C" { #endif /* * Class: packagename_classname * Method: methodName */ JNIEXPORT jint JNICALL Java_packagename_classname_methodname(); // jint 指的返回數據類型為int,JNICALL 后面指定了調用JNI方法的包名和類名、方法名...
JNI的 .c文件格式如下
#include "packagename_classname.h" // 這個是指的定義.h文件的命名,必須與.h文件的命名一致 #include <stdio.h> #include "../../../src/classname.h" // 包含src目錄下定義的.h文件 #include <android/log.h> static char *tag = "logtag_jni"; // 定義打印log的標簽 #define LOGI(...) __android_log_print(ANDROID_LOG_INFO , tag, __VA_ARGS__) #define LOGW(...) __android_log_print(ANDROID_LOG_WARN , tag, __VA_ARGS__) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR , tag, __VA_ARGS__) #define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, tag, __VA_ARGS__) #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG , tag, __VA_ARGS__) /* * Class: packagename_classname * Method: methodName */ JNIEXPORT jint JNICALL Java_packagename_classname_methodName(){...} ...... }
了解這些,幫助理解JNI就容易多了