如何修复Flutter的FileSystemException文件无法打开权限拒绝错误
问题描述
我用Dart和dart_git包开发读取Git仓库数据的Flutter应用,读取.git/config文件时触发权限错误:
I/flutter (13909): Error: FileSystemException: Cannot open file, path = '/storage/emulated/0/Download/git_repository/.git/config' (OS Error: Permission denied, errno = 13)
已在AndroidManifest.xml添加权限:
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <application android:requestLegacyExternalStorage="true"
试过真机和不同模拟器,但问题依旧。
解决方案
1. 修复MANAGE_EXTERNAL_STORAGE权限请求逻辑
Android 11+中,MANAGE_EXTERNAL_STORAGE是特殊权限,无法通过普通弹窗请求获取,必须引导用户到应用设置页手动开启:
Future<bool> _requestManageStoragePermission() async { if (!await Permission.manageExternalStorage.isGranted) { // 跳转到应用设置页让用户手动开启权限 await openAppSettings(); return await Permission.manageExternalStorage.isGranted; } return true; }
替换你代码中_hasFileAccessPermission和_requestFileAccessPermission里的权限请求逻辑,确保先检查权限状态,未授权时直接跳转设置页。
2. 调整权限请求时机
不要等到加载Git仓库后才检查权限,应该在选择文件夹前完成所有必要权限的验证:
onPressed: () async { // 先处理Android 11+的特殊存储权限 bool hasManagePerm = await _requestManageStoragePermission(); if (!hasManagePerm) { print("需要授予「管理所有文件」权限才能访问仓库"); return; } // 兼容低版本的常规存储权限 PermissionStatus storageStatus = await Permission.storage.request(); if (storageStatus.isGranted) { String? directoryPath = await FilePicker.platform.getDirectoryPath(); if (directoryPath != null) { setState(() { _selectedPath = directoryPath; }); await _initializeGitRepo(Directory(directoryPath)); } } else { print('存储权限未授予'); } },
3. 完善AndroidManifest配置
针对不同Android版本拆分权限配置,确保requestLegacyExternalStorage仅作用于Android 10(API 29),同时补全application标签的闭合:
<!-- Android 11+ 需单独声明管理存储权限 --> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" android:minSdkVersion="30"/> <!-- Android 10及以下用读写权限 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <application android:requestLegacyExternalStorage="true" <!-- 其他原有配置 --> > <!-- 活动等组件配置 --> </application>
4. 调整仓库加载顺序
你的代码中先执行GitRepository.load再检查权限,会直接触发权限错误。修改_initializeGitRepo,确保权限验证通过后再加载仓库:
Future<void> _initializeGitRepo(Directory directory) async { try { // 先确认权限已授予,再加载仓库 bool hasPerm = await Permission.manageExternalStorage.isGranted && await Permission.storage.isGranted; if (!hasPerm) { print("权限不足,无法访问仓库"); return; } GitRepository gitRepo = await GitRepository.load(directory.path); // 后续读取HEAD、提交信息的逻辑... } catch (e) { print('Error: $e'); } }
5. 测试注意事项
- Android 11+设备必须手动到「应用设置」-「权限」-「存储」中开启「允许管理所有文件」,仅弹窗请求无法获取该权限。
- 测试前卸载旧版本应用,避免权限缓存导致的异常。
内容的提问来源于stack exchange,提问作者Sam Hughes
相关产品推荐
相关产品推荐

