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的工作。
';