Android 10模拟器下载文件至Download目录遇EACCES权限拒绝问题
问题解决:Android 10模拟器下载文件到Download目录权限拒绝
问题原因
Android 10(API 29)引入了分区存储(Scoped Storage),即便已申请READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE权限,直接通过FileOutputStream操作公共Download目录的文件仍会被系统拦截,返回EACCES权限拒绝错误。而Android 11+(API30及以上)调整了权限规则,授予WRITE_EXTERNAL_STORAGE后允许直接访问公共目录,因此旧代码在高版本设备能正常运行。
解决方案
方案1:临时兼容旧存储模型(快速修复,不推荐长期使用)
在AndroidManifest.xml的<application>标签中添加以下属性,强制Android 10使用旧的存储访问模型:
<application ... android:requestLegacyExternalStorage="true"> ... </application>
注意:该属性仅对Android 10生效,Android11+会忽略此配置,且长期来看不符合Google的存储规范。
方案2:适配分区存储(推荐)
使用MediaStoreAPI写入公共Download目录,这是Android 10及以上的标准做法:
withContext(Dispatchers.IO) { val contentValues = ContentValues().apply { put(MediaStore.Downloads.DISPLAY_NAME, "shareFile.mp3") put(MediaStore.Downloads.MIME_TYPE, "audio/mpeg") put(MediaStore.Downloads.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS) } val uri = contentResolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, contentValues) uri?.let { contentResolver.openOutputStream(it)?.use { outputStream -> URL(soundURL).openStream().use { inputStream -> inputStream.copyTo(outputStream) } } } ?: run { // 处理uri获取失败的情况 } }
该方式无需依赖旧存储模型,完全符合分区存储规范,兼容Android 10及所有更高版本。
内容的提问来源于stack exchange,提问作者HavanaSun
相关产品推荐
相关产品推荐

