根据分析可知,MediaScannerRecevier接收广播请求之后由MediaScannerService完成扫描信息,并添加信息到媒体数据库中。同时MediaScannerProvider可以对数据库进行操作,主要涉及的查询、删除、更新等等。
MediaScannerService中的scan()函数中创建MediaScanner对象,完成扫描任务。主要分析MediaScanner的工作原理,从JAVA,JNI,和Native层三层分析。
MediaScanner对象创建后,由于是在MediaScannerService中的scan()完成的,所以MSS调用MediaScanner.scanDirectories方法开展扫描工作。
1. MediaScanner.java中scanDirectories函数分析:
void scanDirectories(String[] directories, String volumeName) {
// a: 初始化:初始化URi,扫描时需要把文件信息插入到媒体库中,媒体库对video,audio,image等等的文件都有对应的表,这些表的地址是由URi表示的,首先要做的就是完成这些表的初始化。
initialize(volumeName);
// b: 进入到扫描阶段,扫描时会有三个步骤,首先是预处理prescan(),然后是processDirecotory()扫描中扫尾工作postscan().
prescan():保存开始的已有的一些数据库文件信息记录,是扫描前数据库的初态,扫描的过程完成后,会扫描出新的信息,这样就可以能和原来的不一样,这是postscan().开始工作,完成新的数据库的更新。
以上分析的是java层中主要的3点内容。而processDirecotory()这个重点的处理函数是由native层完成的。
2.MediaScanner的native层上的processDirectory(),和native_init,native_setup函数分析。
static void
android_media_MediaScanner_native_init(JNIEnv *env)
{//取得java中mNativeContext的内容,在之后的操作时会把native对象指针放在这个这个mNativeContext中。
jclass clazz = env->FindClass(kClassMediaScanner);
fields.context = env->GetFieldID(clazz, "mNativeContext", "I");
}
在这个函数中得到的android_media_MediaScanner_native_setup会创建native层的MediaScanner,根据代码可知其实是创建的是StagefrightMediaScanner对象完成任务的
android_media_MediaScanner_native_setup(JNIEnv *env, jobject thiz)
{LOGV("native_setup");
MediaScanner *mp = new StagefrightMediaScanner;
if (mp == NULL) {
jniThrowException(env, kRunTimeException, "Out of memory");
return;
env->SetIntField(thiz, fields.context, (int)mp);
}
native_init和 native_setup是一起完成任务的。init获取到java中的设备上下文环境,setup创建native层的MediaScannert对象,同时以把这个对象指针保存在mcontext中,这样就可以native MediaScanner完成工作。在native层代码分析中创建出的对象new StagefrightMediaScanner再继续工作。