MediaScanner扫描文件和文件目录

 MediaScanner主要功能:把上层修改写入到数据库。在android中使用轻量级数据库sqlite来存储数据,使用sql语句可查看数据库中的内容。

1. 扫描文件
在对文件进行重命名、删除等操作后需要 sendBroadcast通知MediaScanner去扫描文件,其中广播发送的Intent携带的action为:ACTION_MEDIA_SCANNER_SCAN_FILE。
MediaScannerReceiver.java中的onReceive中,若收到该action,则调用私有函数scanFile。
私有函数scanFile所做的事情就是startService,来启动一个service:MediaScannerService.java。通过startService开启的服务,一旦服务开启,则跟调用者之间没有任何关系。调用者不可以访问 该service里面的方法,如果调用者被系统回收了或者调用了onDestroy方法, 该service仍然继续存在。 即非绑定的service。
调用startService开启 MediaScannerService,根据非绑定的service的生命周期,接下来依次调用onCreate、onStartCommand。
在onStartCommand中通过ServiceHandler来sendMessage。android的消息队列使用sendMessage和handleMessage的组合来发送和处理消息。
在handleMessage中处理消息。当消息中携带的文件路径不为空时,则调用MediaScannerService类的私有函数scanFile扫描文件,入参分别为文件路径和文件的mimeType。
MediaScannerService.java中的私有函数scanFile调用MediaScanner的公共接口scanSingleFile。到这里可以看到 ACTION_MEDIA_SCANNER_SCAN_FILE的作用只是扫描单个文件。
scanSingleFile中没有做实质性的扫描动作,而是调用了接口doScanFile。
在doScanFile中才真正的对媒体进行了扫描,并且通过endFile最终将媒体的修改写入数据库。

2. 扫描文件目录
       当应用程序对文件夹进行新建、重命名或者删除等操作时,如何通知MediaScanner进行扫描呢?相信大家的第一反应是像扫描单个文件一样,通过发送广播给MediaScannerReceiver来进行处理。
       可以看到MediaScannerReceiver的onReceive中有对ACTION_MEDIA_MOUNTED的处理,即可以重新扫描整个SD卡。试着发送一个action为ACTION_MEDIA_MOUNTED的广播通知执行扫描。但是抛出异常:
W/ActivityManager( 498): Permission Denial: not allowed to send broadcast android.intent.action.MEDIA_MOUNTED from pid=2269, uid=20016
这是因为在Android-4.4以后的版本中限制了系统应用才有权限使用广播通知系统扫描SD卡。

解决方案:调用MediaScanner.java中的公共接口scanDirectories,入参分别为文件夹上级绝对路径和”external”。external表示外部设备。对外部设备该目录下的内容进行扫描。

你可能感兴趣的:(mediascanner)