原作者:Steve Gou 转载请注明!


下面是系统


MediaScannerReceiver会在任何的ACTION_BOOT_COMPLETED, ACTION_MEDIA_MOUNTEDACTION_MEDIA_SCANNER_SCAN_FILE意图(intent)发出的时候启动。因为解析媒体文件的元数据或许会需要很长时间,所以MediaScannerReceiver会启动MediaScannerService


MediaScannerService调用一个公用类MediaScanner去处理真正的工作。MediaScannerReceiver维持两种扫描目录:一种是内部卷(internal volume)指向$(ANDROID_ROOT)/media.另一种是外部卷(external volume)指向$(EXTERNAL_STORAGE).

扫描和解析工作位于JAVA层和C++层。JAVA层是启动器。MediaScanner扫描所有目录,如下步骤:


1.JAVA层初始化


在这一步骤中,它会根据目录是在内部卷还是外部卷打开不同的数据库


2.Java层预扫描


首先清除文件和播放列表的缓存条目。然后根据MediaProvider返回的请求结果生成新文件和播放列表缓存条目。


3.C++层处理目录


列举出所有文件和特定的所有子目录(如果子目录包含一个.nomedia隐藏文件,则不会被列举出来。)。被列举的文件是根据文件扩展来判断文件是否被支持。如果支持这种文件扩展,C++层就会回调到JAVA层扫描文件。这种扩展就会被扫描到MediaFile.java中列出。下面是支持的文件扩展列表。


/* Audio */
addFileType("MP3", FILE_TYPE_MP3, "audio/mpeg");
addFileType("M4A", FILE_TYPE_M4A, "audio/mp4");
addFileType("WAV", FILE_TYPE_WAV, "audio/x-wav");
addFileType("AMR", FILE_TYPE_AMR, "audio/amr");
addFileType("AWB", FILE_TYPE_AWB, "audio/amr-wb");
addFileType("WMA", FILE_TYPE_WMA, "audio/x-ms-wma");
addFileType("OGG", FILE_TYPE_OGG, "application/ogg");
addFileType("MID", FILE_TYPE_MID, "audio/midi");
addFileType("XMF", FILE_TYPE_MID, "audio/midi");
addFileType("RTTTL", FILE_TYPE_MID, "audio/midi");
addFileType("SMF", FILE_TYPE_SMF, "audio/sp-midi");
addFileType("IMY", FILE_TYPE_IMY, "audio/imelody");

/* Video */
addFileType("MP4", FILE_TYPE_MP4, "video/mp4");
addFileType("M4V", FILE_TYPE_M4V, "video/mp4");
addFileType("3GP", FILE_TYPE_3GPP, "video/3gpp");
addFileType("3GPP", FILE_TYPE_3GPP, "video/3gpp");
addFileType("3G2", FILE_TYPE_3GPP2, "video/3gpp2");
addFileType("3GPP2", FILE_TYPE_3GPP2, "video/3gpp2");
addFileType("WMV", FILE_TYPE_WMV, "video/x-ms-wmv");

/* Image */
addFileType("JPG", FILE_TYPE_JPEG, "image/jpeg");
addFileType("JPEG", FILE_TYPE_JPEG, "image/jpeg");
addFileType("GIF", FILE_TYPE_GIF, "image/gif");
addFileType("PNG", FILE_TYPE_PNG, "image/png");
addFileType("BMP", FILE_TYPE_BMP, "image/x-ms-bmp");
addFileType("WBMP", FILE_TYPE_WBMP, "image/vnd.wap.wbmp");

/* Audio Play List */
addFileType("M3U", FILE_TYPE_M3U, "audio/x-mpegurl");
addFileType("PLS", FILE_TYPE_PLS, "audio/x-scpls");
addFileType("WPL", FILE_TYPE_WPL, "application/vnd.ms-wpl");


4.Java层扫描文件

aJava层开始文件

首先它忽略一些MacOSWindows Media Player特殊的文件。然后它会查看被扫描的文件是否已经存在于缓存条目中,如果存在,它会检查文件上次修改的时间是否改变。最后它返回该文件是否需要进一步处理的结果。如果不需要,接下来的两步不会执行。

b)C++层扫描文件

不是所有的文件都需要交给C++层解析成元数据。只有下面的文件类型会被解析,注意,这里不处理image文件。



  1. if (mFileType == MediaFile.FILE_TYPE_MP3 ||
  2. mFileType == MediaFile.FILE_TYPE_MP4 ||
  3. mFileType == MediaFile.FILE_TYPE_M4A ||
  4. mFileType == MediaFile.FILE_TYPE_3GPP ||
  5. mFileType == MediaFile.FILE_TYPE_3GPP2 ||
  6. mFileType == MediaFile.FILE_TYPE_OGG ||
  7. mFileType == MediaFile.FILE_TYPE_MID ||
  8. mFileType == MediaFile.FILE_TYPE_WMA) {
  9. ……

对于被解析的元数据信息,C++层会回调到JAVA层的handleStringTagJava层会记录它的name/value信息。

c)Java层结束文件

最后根据上一步解析出的值,Java层会更新相应的MeidaProvider产生的数据库表。

5.Java层发送扫描

到目前为止,所有文件已经被扫描,它最后会检查文件和播放列表缓存条目,看是否所有项仍然存在于文件系统。如果有空条目,则会从数据库中删除。这样它能够保持数据库和文件系统的一致性。

其他的应用程序通过接收MediaScannerService发出的ACTION_MEDIA_SCANNER_STARTEDACTION_MEDIA_SCANNER_FINISHED意图能够知道什么时候扫描操作开始和结束。




原文地址http://letsgoustc.spaces.live.com/blog/cns!89AD27DFB5E249BA!473.entry?_c=BlogPart

更多相关文章

  1. You must call removeView() on the child's parent first
  2. android ndk (3)
  3. android背景选择器selector用法汇总
  4. Android(安卓)源码下载
  5. ADK的安装
  6. Android布局文件属性
  7. Mac系统下Android(安卓)SDK更新以及ADT无法在线下载
  8. linux ,Android基础知识总结
  9. NPM 和webpack 的基础使用

随机推荐

  1. Android从零开搞系列:自定义View(15)仿天天
  2. 【Android】策略模式封装百度地图路线规
  3. JustWe-WebServer Android上的Http服务器
  4. DialogFragment自定义dialog的位置和大小
  5. Android进阶系列4—从LayoutInflater到se
  6. Unity Android使用相机拍摄照片并在其上
  7. Android开发如何验证输入的手机号码是否
  8. opencv实时视频帧在android中没有显示sob
  9. 通过数据库接口获取到的中文数据是问号怎
  10. 尽管在清单文件中指定了权限,但是ACCESS_F