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
相关产品推荐
相关产品推荐

