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

Flutter在Android 11中下载PDF文件时遭遇FileSystemException(errno=1)权限异常求助

解决Android 11下文件写入权限异常(Operation not permitted, errno=1)

针对你遇到的问题,核心原因是Android 11引入的Scoped Storage机制,以及MANAGE_EXTERNAL_STORAGE权限的特殊管控逻辑,下面是具体的解决方案:

1. 修正MANAGE_EXTERNAL_STORAGE权限的请求逻辑

MANAGE_EXTERNAL_STORAGE是Android 11+的特殊权限,无法通过permission_handler的常规request()方法弹出系统授权弹窗,必须引导用户到应用设置页面手动开启权限。你需要修改权限请求代码:

Map<Permission, PermissionStatus> result = await [
  Permission.storage,
  Permission.mediaLibrary
].request();

// 单独处理MANAGE_EXTERNAL_STORAGE权限
if (Platform.isAndroid && (await Permission.manageExternalStorage.status).isDenied) {
  // 引导用户到应用设置页开启权限
  await openAppSettings();
  // 重新检查权限状态
  bool hasManagePerm = await Permission.manageExternalStorage.request().isGranted;
  if (!hasManagePerm) {
    Components.customSnackBar(context, "需要授予所有文件访问权限才能下载");
    return;
  }
}

// 确认所有必要权限都已授予
bool hasStorage = result[Permission.storage].isGranted;
bool hasMediaLib = result[Permission.mediaLibrary].isGranted;
bool hasManage = await Permission.manageExternalStorage.status.isGranted;

if (hasStorage && hasMediaLib && hasManage) {
  // 执行后续下载逻辑
}

2. 确保目标目录存在且可访问

你的自定义路径/storage/emulated/0/documents/download folder需要确认是否已正确创建,并且应用有访问权限。在Utility.makeAndGetDownloadFolder()方法中,添加目录创建的异常捕获:

static Future<String> makeAndGetDownloadFolder() async {
  String folderPath = '/storage/emulated/0/documents/download folder';
  Directory dir = Directory(folderPath);
  try {
    if (!await dir.exists()) {
      await dir.create(recursive: true);
    }
    return folderPath;
  } catch (e) {
    print("创建目录失败: $e");
    throw Exception("无法创建下载目录");
  }
}

3. 验证AndroidManifest配置的正确性

确保你的targetSdkVersion设置为30或更高(对应Android 11),因为MANAGE_EXTERNAL_STORAGE权限仅在targetSdk 30+时生效。同时,权限声明要精准适配不同版本:

<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
    android:minSdkVersion="30"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
    android:maxSdkVersion="29"/>

4. 优化文件写入的细节处理

你的文件名中包含冒号:,虽然Android系统允许,但部分场景可能存在兼容问题,建议替换为下划线_避免潜在风险:

String dateNow = DateTime.now().toString().replaceAll(RegExp(r'[ :.]'), '_');
String randomName = dateNow + Utility.getRandomString(5);
fullPath = "$dir/$randomName.pdf";

另外,写入文件时改用异步方法替代同步方法,既避免阻塞UI线程,也能更友好地捕获异常:

if (response.statusCode == 200) {
  try {
    File file = File(fullPath);
    await file.writeAsBytes(response.data);
    await showNotification(fullPath);
  } catch (e) {
    print("写入文件失败: $e");
    Components.customSnackBar(context, "文件写入失败");
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 07:53:14