在看到本文之前,如果读者没看过笔者的前文 认识JNI(一),请先翻阅。
在上节Java层分析中提到,加载JNI库时调用了 System.loadLibray("media_jni");方法
System.loadLibray(*.so的档案名);//Java程序要求Android虚拟机载入所指定的C组件
在JNI层,MediaScanner的对应文件是
./frameworks/base/media/jni/android_media_MediaScanner.cpp
就其源码核心部分进行概况
【1】将指针保存到Java对象
android_media_MediaScanner_native_init(JNIEnv *env)
【2】创建Native层的MediaScanner对象
android_media_MediaScanner_native_setup(JNIEnv *env,jobject thiz)
Native层
【1】注册JNI函数,定义并注册JNINativeMethod
static JNINativeMethod gMethods[];
int register_android_media_MediaScanner(JNIEnv *env)
【2】实现注册工作 ( AnroidRuntime.cpp )
int AndroidRuntime::registerNativeMethods(JNIEnv *env,const
char * className,const JNINativeMethod* gMethods,int numMethods)
组件开发人员可以自行向Android虚拟机登记本地函数,以提高寻找函数的效率:在Android的/system/lib/libmedia_jni.so中添加代码片段
【3】实现动态注册
android_media_MediaPlayer.cpp中的函数JNI_OnLoad()
通过此方法,Android虚拟机就能够得知所使用的JNI版本
【4】处理路径参数
frameworks/av/media/libmedia/MediaScanner.cpp的processDirectory()函数
【5】扫描文件
scanFile()函数
【6】添加TAG信息
/frameworks/av/media/libmedia/MediaScannerClient.cpp的addStringTag()函数
【7】JNI中的环境变量
jni.h中定义了JNIEnv结构体,通过JNIEnv指针,才能够调用JNI环境中的方法
在使用JNIEnv接口时,要注意:JNIEnv指针被设计成了Thread Local Storage(TLS)变量,也就是说每一个Thread、JNIEnv变量都有独立的Copy,不能把Thread#1使用的JNIEnv传给Thread#2使用