转:初步理解android的MediaScanner(1)

转自:http://blog.csdn.net/hellofeiya/article/details/8255898

 

MediaScanner完成Android中的多媒体文件的扫描工作。例如,mediascanner扫描系统内存和SD卡文件之后,会将扫描的结果加载在数据库中,在Music这个应用程序中看到的显示在activity 的list列表上歌曲专辑名,流派,歌曲时长等信息,都是扫描后的结果放在数据库中,最后读到的数据库中的信息。

    这里可以明白的一点是:多媒体数据库中的信息是由MediaScanner添加的。

    MediaScanner这项功能使用到的三种android的基本组件:

    (1)MediaScannerService(从Service中派生),完成扫描任务,并将扫描结果放入到媒体数据库中。

    (2)MediaProvider(ContentProvider派生),针对媒体库进行相关操作请求,一般情况就是写,删,查,更操作。

    (3)MediaScannerReceiver接收外界的扫描请求,这里可以看出它MediaScanner的对外接口。

          (这里也是提个醒,不是按照MediaRecorder和MediaPlayer的接口那样的使用方式)

     MediaScanner扫描工作的流程总结:

     首先,外界应该有扫描请求,所有MediaScannerReceiver首先会接收这些请求,得到请求之后需要完成工作扫描工作,这个是由MediaScannerService完成的,所以MediaScannerReceiver利用startService来启动MediaScannerService。在MediaScannerService的工作中,主线和工作线程是分开的,主线程接收请求,工作线程完成

扫描任务。

    其次,工作线程正式开始工作,创建扫描器MediaScanner来处理请求中的扫描目标。扫描前会向系统发送广播,扫描工作完成后,做一点儿后期处理也会向系统发送扫描完毕广播。

  总结的说,调用关系是  MediaScannerReceiver(对外的接口) ---> MediaScanner(扫描执行,这里要知道的是MediaScanner扫描器是在MediaScannerService中创建出来的)MediaScanner和MediaScannerService是宿主关系。

   开始工作: 根据这个扫描过程看看这里的重点类跟函数:

1.   分析MediaScannerReceive.Java:

    public class MediaScannerReceiver extends BroadcastReceiver{  };

这里继承了一个广播类BroadcastReceiver,就是说MediaScannerReceiver是用来接收广播的。

MediaScannerReceiver接收的有效广播有三种,而且对这三种广播的处理都是在OnCreate()函数中完成。

广播一:BOOT_COMPLETED  此时处理的是系统内存上信息的扫描工作。路径:/system/media,这部分的内容主要是系统自带的铃声等文件,这个内存比较小。

广播二:MEDIA_MOUNTED  扫描SD卡,当然是包括内置和外置的SD卡,外部存储挂载路径必须为:/mnt/sdcard.

广播三:MEDIA_SCANNER_SCAN_FILE   处理的是sd卡上的文件,也就是说在路径:/system/media上面。

    对广播的处理其实就是接下来启动startService让MediaScannerService工作完成扫描任务的过程。

   代码:

    public void onReceive(Context context, Intent intent) {

     //  从intent中得到对应ACTION的广播动作对应的路径资源URI

    //  scan()函数工作。首先字符串匹配之后就使用scan(),在scan()中真正工作的是startService(),startService()作用是启动MediaScannerService,MediaScannerReceive的工作就告一段落了,接下来就看MediaScannerService如何使用工作线程完成扫描工作了。

2. MediaScannerService.java

   class MediaScannerService extends Service implements Runnable,实现这个Runnable接口,这就是说至此会创建工作线程。

    Service的函数执行顺序是:首先OnCreate(),然后OnStartCommand(),就是每次MediaScannerReceiver执行scan()即startService(),就会激发一次OnStartCommand()。

    (1)OnCreate(){

    //  实现一个工作线程的创建,这个线程是使用消息处理机制,有一个run()函数的工作。

    Thread thr = new Thread(null, this, "MediaScannerService")

};

    (2)OnStartCommand()函数

    int onStartCommand(Intent intent, int flags, int startId)

{

// i. 从  Intent intent中获取请求处理的消息

// ii. 接收的消息交给Handler工作线程,然后被工作线程处理。

  mServiceHandler.sendMessage(msg);

}

onStartCommand()完成的是消息传递。

(3)ServiceHandler的handleMessage()处理请求。

private final class ServiceHandler extends Handler{

//   scan完成工作

   void scan(String[] directories, String volumeName);

   stopSelf(msg.arg1);

}

MediaScannerService中的scan()函数中创建MediaScanner扫描器,MediaScanner scanner = createMediaScanner();再一层剖析createMediaScanner()函数:

private MediaScanner createMediaScanner() {

MediaScanner scanner = new MediaScanner(this); //创建MediaScanner对象

Locale locale = getResources().getConfiguration().locale; // 得到系统的相关信息,支持的国家和支持的语言

 scanner.setLocale(language + "_" + country);//为扫描器设置当前系统使用的国家和语言

 }

 

至此,工作流程的分析完成,下一层主要是分析重点MediaScanner如何工作。

   

posted on 2017-03-27 22:34  信假名如  阅读(259)  评论(0编辑  收藏  举报

导航