android move to sdcard 和 app 大小 相关知识
理论部分
引题
android手机在某些机型和系统上,自带了move to sdcard功能,其实该功能是尽可能把数据存储放在外部存储上,减少app在内部存储所占用的内存。因为在手机里面,内部存储的大小是远远小于外部存储的大小的。内部存储价格也更昂贵一些。
内部存储和外部存储
提到这部分首先要说一些这两者的区别。
android 系统下的data
目录就是内部存储,需要权限才能打开这个文件夹,不过我们可以访问里面的数据。
外部存储是我们可以经常去操作的空间,一般是android系统下的/storage/
目录,在不同的机型上,也可能是/mnt/
目录。
其下面的/sdcard/
目录,是经常去操作的空间,有时系统会把sdcard/
目录单独拿出来,而在storage
下的/primary/
目录下提供了sdcard/
目录的引用链接。
安装app时发生的操作
首先在安装app后,会在data目录下(data目录下有两个文件夹名字分别为data和app),data 里存放/data/包名/cache
, /data/包名/files
, /data/包名/databases
, /data/包名/shared_prefs
, app目录下存放apk文件:/app/包名.apk
, 以上在安装时便会创建。称之为内部存储app占用部分;
move to sdcard时发生的操作
当去move to sdcard时,会在storage/sdcard/
下创建一个该以该app为包名的文件夹,里面存放相关内容,在该包名
目录下,其他的所有文件夹都和在内部存储的一样,然后,系统会移动内部存储目录下的内容到该目录下;(注意:有一些lib和缓存是不能移动过去的,同时还有一部分记录该app位置信息的内存仍在内部存储下。)
这是引起,在移动app后导致app的总大小变大的原因,是系统去做的一些文件处理。
实现逻辑部分
move to sdcard ,既然有移动,必然涉及到app的大小和app可移动的大小以及sdcard的大小问题。
获取app大小
获取app应用程序大小: 应用程序总大小 = cach(缓存) + code (应用程序包大小) + data(数据存储)。
需要涉及到部分AIDL
IPackageDataObserver.aidl
IPackageStatsObserver.aidl
PackageStats.aidl
因为app的大小数据存放在一个叫PackageStats
里面,需要利用aidl
,反射的机制去获取到。其中:
packageStats.codeSize; 程序大小
packageStats.cacheSize; 缓存大小
packageStats.dataSize; 数据大小
packageStats.packageName; 包名
获取app可移动大小
这部分网上的资料很少,因为显示出的数据大小与app的各项数据均不相同。最后没办法,只好反编译,去看一下具体是如何实现的。最终得到了一个答案,答案比较简单,计算了该app为包名的目录的大小,如下:
//获取applicationInfo
packageManager.getApplicatioinInfo("packageName", int);
//获取包的路径及文件的大小
new File (applicationInfo.sourceDir()).length();
但其实,仍然没有搞明白为什么这样获取的大小和上面app各项大小都不相同……
获取sdcard大小和剩余空间
首先判断是否支持sdcard移动
private boolean isSDCardMounted() {
if(”mounted”.equals(Environment.getExternalStoragestate())) {
return true;
}
return false;
}
...
//等等,其他条件
获取sdcard大小
private long getSDCardSize() {
if (isSDCardMounted()) {
StatFs fs = new StatFs(getSDCardBaseDir());
long count = fs.getBlockCountLong();
long size = fs.getBlockSizeLong();
return size * count;
}
return 0;
}
获取sdcard剩余大小
private long getSDCardAvailableSize() {
if (isSDCardMounted()) {
StatFs fs = new StatFs(getSDCardBaseDir());
long count = fs.getAvailableBlocksLong();
long size = fs.getBlockSizeLong();
return size * count;
}
return 0;
}
以上是对android move to sdcard 方面知识的总结,有错误地方和理解不深刻地方还请指出,谢谢
参考链接 android 中的内部存储与外部存储