先看看以前( < 10/Q )的存储访问权限是怎样的

从 APP 目录(app-specific directories)的角度看,可以分为:

  1. 内部存储(app-specific directories in internal storage)
    1. 对于 app 自己,无需申请任何读/写权限
    2. 对于其他 app,没有访问权限
  2. 外部存储(app-specific directories in external storage)
    1. 对于 app 自己,无需申请任何读/写权限
    2. 对于其他 app,可以访问但需要申请读/写权限

从存储设备的角度看,可以分为:

  1. 内部存储,除了自己的目录,没有访问权限
  2. 外部存储,可以访问但需申请读/写权限(除了自己的目录)

而启用 Scoped Storage( ≥ 10/Q)后,APP 只能通过下述三种方法访问文件:

  1. 对于 APP 目录( app-specific directories ),无论是内部存储还是外部存储,无需申请任何读/写权限即可访问( File API ),APP 卸载时被删除
  2. 通过 MediaStore API 操作媒体文件,读/写 APP 自己的文件时无需任何权限,访问其他 APP 的内容时需要申请 READ_EXTERNAL_STORAGE;开启 Scoped Storage 后,只能访问 MediaStore.ImagesMediaStore.VideoMediaStore.Audio 和自己的 MediaStore.Downloads
  3. 通过 SAF( Storage Access Framework,也就是文件选择器 )读/写其他的文件,参考 Open files using storage access framework
  4. 其他方式即使拥有读写权限也会抛出 java.io.IOException: Permission denied

兼容性( targetSDK )

  1. < 29,默认关闭,可以通过 requestLegacyExternalStorage = false 打开
  2. = 29,默认开启,可以通过 requestLegacyExternalStorage = true 关闭
  3. 29,强制开启,requestLegacyExternalStorage 被忽略

常用的 APP 目录