内部存储和外部存储
前言
Android系统的内部存储和外部存储是两个容易混淆的概念。
下面通过两个图来对内部存储和外部存储进行简单阐述。
图一:内部存储和外部存储
图二:Android系统目录结构
Android系统的内核使用的是Linux内核, 所以Android的文件目录结构和Linux系统的文件目录结构类似.Android系统使用虚拟文件系统(VFS), VFS的目录是以/
为根节点,根节点下又有不同的节点。而我们的物理存储设备就是挂载都这些节点上,如下图所示:
内部存储
内部存储是指系统内部存储空间,在逻辑上用目录来区分就是data目录下的文件夹。
设备安装的apk、以及应用使用过程中产生一些文件如:SharedPreference键值对文件,数据库Sqlite文件均存储于该路径下。
内部存储位于系统中很特殊的一个位置,对于设备中每一个安装的 App,系统都会在data/data/packagename/xxx
自动创建与之对应的文件夹。
如果你想将文件存储于内部存储中,那么文件默认只能被你的应用访问到,且一个应用所创建的所有文件都在和应用包名相同的目录下。也就是说应用创建于内部存储的文件,与这个应用是关联起来的。当一个应用卸载之后,内部存储中的这些文件也被删除。对于这个内部目录,用户是无法访问的,除非获取root权限。
获取某个应用私有的内部存储路径:
String fileDir = context.getFilesDir().getAbsolutePath();
String cacheDir = context.getCacheDir().getAbsolutePath();
打印结果一般如下:
data/data/packagename/files
data/data/packagename/cache
部分手机的打印结果:
fileDir: /data/user/0/packagename/files
cacheDirDir: /data/user/0packagename/cache
可能与手机设置手机分身有关,当开启手机分身后打印结果为:
fileDir: /data/user/10packagename/files
cacheDirDir: /data/user/10/packagename/cache
context.getCacheDir()和context.getFilesDir()的区别
它们都位于内部存储,都是应用私有的目录。
getCacheDir
对应内部存储的路径为: data/data/packagename/cache
,但是对于部分手机取到的路径为:data/user/0/packagename/cache
,它是应用程序的缓存目录,该目录内的文件在设备内存不足时会优先被删除掉,所以存放在这里的文件是没有任何保障的,可能会随时丢掉。
getFilesDir
对应内部存储的路径为: data/data/packagename/files
,位于该路径的文件会被长期存储,不会被清理。
当用户卸载应用时,这两个路径下的文件都会被删除。
外部存储
针对于外部存储比较容易混淆,因为在Android4.4以前,手机机身存储就叫内部存储,插入的SD卡就是外部存储,但是在Android4.4以后的话,就目前而言,手机机身出厂自带的存储也是归属于外部存储,若再插入SD卡的也称之为外部存储,因此对于外部存储分为两部分:SD卡和手机自带扩展内存.(值得一提的是Android手机逐渐摒弃外置SD卡)
外部存储应用私有目录路径获取
context.getExternalCacheDir()
获取外部存储应用私有的缓存。
对应外部存储路径:/storage/emulated/0/Android/data/packagename/cache
缓存目录中的文件可能会在系统需要空间时被清除。
context.getExternalFilesDir(String type)
/**
* @param type The type of files directory to return. May be {@code null}
* for the root of the files directory or one of the following
* constants for a subdirectory:
* {@link android.os.Environment#DIRECTORY_MUSIC},
* {@link android.os.Environment#DIRECTORY_PODCASTS},
* {@link android.os.Environment#DIRECTORY_RINGTONES},
* {@link android.os.Environment#DIRECTORY_ALARMS},
* {@link android.os.Environment#DIRECTORY_NOTIFICATIONS},
* {@link android.os.Environment#DIRECTORY_PICTURES}, or
* {@link android.os.Environment#DIRECTORY_MOVIES}.
* @return the absolute path to application-specific directory. May return
* {@code null} if shared storage is not currently available.
*/
@Nullable
public abstract File getExternalFilesDir(@Nullable String type);
对应外部存储路径:/storage/emulated/0/Android/data/packagename/files
外部存储公有目录存储路径
在启用分区存储之前,SD卡里面的文件是可以被自由访问,即文件的数据对其他应用或者用户来说都是可以访问的,当应用被卸载之后,其卸载前创建的文件仍然保留。
对于SD卡上面的文件路径需要通过Environment获取,同时在获取前需要判断SD的状态:
// Checks if a volume containing external storage is available
// for read and write.
private boolean isExternalStorageWritable() {
return Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED;
}
// Checks if a volume containing external storage is available to at least read.
private boolean isExternalStorageReadable() {
return Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED ||
Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED_READ_ONLY;
}
通过Environment获取:
getExternalStorageDirectory()
对应外部存储路径:/storage/emulated/0
getExternalStoragePublicDirectory(String type)
获取外部存储的共享文件夹路径如:
DIRECTORY_MUSIC 音乐目录
DIRECTORY_PICTURES 图片目录
DIRECTORY_MOVIES 电影目录
DIRECTORY_DOWNLOADS 下载目录
DIRECTORY_DCIM 相机拍照或录像文件的存储目录
DIRECTORY_DOCUMENTS 文件文档目录
例:
String externalStoragePublicDirectory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getPath();
以上便是获取相机DCIM目录,对应获取的路径为:/storage/emulated/0/DCIM
。
参考
Android系统中内部存储和外部存储(公有目录、私有目录、缓存目录)详解
应用数据和文件
解析Android内部存储、外部存储的区别
一篇文章搞懂android存储目录结构