iOS系统中,系统会为每个应用分配一个独立的空间,用来存放应用产生的数据,并且每个应用只能访问自己的存储空间。由于Android手机可以插拔内存卡,所以,相对于iOS来说,存储方式更多一点。

内部存储空间的应用私有目录


Android系统中,当你安装了某个应用后,系统会为此应用分配一块私有存储空间,如果手机未Root,用户是看不到这个空间下的内容的,但是开发人员通过DDMS可以查看此空间,文件目录为:data/data/应用包名,如图:



这个文件夹用于App中的WebView缓存页面信息,SharedPreferencesSQLiteDatabase持久化应用相关数据等。当然,我们可以通过ContextWrapper提供的方法来获取相应的目录:

  • getFilesDir() 获取名为files的文件夹目录
  • getCacheDir() 获取名为cache的文件目录

当使用数据库,Webview,和SharedPreferences的时候,系统会自动创建databasesapp_webviewshared_prefs等文件夹,当然也可以自己创建相关的文件夹。

注意:当用户卸载APP时,系统会自动删除data/data/目录下对应包名的文件夹及其内容

外部存储空间中的应用私有目录


考虑到内部存储空间容量有限,Android在外部存储空间中也提供有特殊目录供应用存放私有文件,文件路径为:

/storage/emulated/0/Android/data/app package name

与内部存储空间的应用私有目录不同的是:

第一,默认情况下,系统并不会自动创建外部存储空间的应用私有目录,只有在应用需要的时候,开发人员通过SDK提供的API创建该目录文件夹和操作文件夹内容。

第二,自Android7.0开始,系统对应用私有目录的访问权限进一步限制。其他App无法通过file://这种形式的Uri直接读写该目录下的文件内容,而是通过FileProvider访问。

我们可以通过ContextWrapper提供的方法来获取相应的目录:

  • getExternalCacheDir()
  • getExternalCacheDir()

等等,当然,也可以通过Environment间接操作,但是需要向用户申请权限。

Environment.getExternalStorageState();

类似于 File 和 Cache 默认分类目录,开发人员也可以在应用私有目录中创建属于自己的自定义目录,方便于分类存储应用相关文件。

值得注意的一点是,对于外部存储空间下的应用私有目录文件,由于普通用户可以自由修改和删除,开发人员在使用时,一定要做好判空处理和异常捕获,防止应用崩溃退出!

外部存储空间中的公共目录


通常来说,应用涉及到的持久化数据分为两类:应用相关数据和应用无关数据。前者是指专供宿主 App 使用的数据信息,比如一些应用的配置信息,数据库信息,缓存文件等。当应用被卸载,这些信息也应该被随之删除,避免存储空间产生不必要的占用。

相对而言,后者更偏向于这类信息:当应用被卸载,用户仍然希望保留于设备当中的信息。常见如,拍照类应用的图片文件,用户是使用浏览器手动下载的文件等。

显然,无论是内部存储空间,还是外部储存空间,上述两个应用私有目录由于其特有的生命周期(随着应用卸载而自动清除)只适合存储应用相关数据。

或者从访问权限上来说,应用无关数据应该是宿主应用希望与其他应用共享这些数据的,应该存放在外部存储空间的公共目录文件夹下。

外部存储空间已经为用户默认分类出一些公共目录。开发人员可以通过 Environment 类提供的方法直接获取相应目录的绝对路径,传递不同的 type 参数类型即可:

Environment.getExternalStoragePublicDirectory(String type);

Envinonment 类提供诸多 type 参数的常量,比如:

  • DIRECTORY_MUSIC:Music
  • DIRECTORY_MOVIES:Movies
  • DIRECTORY_PICTURES:Pictures
  • DIRECTORY_DOWNLOADS:Download

等等,以第一个常量为例,音乐类别的公共目录绝对路径为:/storage/emulated/0/Music。如果你使用文件管理器打开设备的外部存储空间的话,均可以看到这些公共目录文件夹。

面对如此诸多的默认类别,开发人员在保存自己应用的公共文件时,也要养成良好的习惯,将要保存的数据分门别类地保存在不同公共目录下。当然,你也可以在公共目录下再次创建属于自己应用的目录,便于管理。

注意:访问外部存储空间时记得申请读写权限!

外部存储空间中的其他目录


一般来说,利用两种应用私有目录和公共目录便能够存储应用中需要保存的数据和文件。如果这些还不够的话,那一定是你的开发姿势不对。在 Code Review 的前提下,如果还是不够的话,还可以在外部存储空间自由创建其他目录,通过这个方式获取外部存储空间的绝对路径,然后操作文件:

Environment.getExternalStorageDirectory();

例如,我们可以在外包存储的根目录下创建自己的目录:/storage/emulated/0/自己的目录