存储类型 | 特点 | 典型用途 |
---|---|---|
内部存储 | 应用私有空间,数据默认加密存储,卸载自动清除 | 配置文件、数据库、缓存文件 |
外部存储 | 共享存储空间,包含SD卡和手机内置存储空间 | 媒体文件、文档、下载内容 |
虚拟存储 | 通过ContentProvider暴露的数据沙箱(如Downloads/Pictures等系统目录) | 跨应用数据共享 |
/data/data/包名/ # 应用私有目录(内部存储) ├── files/ # 应用专用文件存储区 ├── cache/ # 缓存文件区(系统可清理) ├── databases/ # 数据库文件存放处 /storage/emulated/0 # 外部存储主目录(融合存储) ├── DCIM/ # 相机照片目录 ├── Download/ # 下载内容目录 ├── Pictures/ # 截图/图片目录 /android/data/包名/ # 应用外部存储专属目录
Android 10(API 29)前:
WRITE_EXTERNAL_STORAGE
权限可自由访问全部外部存储Android 10+ Scoped Storage:
| 存储区域 | 访问方式 |
|—————-|————————————————————————–|
| 应用专属目录 | 无需申请权限直接访问(/storage/emulated/0/Android/data/包名/
) |
| 公共媒体目录 | 需通过READ_EXTERNAL_STORAGE
访问(如DCIM/Download等) |
| 任意位置访问 | 必须使用Storage Access Framework
或MediaStore
API |
内部存储操作:
// 获取私有文件目录 val fileDir = context.filesDir // 创建缓存文件 val cacheFile = File(context.cacheDir, "temp.txt")
外部存储适配:
// 检查公共目录访问权限 if (Environment.MEDIA_MOUNTED == mountState) { val pictureDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES) pictureDir?.listFiles()?.forEach { / 处理文件 / } }
大文件存储方案:
| 文件类型 | 推荐方案 |
|—————-|—————————————————————————|
| 媒体文件 | 使用MediaStore
插入系统数据库,自动出现在相册等应用 |
| 文档文件 | 存入getExternalFilesDir()
返回的应用专属目录 |
| 临时大文件 | 使用Context.getCacheDir()
获取缓存路径 |
查询剩余空间:
val stats = context.getExternalFilesDir(null)?.let { StatFs(it.path).let { fs -> fs.availableBlocksLong fs.blockSizeLong } }
文件清理策略:
cacheDir
目录(系统升级时可能被自动清理)deleteOnExit()
标记临时文件Q1:如何判断设备是否支持可移除SD卡?
A1:可通过StorageManager
检测存储状态:
val storageManager = context.getSystemService(Context.STORAGE_SERVICE) as StorageManager val volumes = storageManager.storageVolumes.filter { it.isRemovable && it.state == Environment.MEDIA_MOUNTED } // volumes包含可移除存储介质列表
Q2:Android 11+如何实现任意路径文件选择?
A2:使用DocumentPicker
配合ACTION_OPEN_DOCUMENT
:
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply { addCategory(Intent.CATEGORY_OPENABLE) type = "/" // 支持所有文件类型 } startActivityForResult(intent, REQUEST_CODE_OPEN_DOCUMENT)
通过DocumentProvider
获取的Uri
可长期保存,需在Manifest
声明MANAGE_EXTERNAL_STORAGE
权限(仅限系统应用