android move to sdcard 和 app 大小 相关知识

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 中的内部存储与外部存储

你可能感兴趣的:(android move to sdcard 和 app 大小 相关知识)