Android 数据持久化学习笔记 —— 内外部存储空间访问方法
Android 提供两类物理存储位置:内部存储空间和外部存储空间。
默认情况下,应用本身存储在内部存储空间中。不过,如果 APK 很大,也可以在清单文件中指明偏好设置,以便将应用安装到外部存储空间:
<manifest ...
android:installLocation="preferExternal">
...
</manifest>
内部存储空间
对应的路径是 /data/data/,为了适应多用户的功能会显示为 /data/user/0/,实际上是一个东西。这些目录既包括用于存储持久性文件的专属位置,也包括用于存储缓存数据的其他位置。系统会阻止其他应用访问这些位置,并且在 Android 10 及更高版本中,系统会对这些位置进行加密。这些特征使得这些位置非常适合存储只有应用本身才能访问的敏感数据。
Context 类提供了以下获取内部存储目录的方法:
// 获取的目录是/data/user/0/package_name,即应用内部存储的根目录
getDataDir()
// 获取的目录是/data/user/0/package_name/files,即应用内部存储的files目录
getFilesDir()
// 获取的目录是/data/user/0/package_name/cache,即应用内部存储的cache目录
getCacheDir()
// 获取的目录是/data/user/0/package_name/app_name,如果该目录不存在,系统会自动创建该目录。
getDir(String name, int mode)
外部存储空间
外部存储空间又分为外部私有空间和外部共享空间。
外部私有存储空间
对应路径是 /storage/emulated/0/Android/data/,其他应用可以在具有适当权限的情况下访问这些目录,但存储在这些目录中的文件仅供您的应用使用。如果要明确打算创建其他应用能够访问的文件,应将这些文件存储在外部共享存储空间。
// 获取外部私有存储目录的方法
// 获取到的目录是/storage/emulated/0/Android/data/package_name/cache,如果该目录不存在,调用这个方法会自动创建该目录。
getExternalCacheDir()
getExternalFilesDir(String type)
/* 1.如果 type 为 "",那么获取到的目录是 /storage/emulated/0/Android/data/package_name/files。
2.如果 type 不为空,则会在 /storage/emulated/0/Android/data/package_name/files 目录下创建一个以传入的 type 值为名称的目录,这个其实有点类似于内部存储 getDir 方法传入的 name 参数。Android 官方推荐使用以下 type 类型。
public static String DIRECTORY_MUSIC = "Music";
public static String DIRECTORY_PODCASTS = "Podcasts";
public static String DIRECTORY_RINGTONES = "Ringtones";
public static String DIRECTORY_ALARMS = "Alarms";
public static String DIRECTORY_NOTIFICATIONS = "Notifications";
public static String DIRECTORY_PICTURES = "Pictures";
public static String DIRECTORY_MOVIES = "Movies";
public static String DIRECTORY_DOWNLOADS = "Download";
public static String DIRECTORY_DCIM = "DCIM";
public static String DIRECTORY_DOCUMENTS = "Documents";*/
外部共享存储空间
对应路径是 /storage/emulated/0/,卸载应用不会删除。
// 获取到的目录是/storage/emulated/0,也就是外部存储的根目录。
Environment.getExternalStorageDirectory()
Environment.getExternalStoragePublicDirectory(String type)
/* 1.如果 type 为 "",那么获取到的目录是外部存储的根目录即 /storage/emulated/0。
2.如果 type 不为空,则会在 /storage/emulated/0 目录下创建一个以传入的 type 值为名称的目录。Android 官方推荐使用以下的 type 类型。
public static String DIRECTORY_MUSIC = "Music";
public static String DIRECTORY_PODCASTS = "Podcasts";
public static String DIRECTORY_RINGTONES = "Ringtones";
public static String DIRECTORY_ALARMS = "Alarms";
public static String DIRECTORY_NOTIFICATIONS = "Notifications";
public static String DIRECTORY_PICTURES = "Pictures";
public static String DIRECTORY_MOVIES = "Movies";
public static String DIRECTORY_DOWNLOADS = "Download";
public static String DIRECTORY_DCIM = "DCIM";
public static String DIRECTORY_DOCUMENTS = "Documents";*/
Android 提供用于存储和访问以下类型的可共享数据的 API:
- 媒体内容: 系统提供标准的公共目录来存储这些类型的文件,这样用户就可以将所有照片保存在一个公共位置,将所有音乐和音频文件保存在另一个公共位置,依此类推。可以使用 MediaStore API 访问这些内容。
- 文档和其他文件: 系统有一个特殊目录,用于包含其他文件类型,例如 PDF 文档和采用 EPUB 格式的图书。可以使用此平台的存储访问框架访问这些文件。
- 数据集: 在 Android 11(API 级别 30)及更高版本中,系统会缓存多个应用可能使用的大型数据集。这些数据集可为机器学习和媒体播放等用例提供支持。可以使用 BlobStoreManager API 访问这些共享数据集。
外部存储空间的访问权限
Android 定义了以下与存储相关的权限:READ_EXTERNAL_STORAGE
、WRITE_EXTERNAL_STORAGE
以及在 Android 11 上引入的 MANAGE_EXTERNAL_STORAGE
。
随着 Android 版本的更新,越来越依赖于文件的用途而不是位置来确定应用对特定文件的访问和写入能力。在 Android 11及更高版本上,WRITE_EXTERNAL_STORAGE
权限完全不会影响应用对存储的访问权限。这种基于用途的存储模型可增强用户隐私保护,因为应用只能访问其在设备文件系统中实际使用的区域。