Android开发Android开发经验谈Android技术知识

好好管理你应用的文件夹,别再乱用了

2019-07-25  本文已影响22人  881ef7b85f62

安卓碎片化的问题,由来已久,这次来看一下文件储存碎片化的问题。到底要怎么去正确选择和管理文件存储呢?

为什么要管理文件?

Android手机一直以来被人诟病越用越卡,越用存储空间越少,经常有要靠各种清理app清理垃圾,到最后不得对手机进行双清,原因除了硬件老化和Android的底层实现问题之外,开发者对文件管理的忽视制造出大量无法清理的“垃圾”也是造成手机卡慢的原因之一。

Android的开放性给了开发者巨大的自由度,但自由不是让我们滥用权限和随意开发的借口,每一个开发者都应该注重细节,连曾经一片混乱的第三方推送都开始统一整合规范化了,如果你还在随意开发,不如现在开始,注重细节,提高用户的Android手机体验?

Android闪存

总所周知,Android手机存储分为两个部分:内部存储外部存储,内部存储一般是手机自带的存储空间,外部存储指外插SD卡提供的存储空间;随着手机发展,这两个存储的定义又有了一些些变化,新的手机不再有外插SD卡的概念,采取了内置闪存(eMMC、UFS等)的方式,所以内部存储和外部存储在新的Android手机上已经在同一个硬件上了。但为了兼容旧设备和让用户得到更好的体验,我们仍然需要管理好手机上内外存储的使用。

关于文件存储位置的api

做过文件相关管理的同学应该都曾经被android众多的文件api搞得一片混乱过,现在来理一理.

我把应用操作的文件存储位置分为三个部分

  1. 应用内部存储私有文件目录
  2. 应用外部存储私有文件目录
  3. 公有目录

我们有两种api去获取这三个部分的存储位置,它们分别归属于Context和Environment。

Context

Context是应用的上下文,它用来获取与应用相关的文件目录,可以获取应用私有和应用公有目录,常用的api有(后面是所对应的路径):

1\. Context#getCacheDir()                    /data/user/0/cn.appname.xxx/cache
2\. Context#getDir("spanner",MODE_PRIVATE)   /data/user/0/cn.appname.xxx/app_spanner
3\. Context#getFileDir()                     /data/user/0/cn.appname.xxx/files
3\. Context#getExternalCacheDir()            /storage/emulated/0/Android/data/cn.appname.xxx/cache
4\. Context#getExternalFilesDir(Environment.DIRECTORY_PICTURES)  /storage/emulated/0/Android/data/cn.appname.xxx/files/Pictures
   Context#getExternalFilesDir(null)        /storage/emulated/0/Android/data/cn.appname.xxx/files
5\. Context#getExternalMediaDirs()           /storage/emulated/0/Android/media/cn.appname.xxx

前两个是应用内部存储私有目录,后面4个都是应用外部存储私有文件目录。 注意:/data/user/0/ 等同于 /data/data/

Environment

Environment和应用无关,它用于获取公有存储位置的文件目录,常用的api有:

1\. Environment#getExternalStorageDirectory()                /storage/emulated/0
2\. Environment#getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)        /storage/emulated/0/DCIM
   Environment#getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)    /storage/emulated/0/Pictures
3\. Environment#getDataDirectory()                           /data
4\. Environment#getDownloadCacheDirectory()                  /data/cache
5\. Environment#getRootDirectory()                           /system

API的选用

到底什么时候要用什么api呢?

应用私有文件目录

应用私有目录由Context获取控制,分为内部存储外部存储,内部存储不需要申请文件读写权限也能够使用,外部存储需要权限(getetExternalCacheDir() 和 getExternalFilesDir() 这两个方法从4.4之后不再需要读写权限)。用户对app进行数据清理或卸载可以清理外部存储和内部存储下的所有文件目录。

内部存储

内部存储的文件夹其他应用和用户无法直接访问,可以用于存放敏感数据。

外部存储

在Android Q之前其他应用是可以访问修改外部存储的应用私有目录的,这个要注意。

使用外部存储之前一定要检查外部存储是否可用,因为旧设备不一定会有外部存储,新手机也不一定会给你读写权限,就算用户不给你权限,你的app也要运行啊,不然就不用你的了。

    public static boolean isSDCardEnable() {
        return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState());
    }

公有目录

获取公有目录要使用Environment的Api,它返回的目录全都是共享的公有目录。造成Android手机文件存储混乱的罪魁祸首!为数众多的无责任开发者在这里胡乱创建文件夹,乱起名、乱放文件,普通用户根本无法判断哪些文件夹、文件是有用的,卸载app之后留下庞大的无法清理的垃圾文件,导致手机空间不足。于是它们在Android Q被废弃了,但是Q之前还是能好好使用的,我认为要开始减少使用它们,更多地使用Context下的私有目录API。

适配Android Q

上面提到Environment的两个公有目录常用API在Android Q被废弃了,应用存储功能沙箱化,文件存放到沙箱外面要使用 DocumentFile,共享媒体文件要使用MediaStore进行。

结尾

最后说一下几个重要的事:

这次的分享到这里,希望看完这篇文章之后能够让你更了解如何管理手机文件夹。

学习分享,共勉

题外话,我从事Android开发已经五年了,此前我指导过不少同行。但很少跟大家一起探讨,正好最近我花了一个多月的时间整理出来一份包括不限于高级UI、性能优化、移动架构师、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter等全方面的Android进阶实践技术,今天暂且开放给有需要的人,若有关于此方面可以关注+点赞后领取,或者评论与我一起交流探讨。

加群:腾讯@Android高级架构(818520403)
免费获取往期Android高级架构资料、源码、笔记、视频。高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter全方面的Android进阶实践技术,群内还有技术大牛一起讨论交流解决问题。

上一篇 下一篇

猜你喜欢

热点阅读