Flutter Android11及以上使用File.writeAsBytes保存图片到公共路径报错如何解决
你遇到的报错是Android 11及以上版本的分区存储机制限制导致的,系统禁止普通应用直接通过绝对路径写入公共存储目录,仅应用专属目录可直接读写。以下是可行解决方案:
解决方案
方案1:使用gallery_saver等封装好的第三方库(最省事)
该库已经完成了不同Android版本的存储逻辑适配,无需自行处理原生API适配:
- 先在
pubspec.yaml引入依赖:
dependencies: gallery_saver: ^2.3.2 path_provider: ^2.1.0 # 用于获取应用缓存目录
- 保存图片的代码修改为如下内容:
import 'package:gallery_saver/gallery_saver.dart'; import 'package:path_provider/path_provider.dart'; import 'package:http/http.dart' as http; import 'dart:typed_data'; import 'dart:io'; void saveFileAndroid() async { int i = 0; for(var file in certificateList){ i += 1; var url = Uri.parse(GlobalApiService.getImage(file.path!)); var res = await http.get(url); // 先将图片写入应用专属缓存目录 final tempDir = await getTemporaryDirectory(); String imgName = "${model!.product.createdDate}$i.jpg"; File tempFile = File('${tempDir.path}/$imgName'); await tempFile.writeAsBytes(Uint8List.fromList(res.bodyBytes)); // 调用库方法自动保存到公共相册,会自动在Pictures目录下创建对应相册文件夹 await GallerySaver.saveImage(tempFile.path, albumName: "ProjectName"); // 可选:删除不再需要的临时文件 await tempFile.delete(); } }
适配Android 13及以上版本时,需要在AndroidManifest.xml中更新权限配置:
<!-- 安卓13以下权限 --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" /> <!-- 安卓13及以上图片权限 --> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
方案2:自行通过MediaStore API实现(无额外依赖)
如果不想引入第三方库,可以自行通过Android原生MediaStore接口插入图片到公共相册:
- 首先将项目
build.gradle中的compileSdkVersion和targetSdkVersion都升级到33或更高,保证API兼容性 - 移除
AndroidManifest.xml中application节点下的requestLegacyExternalStorage、preserveLegacyExternalStorage等旧版本适配标记 - 可以通过MethodChannel调用原生MediaStore逻辑,也可以用纯dart实现的
media_store库直接操作MediaStore接口完成图片插入
方案3:申请所有文件访问权限(不推荐,上架易被拒)
如果是内部使用不需要上架应用市场的应用,可以申请MANAGE_EXTERNAL_STORAGE权限,授权后原有直接写绝对路径的代码可正常运行:
- 引入
permission_handler库后动态申请权限:
import 'package:permission_handler/permission_handler.dart'; Future<bool> requestAllFilePermission() async { if (await Permission.manageExternalStorage.isGranted) return true; await Permission.manageExternalStorage.request(); return await Permission.manageExternalStorage.isGranted; }
注意:该权限仅允许核心功能为文件管理的应用申请,普通图片保存场景使用该权限会被Google Play及国内主流应用市场驳回上架申请
内容的提问来源于stack exchange,提问作者hong4383
相关产品推荐
相关产品推荐

