Android 数据持久化之 文件存储
在 Android 开发中,存储文件是一个常见的需求。文件存储对数据不进行任何格式化处理,原封不动地保存到文件中。适合存储一些简单的文本数据或者二进制数据。
一、存储路径
根据文件的存储位置和访问权限,可以将文件存储分为内部存储(Internal Storage)和外部存储(External Storage)。
1、内部存储(Internal Storage)
- 私有存储空间
内部存储是应用私有的存储空间,其他应用无法访问。它适用于存储敏感信息或应用专用的数据。 - 不需特殊权限
内部存储的文件路径是应用私有的,不需要特殊权限。 - 文件路径
内部存储的文件路径通常位于 /data/data/你的应用包名/ 目录下。但是从 Android 6.0(API 级别 23)开始,Google 引入了多用户支持,这导致了内部存储路径的变化,路径从 /data/data/你的应用包名/ 变为 /data/user/0/你的应用包名/。 - 多用户支持
每个用户的数据都存储在独立的目录中,路径格式为 /data/user/用户ID/。0 是默认用户的用户 ID,如果你的设备上只有一个用户,那么 /data/user/0/ 就是默认用户的内部存储路径。 - 路径映射
在多用户支持的系统中,/data/data/包名/ 是一个符号链接,它指向 /data/user/0/包名/。这两个路径实际上是相同的,指向同一个物理目录。 - 文件访问
使用 Context 提供的方法(如 filesDir、cacheDir、getDatabasePath() 等)来访问内部存储路径。 - 文件大小
内部存储的文件大小通常没有限制,但建议不要存储过大的文件,以免影响应用性能。
/*** 获取内部存储路径: /data/user/0/<packageName>/*/fun getInternalPath(context: Context) {// 获取文件目录路径: /data/user/0/你的应用包名/files/val filePath = context.filesDir.absolutePath// 获取缓存目录路径: /data/user/0/你的应用包名/cache/val cachePath = context.cacheDir.absolutePath// 获取数据库文件路径: /data/user/0/你的应用包名/databases/my_database.dbval dbPath = context.getDatabasePath("my_database.db").absolutePath}
2、外部存储(External Storage)
- 共享存储空间
外部存储是共享的存储空间,其他应用可以访问。从 Android 10(API 级别 29)开始,外部存储的访问方式发生了变化,引入了分区存储(Scoped Storage)。如果你的应用目标 API 级别是 29 或更高,分区存储是强制性的。 - 需要特殊权限
外部存储需要 READ_EXTERNAL_STORAGE 和 WRITE_EXTERNAL_STORAGE 权限。从 Android 10 开始,建议使用分区存储,减少对这些权限的依赖。 - 分区存储
从 Android 10 开始,推荐使用分区存储。分区存储限制了应用对用户文件的访问,以保护用户隐私。推荐使用 MediaStore API 来访问外部存储中的媒体文件(图片、音频和视频文件)。 - 外部存储路径
外部存储路径通常位于 /storage/emulated/0/,这是用户可以访问的共享存储空间。通过 Environment.getExternalStorageDirectory().absolutePath 获取。 - 应用专用外部存储路径
应用专用外部存储路径是应用私有的,其他应用无法访问。路径通常位于 /storage/emulated/0/Android/data/你的应用包名/。通过 context.getExternalFilesDir(null).absolutePath 来获取。 - 公共目录路径
公共目录路径是所有应用都可以访问的共享存储路径,例如 Pictures、Documents、Movies 等。 - 使用 Storage Access Framework (SAF)
对于需要用户选择文件或存储位置的场景,可以使用 Storage Access Framework (SAF)。
/*** 外部存储路径: /storage/emulated/0/*/fun getExternalPath(context: Context) {// 获取应用专用外部存储路径: /storage/emulated/0/Android/data/你的应用包名/filesval filePath = context.getExternalFilesDir(null)?.absolutePath ?: ""// 获取外部存储路径: /storage/emulated/0val filePathEnv = Environment.getExternalStorageDirectory().absolutePath// 获取图片公共目录路径: /storage/emulated/0/Picturesval picturesPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).absolutePathLog.d("FileStorage", "[getExternalFilePath] filePath: $filePath, filePathEnv: $filePathEnv")}
3、使用 MediaStore API 访问媒体文件
4、使用 SAF 打开文件选择器
二、File 方式
在 Android 开发中,使用 File 类来存取数据是一种常见的方法。File 类提供了对文件系统的基本操作,包括创建、读取、写入和删除文件。
1、读写内部存储文件
/*** 读写内部存储文件*/fun writeReadFile(context: Context