设为首页 加入收藏

TOP

Android media媒体库分析之:分类别统计媒体文件大小(一)
2015-04-07 15:30:18 来源: 作者: 【 】 浏览:101
Tags:Android media 媒体 分析 类别 统计 媒体文件 大小

对系统媒体库不了解的线看这儿:


先看一下要实现的效果:



上图是系统设置中分类别对文件所占空间的统计,项目中要统计媒体文件所占空间,于是研究了一下系统的做法,收获如下:


1、从源码packages/app/下找到settings工程,找到存储功能的实现,相关类有:


com.android.settings.deviceinfo.StorageMeasurement
com.android.settings.deviceinfo.StorageVolumePreferenceCategory
其他相关源码:
com.android.defcontainer.DefaultContainerService


StorageMeasurement类中启动服务,绑定服务,通知界面更新;
StorageVolumePreferenceCategory显示界面
StorageMeasurement中建立了与DefaultContainerService服务的通信,指定要扫描的目录:


? ? /** Media types to measure on external storage. */
? ? private static final Set sMeasureMediaTypes = Sets.newHashSet(
? ? ? ? ? ? Environment.DIRECTORY_DCIM, Environment.DIRECTORY_MOVIES,
? ? ? ? ? ? Environment.DIRECTORY_PICTURES, Environment.DIRECTORY_MUSIC,
? ? ? ? ? ? Environment.DIRECTORY_ALARMS, Environment.DIRECTORY_NOTIFICATIONS,
? ? ? ? ? ? Environment.DIRECTORY_RINGTONES, Environment.DIRECTORY_PODCASTS,
? ? ? ? ? ? Environment.DIRECTORY_DOWNLOADS, Environment.DIRECTORY_ANDROID);


上面这个set就是定义了我们系统里面常用的目录:


public static String DIRECTORY_DOWNLOADS = "Download";
public static String DIRECTORY_DCIM = "DCIM";
public static String DIRECTORY_MUSIC = "Music";
public static String DIRECTORY_PICTURES = "Pictures";
public static String DIRECTORY_MOVIES = "Movies";
...


获取每个目录的大小:


? ? ? ? ? ? ? ? for (String type : sMeasureMediaTypes) {
? ? ? ? ? ? ? ? ? ? final File path = currentEnv.getExternalStoragePublicDirectory(type);
? ? ? ? ? ? ? ? ? ? final long size = getDirectorySize(imcs, path);
? ? ? ? ? ? ? ? ? ? details.mediaSize.put(type, size);
? ? ? ? ? ? ? ? }


其中getDirectorySize方法通过IMediaContainerService调用了DefaultContainerService服务中的方法,在DefaultContainerService中获取到所有信息之后回调IMediaContainerService,再更新界面;


也就是说:系统只统计了上述几个目录的大小(sMeasureMediaTypes中定义的),如果你的歌曲是拷贝到其他目录,那系统存储里面是不会统计使用量。看来Android也不是很智能嘛!!!难度是考虑效率???


2、如何获取某个目录的大小?
先看一下系统是怎么做的:
下面方法是在DefaultContainerService中定义的,获取某一目录大小,获取某一文件大小;


? ? ? ? @Override
? ? ? ? public long calculateDirectorySize(String path) throws RemoteException {
? ? ? ? ? ? Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);


? ? ? ? ? ? final File directory = new File(path);
? ? ? ? ? ? if (directory.exists() && directory.isDirectory()) {
? ? ? ? ? ? ? ? return MeasurementUtils.measureDirectory(path);
? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? return 0L;
? ? ? ? ? ? }
? ? ? ? }


? ? ? ? @Override
? ? ? ? public long[] getFileSystemStats(String path) {
? ? ? ? ? ? Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);


? ? ? ? ? ? try {
? ? ? ? ? ? ? ? final StructStatFs stat = Libcore.os.statfs(path);
? ? ? ? ? ? ? ? final long totalSize = stat.f_blocks * stat.f_bsize;
? ? ? ? ? ? ? ? final long availSize = stat.f_bavail * stat.f_bsize;
? ? ? ? ? ? ? ? return new long[] { totalSize, availSize };
? ? ? ? ? ? } catch (ErrnoException e) {
? ? ? ? ? ? ? ? throw new IllegalStateException(e);
? ? ? ? ? ? }
? ? ? ? }


但是
MeasurementUtils.measureDirectory(path)和Libcore.os.statfs(path)
两个方法我们都调不到,怎么办?
我们把MeasurementUtils类从源码中拷贝出来到我们的功能,但注意要保留包路径,否则可以编译通过,但无法运行,因为他里面用到了一个本地方法,需要加载一个so文件。如下:



?
这样就可以解决第一个问题了;


再来看第二方法,其实这个方法我们用不到,我们已经通过第一个方法获取到指定文件夹的大小了,那关于某一个文件的大小我们之间通过file可以拿到。
第二个方法有一个封装类:starfs,可以获取rom、sdcard的总大小和可用空间,如下:


? ? /**
? ? * The size, in bytes, of a block on the file system. This corresponds to
? ? * the Unix {@code statfs.f_bsize} field.
? ? */
? ? public int getBlockSize() {
? ? ? ? return (int) mStat.f_bsize;
? ? }


? ? /**
? ? * The total number of blocks on the file system. This corresponds to the
? ? * Unix {@code statfs.f_blocks}

首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇Android中单击空白区域隐藏键盘 下一篇Android media媒体库分析之:Medi..

评论

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