Flutter读写Android/data文件夹权限报错(errno=3)求助
问题分析与解决方案
你的需求在部分Android版本下可实现,但受限于Android 10+引入的Scoped Storage机制,直接访问其他应用的Android/data目录存在系统级限制,你遇到的权限拒绝(errno=3)正是这个原因导致的,权限处理上存在以下疏漏:
核心限制说明
从Android 10(API 29)开始,系统引入Scoped Storage,Android/data属于其他应用的专属私有目录,默认禁止第三方应用直接读写。哪怕你申请了READ_EXTERNAL_STORAGE或MANAGE_EXTERNAL_STORAGE权限,在Android 11+系统中,也无法直接通过File API访问该目录下的文件。
权限处理的疏漏
- MANAGE_EXTERNAL_STORAGE是特殊权限:这个权限不能通过普通的权限申请流程获取,必须引导用户手动进入系统设置的「应用特殊权限」页面开启,代码里的权限申请弹窗不会触发该权限的授权。
- 权限不覆盖所有场景:即便用户开启了
MANAGE_EXTERNAL_STORAGE,Android 11+依然限制第三方应用直接访问其他应用的Android/data和Android/obb目录,这是系统硬规则,无法通过权限绕过。
可行实现方案
导出功能
- 使用存储访问框架(SAF):通过Intent唤起系统文件选择器,让用户手动找到游戏存档文件(需用户知晓存档在
Android/data/[游戏包名]下的具体路径),获取文件的Uri后,通过ContentResolver将文件复制到下载目录。 - 兼容Android 9及以下:这部分系统无Scoped Storage限制,可直接用File API完成复制操作。
导入功能
- 同样依赖SAF:让用户选择要导入的存档文件,再通过SAF尝试写入游戏的
Android/data目录。但注意:Android 11+下,除非游戏应用通过ContentProvider开放了写入权限,否则你无法直接写入其专属目录,此时只能引导用户手动复制文件,或使用root权限(但root不具备通用性)。
关键代码提示
以SAF获取文件为例:
// 唤起文件选择器 final intent = Intent( action: IntentConstants.ACTION_OPEN_DOCUMENT, type: '*/*', ); await intent.launch(); // 获取返回的Uri final uri = intent.resultData; // 通过ContentResolver读取文件 final inputStream = await contentResolver.openInputStream(Uri.parse(uri)); // 写入到下载目录 final outputFile = File('${(await getExternalStorageDirectory())?.path}/Download/存档文件'); await inputStream?.pipe(outputFile.openWrite());
内容的提问来源于stack exchange,提问作者StormPooper
相关产品推荐
相关产品推荐

