MediaScannerService研究- https://blog.csdn.net/codefly/article/details/53177926
Android调用MediaScanner进行扫描- https://bashenmail.iteye.com/blog/603680
SD卡,MediaScannerService收到media_mount的action;手机存储卡,MediaScannerService收到boot_completed的action.
MediaScannerService是Android平台提供的一个用于扫描手机中多媒体文件的应用级service。它并不是系统服务。MediaScannerService和MediaProvider有着非常紧密的关系,因为扫描出的结果总需要存储到某个地方来展现给用户。
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND +
Process.THREAD_PRIORITY_LESS_FAVORABLE);
Looper.prepare();
mServiceLooper = Looper.myLooper(); // 消息looper
mServiceHandler = new ServiceHandler(); // 发送消息的handler
Looper.loop();
}
-- MediaScanner和媒体文件扫描有关,例如,在Music应用程序中见到的歌曲专辑名、歌曲时长等信息,都是通过它扫描对应的歌曲而得到的。另外,通过MediaStore接口查询媒体数据库,从而得到系统中所有媒体文件的相关信息也和MediaScanner有关,因为数据库的内容就是由MediaScanner添加的。
MediaScannerService调用一个公用类MediaScanner去处理真正的工作。MediaScannerReceiver维持两种扫描目录:一种是内部卷(internal volume)指向$(ANDROID_ROOT)/media. 另一种是外部卷(external volume)指向$(EXTERNAL_STORAGE).
当系统刚刚启动时,收到ACTION_BOOT_COMPLETED广播,此时会把内部卷标(“internal”)和外部卷标(“external”)都扫描一下;
如果收到ACTION_MEDIA_MOUNTED广播,则只扫描外部卷标;
如果收到的是ACTION_MEDIA_SCANNER_SCAN_FILE广播,则扫描具体的文件路径。
-- MediaScannerService三个组件:
1.MediaScannerService(从Service派生)模块负责扫描媒体文件,然后将扫描得到的信息插入到媒体数据库中。
2.MediaProvider(从ContentProvider派生)模块负责处理针对这些媒体文件的数据库操作请求,例如查询、删除、更新等。
3.MediaScannerReceiver(从BroadcastReceiver派生)模块负责接收外界发来的扫描请求。也就是MS对外提供的接口。
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
final Uri uri = intent.getData();
if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
// Scan both internal and external storage
scan(context, MediaProvider.INTERNAL_VOLUME); // INTERNAL_VOLUME = "internal"
scan(context, MediaProvider.EXTERNAL_VOLUME); // EXTERNAL_VOLUME = "external"
} else {
if (uri.getScheme().equals("file")) {
// handle intents related to external storage
. . . . . .
Log.d(TAG, "action: " + action + " path: " + path);
if (Intent.ACTION_MEDIA_MOUNTED.equals(action)) {
// scan whenever any volume is mounted
scan(context, MediaProvider.EXTERNAL_VOLUME);
} else if (Intent.ACTION_MEDIA_SCANNER_SCAN_FILE.equals(action) &&
path != null && path.startsWith(externalStoragePath + "/")) {
scanFile(context, path);
}
}
}
}
static const char *kValidExtensions[] = {
".mp3", ".mp4", ".m4a", ".3gp", ".3gpp", ".3g2", ".3gpp2",
".mpeg", ".ogg", ".mid", ".smf", ".imy", ".wma", ".aac",
".wav", ".amr", ".midi", ".xmf", ".rtttl", ".rtx", ".ota",
".mkv", ".mka", ".webm", ".ts", ".fl", ".flac", ".mxmf",
".avi", ".mpeg", ".mpg", ".awb", ".mpga"
};
-- 使用MediaScannerConnection执行具体文件或文件夹进行扫描,核心代码如下:
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
Intent mediaScanIntent = new Intent(
Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
Uri contentUri = Uri.fromFile(Environment.getExternalStorageDirectory()); //指定SD卡路径
mediaScanIntent.setData(contentUri);
sendBroadcast(mediaScanIntent);
} else {
sendBroadcast(new Intent(
Intent.ACTION_MEDIA_MOUNTED,
Uri.parse("file://"
+ Environment.getExternalStorageDirectory())));
}
} catch(Exception e) {
e.getMessage();
}
}