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
相关产品推荐
相关产品推荐

