10.2.1 MSR模块分析
最后更新于:2022-04-02 05:54:03
MSR模块的核心类MediaScannerReceiver从BroadcastReceiver派生,它是专门用来接收广播的,那么它感兴趣的广播有哪几种呢?其代码如下所示:
**MediaScannerReceiver.java**
~~~
public class MediaScannerReceiver extendsBroadcastReceiver
{
private final static String TAG ="MediaScannerReceiver";
@Override //MSR在onReceive函数中处理广播
publicvoid onReceive(Context context, Intent intent) {
String action = intent.getAction();
Uri uri = intent.getData();
//一般手机外部存储的路径是/mnt/sdcard
String externalStoragePath =
Environment.getExternalStorageDirectory().getPath();
//为了简化书写,所有Intent的ACTION_XXX_YYY字串都会简写为XXX_YYY。
if(action.equals(Intent.ACTION_BOOT_COMPLETED)) {
//如果收到BOOT_COMPLETED广播,则启动内部存储区的扫描工作,内部存储区
//实际上扫描的是/system/media目录,这里存储了系统自带的铃声等媒体文件。
scan(context, MediaProvider.INTERNAL_VOLUME);
}else {
if (uri.getScheme().equals("file")) {
String path = uri.getPath();
/*
注意下面这个判断,如果收到MEDIA_MOUNTED消息,并且外部存储挂载的路径
和“/mnt/sdcard“一样,则启动外部存储也就是SD卡的扫描工作
*/
if (action.equals(Intent.ACTION_MEDIA_MOUNTED) &&
externalStoragePath.equals(path)) {
scan(context,MediaProvider.EXTERNAL_VOLUME);
} else if(action.equals(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE)
&& path != null
&& path.startsWith(externalStoragePath +"/")) {
/*
外部应用可以发送MEDIA_SCANNER_SCAN_FILE广播让MSR启动单个文件
的扫描工作。注意这个文件必须位于SD卡上。
*/
scanFile(context, path);
}
}
}
}
~~~
从上面代码中发现MSR接收的三种请求,也就是说,它对外提供三个接口函数:
- 接收BOOT_COMPLETED请求,这样MSR会启动内部存储区的扫描工作,注意这个内部存储区实际上是/system/media这个目录。
- 接收MEDIA_MOUNTED请求,并且该请求携带的外部存储挂载点路径必须是/mnt/sdcard,通过这种方式MSR会启动外部存储区也就是SD卡的扫描工作,扫描目标是文件夹/mnt/sdcard。
- 接收MEDIA_SCANNER_SCAN_FILE请求,并且该请求必须是SD卡上的一个文件,即文件路径须以/mnt/sdcard开头,这样,MSR会启动针对这个文件的扫描工作。
读者是否注意到,MSR和跨Binder调用的接口(在本章拓展内容中将介绍)都不支持对目录的扫描(除了SD卡的根目录外)。实现这个功能并不复杂,有兴趣的读者可自行完成该功能,如果方便,请将自己实现的代码与大家共享。
大部分的媒体文件都已放在SD卡上了,那么来看收到MEDIA_MOUNTED请求后MSR的工作。还记得第9章中对Vold的分析吗?这个MEDIA_MOUNTED广播就是由MountService发送的,一旦有SD卡被挂载,MSR就会被这个广播唤醒,接着SD卡的媒体文件就会被扫描了。真是一气呵成!
SD卡根目录扫描时调用的函数scan的代码如下:
**MediaScannerReceiver.java**
~~~
private void scan(Context context, Stringvolume) {
//volume的值为/mnt/sdcard
Bundleargs = new Bundle();
args.putString("volume", volume);
//启动MSS。
context.startService(
new Intent(context, MediaScannerService.class).putExtras(args));
}
~~~
scan将启动MSS服务。下面来看MSS的工作。
';