You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

如何使用Flutter将应用内存储的拍摄图片保存至手机相册?

把Flutter应用内的图片保存到系统相册的方案

嗨,我来帮你搞定这个问题!确实image_picker只负责读取相册或拍照,要写入相册得用专门的第三方包,最常用的是gallery_saver(或者功能类似的image_gallery_saver),再配合权限处理包permission_handler搞定系统权限问题,下面是具体步骤:

具体实现步骤

1. 添加依赖

在你的pubspec.yaml文件里添加以下依赖:

dependencies:
  flutter:
    sdk: flutter
  gallery_saver: ^2.3.2  # 可以用最新版本号
  permission_handler: ^10.2.0  # 处理系统权限请求
  path_provider: ^2.0.15  # 你已经在用这个,无需重复添加

添加后运行flutter pub get安装依赖。

2. 配置平台权限

不同系统需要配置对应的权限声明,否则保存操作会失败甚至崩溃:

  • Android
    打开android/app/src/main/AndroidManifest.xml,在<manifest>标签内添加权限:
    <!-- Android 13+ 写入相册专属权限 -->
    <uses-permission android:name="android.permission.WRITE_MEDIA_IMAGES" />
    <!-- 兼容Android 12及以下版本 -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
    <!-- Android 10+ 兼容旧存储模式,可选 -->
    <application android:requestLegacyExternalStorage="true" ...>
    
  • iOS
    打开ios/Runner/Info.plist,添加相册写入权限的描述:
    <key>NSPhotoLibraryAddUsageDescription</key>
    <string>需要将拍摄的照片保存到相册</string>
    

3. 完整代码示例

这里是包含权限请求和保存逻辑的完整代码,你可以直接参考:

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:gallery_saver/gallery_saver.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:path_provider/path_provider.dart';

class PhotoSavePage extends StatefulWidget {
  const PhotoSavePage({super.key});

  @override
  State<PhotoSavePage> createState() => _PhotoSavePageState();
}

class _PhotoSavePageState extends State<PhotoSavePage> {
  // 获取你存在应用文档目录的图片路径
  Future<String> getLocalImagePath() async {
    final appDir = await getApplicationDocumentsDirectory();
    // 替换成你实际的图片文件名
    return '${appDir.path}/my_captured_photo.jpg';
  }

  Future<void> saveImageToGallery() async {
    // 第一步:请求相册写入权限
    PermissionStatus permissionStatus;
    if (await Permission.photosAddOnly.isRestricted) {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('相册权限被限制,请前往设置开启')),
      );
      return;
    }
    permissionStatus = await Permission.photosAddOnly.request();

    if (permissionStatus.isGranted) {
      // 第二步:确认图片文件存在
      final imagePath = await getLocalImagePath();
      final imageFile = File(imagePath);
      if (!await imageFile.exists()) {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(content: Text('应用内图片不存在')),
        );
        return;
      }

      // 第三步:调用GallerySaver保存到相册
      final saveResult = await GallerySaver.saveImage(imagePath);
      if (saveResult != null && saveResult) {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(content: Text('图片已成功保存到相册!')),
        );
      } else {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(content: Text('保存图片失败,请重试')),
        );
      }
    } else {
      // 权限被拒绝的处理
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('需要开启相册权限才能保存图片')),
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('保存图片到相册')),
      body: Center(
        child: ElevatedButton(
          onPressed: saveImageToGallery,
          child: const Text('保存到相册'),
        ),
      ),
    );
  }
}

额外说明

  • 如果你更倾向于使用image_gallery_saver,用法和gallery_saver几乎一致,只是保存方法变成ImageGallerySaver.saveFile(imagePath),可以自行替换。
  • Android 13+的权限逻辑有更新,permission_handlerPermission.photosAddOnly会自动适配对应系统的权限请求,无需手动判断系统版本。
  • 保存成功后,部分设备可能需要等待几秒才能在相册里看到新图片,这是系统相册的刷新机制问题,属于正常现象。

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

火山引擎 最新活动