25

My flutter app uses the camera package to take a photo, which I save to the application's data directory (obtained from path_provider and the getApplicationDocumentsDirectory() function).

How can I save this image file into the phone photo gallery? I've noticed the image_picker package allows reading from the gallery, but how can I write to it?

Duncan Jones
  • 67,400
  • 29
  • 193
  • 254
  • Hey, it's been more than 2 years, did you find any plugin that does what you required(I don't know how to use platform channels) – Nithin Sai Dec 16 '20 at 03:58

10 Answers10

20

https://pub.dev/packages/gallery_saver

this plugin saves images and video to gallery/photos.

You just need to provide it with path to temp file that you got from Camera(or even network url, it also works):

GallerySaver.saveVideo(recordedVideo.path);
GallerySaver.saveImage(recordedImage.path);
jelenap
  • 501
  • 6
  • 18
9

Unfortunately flutter doesn't currently exposes that functionality. It does seem like a candidate for a plugin though.

If you're motivated enough, you could use platform channels to communicate from flutter to native Android (and iOS) code, from which you can get full access the gallery. Bonus points if you make it into a plugin and publish it!

rmtmckenzie
  • 37,718
  • 9
  • 112
  • 99
  • As far as I know there's no plugin yet for that. I have added this exact case as an example of relatively easy plugin to be implemented, with detailed steps necessary for doing it in my post on https://medium.com/p/contributing-to-flutter-part-2-46092dc4417e. – Fabio May 06 '18 at 07:38
  • Is there any plugin for that now? – Balaji Feb 04 '22 at 12:40
8

There is a plugin that supports this.

https://pub.dev/packages/image_gallery_saver

I have tested it and it's working fine.

Ares
  • 2,504
  • 19
  • 19
  • 3
    Also - like gallery_saver - fails on Android 11 – novas1r1 Nov 05 '20 at 08:07
  • works on android now but fails for iOS :(! Opened an issue on github: https://github.com/CarnegieTechnologies/gallery_saver/issues/93 – novas1r1 Feb 11 '21 at 09:11
  • actually the saveImage method not works when you specify a name of image. the image name remains in the ios format IMG_XXX. i have open an issue on github but there are many issue remained open for this issue. – bl4ckr0se Feb 23 '22 at 00:22
6

I made the plugin. Please try it if you like.

https://pub.dartlang.org/packages/image_downloader#-readme-tab-

update

I will explain how to use.

Add this to your package's pubspec.yaml file:

dependencies:
  image_downloader: ^0.9.0

After that, specify permission for each devices.

Just write the following and image will be saved.

ImageDownloader.downloadImage(url);
ko2ic
  • 1,977
  • 14
  • 20
  • I implemented it and ImageDownloader return true, but where is the file located? – Meir Jan 01 '19 at 17:29
  • If download image has CreateDate of exif, there is in the date in Photo app(iOS) or download directory(Android). – ko2ic Jan 02 '19 at 04:59
1

I have been searching for this answer for a while but fortunately, I am able to save files to gallery with this code:

ByteData byteData = await rootBundle.load('assets/images/example.png');
File file = await File('/storage/emulated/0/Android/media/<your app package>/<App title/folder>/example.png').create(recursive: true);
await MediaStore.saveImage(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));

This will save your image to the device and your device gallery.

This only works for Android

Thanks.

1

There is a package which you can use to update the gallery by giving the path of the image or the video. The advantage of this over the other packages is that you can save files even in a sd card. The file will not be saved twice when you try to add media to gallery which are already saved to the device. This is the link to the package. https://pub.dev/packages/media_scanner

MediaScanner.loadMedia("Path to the file or directory"); // This will update the gallery

This is Android only

LovinduLI
  • 339
  • 4
  • 13
1

I had to search a lot, but I found a very useful solution to save the image in the cell phone's photo gallery and get the absolute path to use it the way you want. For this example I used a result obtained from saving an image in the photo gallery, however it could also work to read other files, obviously making the changes that you see necessary, I hope it will help you uri_to_file image_gallery_saver

import 'dart:io';

import 'package:image_gallery_saver/image_gallery_saver.dart';
import 'package:uri_to_file/uri_to_file.dart';

Future<File> saveImage(File image, String identifier) async {
try {
    var result = await 
    ImageGallerySaver.saveImage(image.readAsBytesSync(),
     quality: 60, name: identifier + 
    "-${DateTime.now().toIso8601String()}");
    print(result);
    File file = await toFile(Uri.parse(result['filePath']));
    print(file);
    return file;
   } catch (e) {
     print(e);
    return new File('assets/img/default-img.jpg');
  }
}
// example
saveImage(File("path/image/img223.jpg"),"img-test");
// or
ArmandoHackCode
  • 311
  • 2
  • 6
1

There is a workaround, I made it worked by specifying path to "/storage/emulated/0/DCIM/YOUR_FOLDER/YOUR_FILE_NAME" then it will be saved outside of support package directory then image appears in Gallery. You can use any image saver plugin just provide that hardcoded path.

ITcians
  • 47
  • 5
1

Since gallery_saver has already been unmaintained for two years, the gal package can be used instead.

await Gal.putImage(path);
await Gal.putVideo(path);

Incidentally, the temporary directory can be obtained without using path_provider, just with this code

Directory.systemTemp.path;

Some people try to save the media in the project's asset folder, so I leave the code for that as well.

final byteData = await rootBundle.load('assets/image.jpg');
final file = await File('${Directory.systemTemp.path}${path.replaceAll('assets', '')}').create();
await file.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
await Gal.putImage(file.path);

It works for both Android and iOS. More info can be found in the example of the gal package. Thank you.

okok
  • 63
  • 7
0

This is working for me-

// https://pub.dev/packages/path_provider
Future<String> getExtStorageOrDownloadsDirPath() async {
  final documentsDir = await getApplicationDocumentsDirectory();
  if (Platform.isAndroid) {
     //final extStorageDir = await getExternalStorageDirectory();
     //return extStorageDir?.path ?? documentsDir.path;
     return '/storage/emulated/0/Download';
  } else {
     final downloadsDir = await getDownloadsDirectory();
     return downloadsDir?.path ?? documentsDir.path;
  }
}

Once you get path, you can save like this

if (imageBytes != null) {
  XFile xFile = XFile.fromData(imageBytes, mimeType: 'image/png');
  String documentsDirPath = await getExtStorageOrDownloadsDirPath();
  String filePath =
      '$documentsDirPath/${widget.bannerData.creativeTitle?.split(' ').join('-')}.png';
  if (await Permission.storage.request().isGranted) {
    // Either the permission was already granted before or the user just granted it.
    xFile.saveTo(filePath);
    showToastMessage('Saved to $filePath');
  }
}
Varun Kumar
  • 2,543
  • 1
  • 23
  • 22