saver_gallery 5.0.2 copy "saver_gallery: ^5.0.2" to clipboard
saver_gallery: ^5.0.2 copied to clipboard

Flutter plugin to save images and videos to gallery on Android, iOS and HarmonyOS.

Saver Gallery #

pub package GitHub stars GitHub forks GitHub license GitHub issues FlutterCandies QQ 群

Overview #

The saver_gallery plugin enables you to save images and other media files (such as videos) directly to the Android and iOS gallery. While the image_picker plugin allows you to select images from the gallery, it does not support saving them back to the gallery. saver_gallery provides this essential functionality, making it easy to save media files in Flutter applications.

HarmonyOS support is also included starting from version 4.0.0.

Features #

  • Save images of various formats (png, jpg, gif, etc.) to the gallery.
  • Save video and other media files to the gallery.
  • Batch save multiple images or files at once.
  • Handle conditional saving with the skipIfExists parameter.
  • Compatible with Android, iOS, and HarmonyOS platforms.

Installation #

To include saver_gallery in your project, add it as a dependency in your pubspec.yaml file:

dependencies:
  saver_gallery: ^5.0.0

Requirements #

  • Flutter >=3.44.0
  • Dart >=3.12.0 <4.0.0
  • JDK 17 for Android builds
  • Android compileSdkVersion 36
  • Android minSdkVersion 19
  • iOS 13.0+

Version 5.0.0 and later require Flutter 3.41.0+. If your project still uses an older Flutter SDK, use saver_gallery 4.1.2.

The iOS implementation supports Swift Package Manager on Flutter 3.44.0+ while keeping CocoaPods support.


iOS Configuration #

If you are targeting iOS, ensure that your project is configured to use Swift. Add the following keys to your Info.plist file located at <project_root>/ios/Runner/Info.plist:

<key>NSPhotoLibraryAddUsageDescription</key>
<string>We need access to your photo library to save images.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>We need access to your photo library to save images.</string>

Explanation:
These keys provide descriptions for permission prompts shown to users when your app requests access to their photo library.


Android Configuration #

For Android, you need to handle storage permissions to save files to the gallery. Use the permission_handler package to manage permissions.

Required Permissions #

Add the following permissions to your AndroidManifest.xml file:

<uses-permission
    android:name="android.permission.WRITE_EXTERNAL_STORAGE"
    android:maxSdkVersion="28"
    tools:ignore="ScopedStorage" />

<!-- Required if skipIfExists is set to true on Android 12 and below -->
<uses-permission
    android:name="android.permission.READ_EXTERNAL_STORAGE"
    android:maxSdkVersion="32" />

<!-- Required if skipIfExists is set to true on Android 13+ for the media types you save -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />

If your manifest does not already declare the tools namespace, add xmlns:tools="http://schemas.android.com/tools" to the root <manifest> element.

Handling Permissions #

To handle permissions properly, use the permission_handler package. Depending on the Android SDK version, permissions requirements vary. Here's how you can implement permission handling:

import 'dart:io';
import 'package:permission_handler/permission_handler.dart';
import 'package:device_info_plus/device_info_plus.dart';

enum MediaType {
  image,
  video,
  audio,
}

Future<bool> checkAndRequestPermissions({
  required bool skipIfExists,
  MediaType mediaType = MediaType.image,
}) async {
  if (!Platform.isAndroid && !Platform.isIOS) {
    return false; // Only Android and iOS platforms are supported
  }

  if (Platform.isAndroid) {
    final deviceInfo = await DeviceInfoPlugin().androidInfo;
    final sdkInt = deviceInfo.version.sdkInt;

    if (sdkInt < 29) {
      return await Permission.storage.request().isGranted;
    }

    if (!skipIfExists) {
      return true;
    }

    if (sdkInt < 33) {
      return await Permission.storage.request().isGranted;
    }

    switch (mediaType) {
      case MediaType.image:
        return await Permission.photos.request().isGranted;
      case MediaType.video:
        return await Permission.videos.request().isGranted;
      case MediaType.audio:
        return await Permission.audio.request().isGranted;
    }
  } else if (Platform.isIOS) {
    // iOS permission for saving images to the gallery
    return skipIfExists
        ? await Permission.photos.request().isGranted
        : await Permission.photosAddOnly.request().isGranted;
  }

  return false; // Unsupported platforms
}

