所有内容为记录学习过程,不是大牛尽情谅解。所有分析都参考深入理解Android 卷一 概括: 在Android平台上,JNI就是一座将Native世界和Java世界间的天堑变为通途的桥。 JAVA <---> JNI <---> NATIVE Java世界对应的是MediaScanner 而这个MediaScanner类有一些函数需要由Native层来实现 JNI层对应的是libmedia_ni.so库 media_jni是JNI库的名字,其中,下划线前的media是Native层库的名字。 在Android平台上基本采用lib模块名_jni.so的命名方式 Native层对应的是libmedia.so 这个库完成实际功能 MediaScanner 将通过JNI库 libMedia_jni.so和Native层 现在看代码 在frameworks/base/media/java/android/media/MediaScanner.java 加载对应的JNI库,media_jni是JNI库名,在实际加载的时候拓展成libmedia_jni.so,在windows平台上扩展为media_jni.dll Native函数的声明 现在看一下 native_init();函数 在framewords/base/media/jni/android_media_MediaScanner.cpp 这部分为MediaScanner的JNI代码 到这里有个问题native_init 怎么就映射成了android_media_MedeaScanner_native_init了 仔细查看 native_init 函数 位于android.media这个包中MediaScanner.java这个问题中 这么一看思路就有点对了 android.media.MediaScanner.native_init 将这里面的.(点)换成下划线就对应上了。 因为在native语言中,”.”符号点有着特殊的含义,所以JNI 层需要把java函数名称(包括包名)中的”.”换成”_” 也就是通过这种方式native_init 找到了自己的另一半android.;mediaMediaScanner.native_init 可以看出 静态方法就是根据函数名来建立 java函数和JNI函数的关联关系的,这个关联关系由虚拟机完成 下面看一下JNI 中的动态注册 Java native 函数 和JNI 函数 是一一对应的,其对应该系用一个结构来保存。 JNINativeMethod的结构 const char* name;//java中的native函数的名称,不用携带包路径,例如 native_init const char* signature;//函数签名信息,用字符串表示,是参数类型和返回值类型的组合 void* fnPtr;//JNI层对应函数的函数指针,void*类型 } JNINativeMethod; 应该如何使用这个结构体呢,看一下MediaScanner JNI 层的做法 register_android_media_MediaScanner(JNIEnv *env)函数 调用AndroidRuntime::registerNativeMethods(); 完成JNI函数的注册问题 Frameworks/base/core/jni/AndroidRuntime.cpp Dalvik/libnativehelper/JNIHelp.c 其实这里面只用两个操作就完成了 注册 第一个是获取android/media/MediaScanner 类 另一个 就是将刚才JNINativeMethod 里面注册的方法和这个获取的类绑定 为了学习JNI中的数据类型转换,这里看一下processFile这个函数 在MediaScanner.java中的定义 Private native void processFile(String path, String mimeType, MediaScannerClient client) 对应的android_media_MediaScanner.cpp中 Static void android_media_MediaScanner_processFile(JNIEnv *env,jobject thiz, jstring path, Jstring mimetype, jobject client) Java中的String 对应 JNI 中的jstring Java中的MediaScannerClient 对应JNI中的jobject 如果都用jobject表示,那么该如何操作呢。 解释一下JNI层中几个函数参数的意义 第一个JNIEnv 是一个 JAVA环境,对于这个变量,暂时没明白,以后分析。 第二个jobject 由于是非静态方法所以传过来的是MediaScanner对象,它表示是安格MediaScnner对象上调用了processFile (如果该函数在java层定义为static寒素那么这个参数就换位jclass 表示在哪个class中调用了该静态方法 这个应该很容易理解) |
|