设为首页 加入收藏

TOP

Android media媒体库分析之:MediaProvider(一)
2015-04-07 15:30:18 来源: 作者: 【 】 浏览:79
Tags:Android media 媒体 分析 MediaProvider

一、获取MediaProvider:
该工程在系统源码的packages\providers目录下,提出并导入Eclipse,便于阅读;



图中可见都很多报错的,是滴,因为需要一些系统标准sdk之外的接口,不过不影响我们阅读代码。


二、工程结构及内部关系:
可以从上图看出包含4个文件:
MediaScannerService.Java:媒体服务,配合广播实现媒体扫描类的实例化,数据库的初始化等工作,也向外提供接口;
MediaScannerReceiver.Java:一个广播接收器,用于接受系统发给媒体服务的广播并启动媒体服务;
MediaProvider.Java:媒体数据库的封装类,代码量比较大(四千多行),功能比较复杂,但总的来说就是创建数据库,对外提供URI以实现对数据库的增删改查功能;
MediaThumbRequest.Java:媒体文件缩略图请求类,与MediaProvider配合使用;
上一个关系图更直观一些:



上图不是标准的类图,只是为了梳理逻辑关系画的结构图。
MediaProvider所处的位置及作用见图中红色框中的内容;
上图还包括其他内容:
1、App层:audio、image、video如何与媒体库进行交互;
2、框架层(android.media包下):如何实现媒体的扫描;
3、Native层:如何实现正在的媒体文件解析;
4、资源存储层:sd卡、U盘等介质,DTCM存储缩略图;


三、类详解


1、MediaScannerReceiver:


?public void onReceive(Context context, Intent intent) {
? String action = intent.getAction();
? Uri uri = intent.getData();
? // String externalStoragePath =
? // Environment.getExternalStorageDirectory().getPath();
? String externalSDStoragePath = Environment
? ? .getExternalSDStorageDirectory().getPath();
? String externalUDiskStoragePath = Environment
? ? .getExternalUDiskStorageDirectory().getPath();
? String externalExtSDStoragePath = Environment
? ? .getExternalExtSDStorageDirectory().getPath();


? if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
? ?// scan internal storage
? ?scan(context, MediaProvider.INTERNAL_VOLUME);
? } else {
? ?if (uri.getScheme().equals("file")) {
? ? // handle intents related to external storage
? ? String path = uri.getPath();
? ? if (action.equals(Intent.ACTION_MEDIA_MOUNTED)) {
? ? ?if (externalSDStoragePath.equals(path))
? ? ? scan(context, MediaProvider.EXTERNAL_VOLUME_SD);
? ? ?else if (externalUDiskStoragePath.equals(path))
? ? ? scan(context, MediaProvider.EXTERNAL_VOLUME_UDISK);
? ? ?else if (externalExtSDStoragePath.equals(path))
? ? ? scan(context, MediaProvider.EXTERNAL_VOLUME_EXTSD);
? ? ?else
? ? ? Slog.w(TAG, "unknown volume path " + path);
? ? } else if (action.equals(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE)
? ? ? && path != null
? ? ? && (path.startsWith(externalSDStoragePath + "/")
? ? ? ? || path.startsWith(externalExtSDStoragePath
? ? ? ? ? + "/") || path
? ? ? ? ?.startsWith(externalUDiskStoragePath + "/"))) {
? ? ?scanFile(context, path);
? ? }
? ?}
? }
?}


三类情况需要启动扫描服务:
a、系统启动完成;
b、媒体挂载(EXTERNAL_VOLUME_SD、EXTERNAL_VOLUME_UDISK、EXTERNAL_VOLUME_EXTSD);
c、媒体文件扫描广播(ACTION_MEDIA_SCANNER_SCAN_FILE);


scanFile和scan方法很简单,只是启动媒体服务即可:


?private void scan(Context context, String volume) {
? Bundle args = new Bundle();
? args.putString("volume", volume);
? context.startService(new Intent(context, MediaScannerService.class)
? ? .putExtras(args));
?}


?private void scanFile(Context context, String path) {
? Bundle args = new Bundle();
? Slog.i(TAG, "Start scanFile.");
? args.putString("filepath", path);
? context.startService(new Intent(context, MediaScannerService.class)
? ? .putExtras(args));
?}


2、MediaScannerService:
第一步:启动一个线程


?public void run() {
? // reduce priority below other background threads to avoid interfering
? // with other services at boot time.
? Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND
? ? + Process.THREAD_PRIORITY_LESS_FAVORABLE);
? Looper.prepare();


? mServiceLooper = Looper.myLooper();
? mServiceHandler = new ServiceHandler();


? Looper.loop();
?}


在线程中拿到当前的消息队列,使用handler处理消息;


第二部:启动ServiceHandler处理消息
ServiceHandler中还是处理两种,一种是扫描,第二种是具体媒体文件的解析

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇Android media媒体库分析之:分类.. 下一篇Android media媒体库分析之:调用..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: