这章主要从4个方面对JNI进行了阐述:
1.JNI的注册,静态注册和动态注册
2.Java和JNI层的类型转换
3.JNIEnv和jstring的用法,类型签名
4.垃圾回收和异常处理
JNI的使用,JNI是Java层调用Native层的接口。
以MediaScanner为例:
Java层:
frameworks/base/media/java/android/media/MediaScanner.java
static {
System.loadLibrary("media_jni"); //加载so库,在java层,会接上lib,为libmedia_jni.so
native_init();k
}
//声明native接口
private static native final void native_init();
Native层:
文件:
frameworks/base/media/jni/android_media_MediaScanner.cpp //这里的命名是packagename+classname
static void android_media_MediaScanner_native_init(JNIEnv *ent){
jclass clazz = env->FindClass(kClassMediaScanner); //这个就是得到MediaScanner.cpp类
}
MediaScanner.cpp文件即是最后执行函数的地方:
frameworks/av/media/libmedia/MediaScanner.cpp
Java层和Native层函数的关联即为注册,分为静态注册和动态注册
静态注册则是通过javah,生成头文件
javah -d /Users/longcheng/Documents/AndroidCode/DemoCode/JNIDemo/app/src/main/jni(jni的目录)
动态注册
a.添加到JNINativeMethod结构体
static JNINativeMethod methods[] = {
{"stringFromJni", "()Ljava/lang/String;", (void*)getCLanguageString},
};
b.调用register
static int registerNativeMethods(JNIEnv* env , const char* className , JNINativeMethod* gMethods, int numMethods)
{
jclass clazz;
clazz = (*env)->FindClass(env, className);
if (clazz == NULL) {
return JNI_FALSE;
}
if ((*env)->RegisterNatives(env, clazz, gMethods, numMethods) < 0) {
return JNI_FALSE;
}
return JNI_TRUE;
}
c.通过ONLoad加载
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved)
{
JNIEnv* env = NULL;
jint result = -1;
if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) {
return -1;
}
assert(env != NULL);
//动态注册,自定义函数
if (!registerNatives(env)) {
return -1;
}
return JNI_VERSION_1_4;
}