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

Flutter应用Android 11运行报错OS Error: Operation not permitted errno=1 模拟器及安卓8正常

问题根因

你遇到的报错是Android 11及以上版本的分区存储权限限制导致的。Android 10开始引入分区存储机制,Android 11强制启用,应用默认无法直接在公共存储空间根目录创建自定义文件夹(你代码里的storage/emulated/0/sweld路径就属于这类场景),所以截图保存时触发权限拒绝异常,异步代码报错中断执行,就不会执行后续的页面跳转逻辑,同时截图返回null。

可行解决步骤
  • 步骤1:配置Android静态权限
    打开android/app/src/main/AndroidManifest.xml文件,在<manifest>标签下添加以下权限声明,同时给<application>标签添加兼容属性:
    <!-- 读写公共存储权限 -->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
    <!-- Android 13及以上图片存储权限 -->
    <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
    
    <application
      android:requestLegacyExternalStorage="true"
      ...其他原有application配置不变>
    
  • 步骤2:动态申请存储权限
    执行截图保存逻辑前,先动态申请存储权限,权限授予成功后再执行后续操作,可通过permission_handler包实现权限申请,示例逻辑如下:
    import 'package:permission_handler/permission_handler.dart';
    import 'package:device_info_plus/device_info_plus.dart';
    
    // Next按钮点击事件调整为以下逻辑
    onPressed: () async {
      PermissionStatus status;
      if (Platform.isAndroid) {
        final androidInfo = await DeviceInfoPlugin().androidInfo;
        if (androidInfo.version.sdkInt >= 33) {
          status = await Permission.photos.request();
        } else if (androidInfo.version.sdkInt >= 23) {
          status = await Permission.storage.request();
        } else {
          status = PermissionStatus.granted;
        }
      } else {
        status = PermissionStatus.granted;
      }
      if (!status.isGranted) {
        ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("存储权限未授予,无法保存截图")));
        return;
      }
      // 权限授予成功后再执行截图
      Globals.ss211 = await _ssc.captureAndSave(Globals.appDir,
          fileName: "ss211.png",
          pixelRatio: MediaQuery.of(context).devicePixelRatio,
          delay: Duration(milliseconds: 100));
      // 校验截图结果再跳转
      if (Globals.ss211 != null) {
        Navigator.pushNamed(context, "/212");
      } else {
        ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("截图保存失败,请重试")));
      }
    }
    
  • 步骤3:优化存储路径(长期推荐方案)
    不要手动拼接公共存储根目录路径,改用path_provider包获取官方推荐的合法存储路径:
    import 'package:path_provider/path_provider.dart';
    
    // 获取应用私有目录,不需要额外权限,仅应用自身可访问
    final appDir = await getApplicationDocumentsDirectory();
    // 如果需要截图在系统相册可见,获取公共图片目录
    final publicImgDir = await getExternalStorageDirectory(type: StorageDirectory.pictures);
    
  • 步骤4:适配高版本系统(可选)
    后续可将build.gradle中的compileSdkVersion和targetSdkVersion升级到33,适配最新Android系统的权限规则。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 22:57:04