所有内容为记录学习过程,不是大牛尽情谅解。所有分析都参考深入理解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的结构
type struct{
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中调用了该静态方法 这个应该很容易理解)
下面就开始 JNIEnv介绍了
下面开始jstring介绍
下面开始JNI类型签名介绍
下面开始垃圾回收介绍
下面开始JNI异常介绍