You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android 11及以上Scoped Storage模式下如何向共享存储(如Download)存取文件?

Scoped Storage 模式下共享Download目录的文件存取实现方案

面向Android 11(targetSdk 30+)强制Scoped Storage的场景,完全不用依赖废弃的外部存储根路径API,有两种官方推荐的合规实现路径:

方案1:MediaStore API 直写Download公共集合

这是最常用、适配成本最低的方案,适合单文件的常规存取场景:

  • 无需申请任何存储类危险权限,Android 10及以上版本对公共媒体集合的写入权限完全放开,旧的WRITE_EXTERNAL_STORAGE权限在targetSdk30+下已经完全失效,不需要在Manifest中声明
  • 实现逻辑是通过Android 10新增的MediaStore.Downloads专属集合,插入条目获取可写Uri,完成文件写入
  • 核心实现代码:
// 对应Download目录的系统Uri集合
val collection = MediaStore.Downloads.EXTERNAL_CONTENT_URI
// 构建文件元数据
val fileDetails = ContentValues().apply {
    put(MediaStore.Downloads.DISPLAY_NAME, "目标文件名.后缀")
    put(MediaStore.Downloads.MIME_TYPE, "文件对应的MIME类型,比如application/pdf")
    put(MediaStore.Downloads.IS_PENDING, 1) // 标记写入中,避免其他应用读到未完成的损坏文件
}
// 插入空条目,拿到可操作的文件Uri
val itemUri = contentResolver.insert(collection, fileDetails) ?: return
// 写入文件内容
contentResolver.openFileDescriptor(itemUri, "w")?.use { pfd ->
    FileOutputStream(pfd.fileDescriptor).use { outputStream ->
        // 此处写入实际文件数据
    }
}
// 写入完成后更新状态,通知系统文件可被公开访问
fileDetails.clear()
fileDetails.put(MediaStore.Downloads.IS_PENDING, 0)
contentResolver.update(itemUri, fileDetails, null, null)
  • 特性说明:
    • 自己写入的文件可以一直通过保存的Uri直接读写,不需要额外权限
    • 读取Download目录下其他应用创建的文件时,直接通过MediaStore查询对应集合拿到Uri即可打开,无需用户手动授权

方案2:存储访问框架(SAF)适配自定义子目录场景

如果需要在Download目录下创建自定义子文件夹、或者实现类似文件管理器的批量目录浏览操作,用MediaStore就满足不了需求,此时用SAF实现:

  • 同样不需要申请任何危险权限,通过系统自带的目录选择器引导用户手动完成一次授权,应用拿到对应目录的可读写Uri授权后,只要用户不手动在系统设置里撤销权限,就可以长期访问该目录
  • 核心触发授权代码:
// 唤起系统目录选择器,默认定位到Download目录
val selectDirIntent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).apply {
    putExtra(DocumentsContract.EXTRA_INITIAL_URI, Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS))
}
startActivityForResult(selectDirIntent, REQUEST_TREE_PERMISSION)
  • 拿到授权的目录Uri后,就可以通过DocumentsContract提供的接口完成新建文件、读写、删除等操作,不需要重复弹授权框

避坑提醒

几个实际开发里容易踩的合规坑:

  • 不要试图拿Environment.getExternalStoragePublicDirectory(DIRECTORY_DOWNLOADS)返回的绝对路径直接用Java File类操作文件,targetSdk30+下这种操作会直接抛权限拒绝错误,Scoped Storage下应用根本没有外部存储绝对路径的直接访问权限
  • 不要为了绕开限制去申请MANAGE_EXTERNAL_STORAGE全文件访问权限,这个属于特殊高风险权限,主流应用商店对这类权限的审核非常严格,无合理业务场景的应用会直接被拒绝上架
  • 如果存的是应用运行产生的临时文件、缓存文件,完全不需要放到公共Download目录,直接用应用专属的外部存储目录就行,该目录不需要任何权限,随时可以读写,应用卸载时会被系统自动清理

内容的提问来源于stack exchange,提问作者soiXam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.26 13:45:04