Android 读写权限变更详解:从运行时权限到分区存储
随着 Android 系统不断升级,为了更好地保护用户隐私,Google 对应用读写存储权限的控制越来越严格。尤其从 Android 10 起,“分区存储”(Scoped Storage)成为默认机制,彻底改变了传统文件访问方式。本文将系统梳理 Android 各版本中读写权限的演变,并给出实际开发建议。
一、权限演进时间线
📌 Android 6.0(API 23)— 引入运行时权限机制
首次需要开发者在运行时请求敏感权限,例如:
READ_EXTERNAL_STORAGEWRITE_EXTERNAL_STORAGE
开发者必须动态请求权限,才能访问外部存储的公共目录(如 DCIM、Download)。
📌 Android 10(API 29)— 引入 Scoped Storage
- 默认启用“分区存储”:应用仅能访问自己的沙盒目录。
- 公共目录访问受限,必须通过
MediaStore或 SAF。 requestLegacyExternalStorage="true"可临时回退至旧行为(仅在 Android 10 生效)。
📌 Android 11(API 30)— 强制分区存储,新增“全部文件访问”权限
-
requestLegacyExternalStorage彻底失效。 -
若应用需要访问整个外部存储,必须申请:
xml 复制编辑 <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>并引导用户前往设置页面授权:
kotlin 复制编辑 if (!Environment.isExternalStorageManager()) { val intent = Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION) startActivity(intent) } -
此权限适用于文件管理器、杀毒类 App,Google Play 上架需说明充分理由。
📌 Android 13(API 33)— 精细化媒体权限控制
将媒体访问权限拆分为三类:
READ_MEDIA_IMAGESREAD_MEDIA_VIDEOREAD_MEDIA_AUDIO
开发者根据访问类型申请对应权限,而非笼统的 READ_EXTERNAL_STORAGE。
📌 Android 14(API 34)— 权限使用透明化
- 系统增强权限审计,用户可查看 App 权限访问历史。
- 后台访问媒体的行为进一步限制。
- SAF 仍然是访问文档类、非媒体文件的推荐方式。
二、常见场景应对策略
| 需求 | 推荐方式 | 是否需权限 |
|---|---|---|
| 访问 App 私有目录 | context.getExternalFilesDir() | 否 |
| 读取媒体文件(图片/视频/音频) | MediaStore + READ_MEDIA_* 权限 | 是 |
| 读取非媒体文件(如 PDF、ZIP) | SAF(文档选择器) | 否 |
| 管理整个外部存储 | MANAGE_EXTERNAL_STORAGE 权限 | 是(Play 审核严格) |
三、实践建议
- 避免不必要的存储权限,尽量使用 App 专属目录。
- 使用 MediaStore 替代传统文件 API 访问媒体资源。
- 通过 SAF 让用户主动选择文件/目录,提升安全性与兼容性。
- 注意系统版本差异,通过
Build.VERSION.SDK_INT做兼容处理。
四、处理
- 低于android 清单声明直接用
- android 6 到android 12 声明+动态授权
- android 13到android 14 细分为图片喝适配
- android 14及以上 需要增加'android.permission.READ_MEDIA_VISUAL_USER_SELECTED'
fun getMediaPermissions(): MutableList<String> {
return if (Build.VERSION.SDK_INT >= 34) {
// Android 14+ 需要全部三个权限
mutableListOf<String>(
android.Manifest.permission.READ_MEDIA_IMAGES,
android.Manifest.permission.READ_MEDIA_VIDEO,
"android.permission.READ_MEDIA_VISUAL_USER_SELECTED"
)
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
// Android 13-14 需要两个细分权限
mutableListOf<String>(
android.Manifest.permission.READ_MEDIA_IMAGES,
android.Manifest.permission.READ_MEDIA_VIDEO
)
} else {
// Android 12 及以下只需旧权限
mutableListOf<String>(android.Manifest.permission.READ_EXTERNAL_STORAGE)
}
}
五、结语
Android 存储权限的变更是不可逆的趋势。对于开发者而言,虽然这增加了开发复杂度,但也是对用户隐私的尊重。理解这些权限机制,并合理选择数据存储与访问方式,是每个 Android 开发者的必修课。