Explanation:

  • For Android:

    • SDK 29+: Does not require read permission for writing files.
    • SDK 33+: Requires Permission.photos, Permission.videos, or Permission.audio to check if a file exists.
    • SDK < 29: Requires Permission.storage for read and write operations.
  • For iOS:

    • Uses Permission.photos to check if a file exists.
    • Uses Permission.photosAddOnly for saving files without needing full photo library access.

Usage #

Saving an Image #

To save an image (e.g., png, jpg, or gif) to the gallery from the internet:

import 'dart:typed_data';
import 'package:dio/dio.dart';
import 'package:saver_gallery/saver_gallery.dart';

_saveGif() async {
  var response = await Dio().get(
    "https://hyjdoc.oss-cn-beijing.aliyuncs.com/hyj-doc-flutter-demo-run.gif",
    options: Options(responseType: ResponseType.bytes),
  );

  String imageName = "test_image.gif";

  final result = await SaverGallery.saveImage(
    Uint8List.fromList(response.data),
    quality: 60,
    fileName: imageName,
    androidRelativePath: "Pictures/appName/images",
    skipIfExists: false,
  );

  print(result.toString());
  _showToast("$result");
}

Explanation:

  • quality: Set the image quality (0-100) for compressing images. This only applies to jpg format.
  • fileName: The name of the file being saved.
  • androidRelativePath: Relative path in the Android gallery, e.g., "Pictures/appName/images".
  • skipIfExists: If true, skips saving the image if it already exists in the specified path.

Saving a File (e.g., Video) #

To save other types of files (e.g., videos) to the gallery:

import 'package:path_provider/path_provider.dart';
import 'package:dio/dio.dart';
import 'package:saver_gallery/saver_gallery.dart';

_saveVideo() async {
  var tempDir = await getTemporaryDirectory();
  String videoPath = "${tempDir.path}/sample_video.mp4";

  await Dio().download(
    "http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4",
    videoPath,
  );

  final result = await SaverGallery.saveFile(
    filePath: videoPath,
    skipIfExists: true,
    fileName: 'sample_video.mp4',
    androidRelativePath: "Movies",
  );

  print(result);
}

Explanation:

  • filePath: Path to the file being saved.
  • skipIfExists: If true, skips saving the file if it already exists.
  • fileName: Desired name of the file in the gallery.
  • androidRelativePath: Relative path in the Android gallery, e.g., "Movies".

Batch Saving #

Save multiple images or files at once:

import 'package:saver_gallery/saver_gallery.dart';

// Batch save images
_saveBatchImages() async {
  final images = [
    SaveImageData(bytes: imageBytes1, fileName: 'image1.jpg'),
    SaveImageData(bytes: imageBytes2, fileName: 'image2.png'),
  ];
  
  final result = await SaverGallery.saveImages(images, skipIfExists: false);
  print(result);
}

// Batch save files
_saveBatchFiles() async {
  final files = [
    SaveFileData(filePath: '/path/to/file1.mp4', fileName: 'video1.mp4'),
    SaveFileData(filePath: '/path/to/file2.mp4', fileName: 'video2.mp4'),
  ];
  
  final result = await SaverGallery.saveFiles(files, skipIfExists: false);
  print(result);
}

Additional Information #

For more advanced usage and detailed API documentation, refer to the official documentation.


License #

This project is licensed under the MIT License. For more details, see the LICENSE file.


75
likes
150
points
38.4k
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Flutter plugin to save images and videos to gallery on Android, iOS and HarmonyOS.

Homepage
Repository (GitHub)
View/report issues

Topics

#flutter #gallery #image #video #save

License

MIT (license)

Dependencies

flutter, mime, path, path_provider, uuid

More

Packages that depend on saver_gallery

Packages that implement saver_gallery