save_in_gallery 0.1.3

  • Readme
  • Changelog
  • Example
  • Installing
  • 92

alt text

save_in_gallery #

Flutter plugin that allows you to save images in native gallery in both Android and iOS. You can either save them in default album or in named album of your choice.

Installation #

For installation details see Installing tab on this page.

Configuration #

iOS #

To use this plugin in iOS you must add 2 new records to configuration file info.plist located in ios/Runner directory. To do so, open iOS project in Xcode by running open ios/Runner.xcworkspace then right-click on info.plist file in project navigator and click open as > source code. Then add following 2 records at the end of <dict> object:

  • <key>NSPhotoLibraryAddUsageDescription</key> <string>write</string> Where write should be reason why your app requires write access to user's gallery. This is necessary to save images in gallery.
  • <key>NSPhotoLibraryUsageDescription</key> <string>read</string> Where read should be reason why your app requires read access to user's gallery. This is necessary to create and use named albums in gallery.

Be aware that app will ask user's permission to read/write gallery access using standard iOS alerts when you will use methods provided by this plugin. These alerts' appearance can not be changed.

If user declines access, these alerts can not be shown again, instead you must use custom controls to redirect user to Settings app, so they can grant access rights themselves. Methods provided by this plugin will not work unless user provides proper access rights.

Android #

This plugin should work out-of-the-box and does not require additional configuration.

Be aware that app will ask user's permission to WRITE_EXTERNAL_STORAGE using standard Android alerts when you will use methods provided by this plugin. These alerts' appearance can not be changed.

If user declines access, these alerts can not be shown again, instead you must use custom controls to redirect user to Settings app, so they can grant access rights themselves. Methods provided by this plugin will not work unless user provides proper access rights.

Examples #

import  'package:save_in_gallery/save_in_gallery.dart';
final _imageSaver =  ImageSaver();
Future<void> saveAssetImage() async {
	// 1
	final urls =  [
		"assets/image1.jpg",
		"assets/image2.jpg",
		"assets/image3.jpg",
	];
	// 2 
	List<Uint8List> bytesList = [];
	for (final url in urls) {
		final bytes =  await rootBundle.load(url);
		bytesList.add(bytes.buffer.asUint8List());
	}
	// 3
	final res = await _imageSaver.saveImages(
		imageBytes: bytesList
	);
	// 4
}
  1. Prepare list of asset URLs;
  2. Load each image, extract byte data, and map to Uint8List type;
  3. Invoke plugin method to save loaded images;
  4. res variable will hold result of saving operation. If it's true, then everything went as expected and images have been successfully saved. Otherwise something went wrong along the way. Use this variable to provide feedback to user.
import  'package:save_in_gallery/save_in_gallery.dart';
final _imageSaver =  ImageSaver();
Future<void> saveNetworkImage() async {
	// 1
	final url = "https://some_url/image.png";
	// 2
	final image =  NetworkImage(url);
	final key =  await image.obtainKey(ImageConfiguration());
	final load = image.load(key);
	load.addListener((listener, err) async {
		// 3
		final byteData = await listener.image.toByteData(
			format:  ImageByteFormat.png
		);		
		final bytes = byteData.buffer.asUint8List();
		// 4
		final res =  await _imageSaver.saveImage(
			imageBytes: bytes,
			directoryName:  "dir_name",
		);
		// 5
	});
}
  1. Prepapre URL to image you want to fetch;
  2. Create NetworkImage object with your URL and load it's configuration;
  3. Extract byte data from image;
  4. Invoke plugin method to save fetched image in custom album named dir_name;
  5. res variable will hold result of saving operation. If it's true, then everything went as expected and image have been successfully saved. Otherwise something went wrong along the way. Use this variable to provide feedback to user.

0.1.3 #

  • Fixed bug that caused photos to not save properly if it was first save after granting gallery access

0.1.2 #

  • Fixed bug that caused too many named albums to be created on iOS
  • Bumped dart minimal version to 2.2.2

0.1.1 #

  • Fixed code warnings
  • Bumped dart minimal version to 2.2.0

0.1.0 #

  • Initial release of save_in_gallery plugin

example/lib/main.dart

import 'dart:async';
import 'dart:ui';
import 'dart:typed_data';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:save_in_gallery/save_in_gallery.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final _imageSaver = ImageSaver();

  bool _isLoading = false;
  bool _showResult = false;
  String _resultText = "";
  Color _resultColor = Colors.red;

  @override
  void initState() {
    super.initState();
  }

  /// Fetches image from web and saves in gallery
  Future<void> saveNetworkImage() async {
    _startLoading();
    final url =
        "https://solarsystem.nasa.gov/system/downloadable_items/519_solsticeflare.jpg";
    final image = NetworkImage(url);
    final key = await image.obtainKey(ImageConfiguration());
    final load = image.load(key);
    load.addListener(
      ImageStreamListener((listener, err) async {
        final byteData =
            await listener.image.toByteData(format: ImageByteFormat.png);
        final bytes = byteData.buffer.asUint8List();
        final res = await _imageSaver.saveImage(
          imageBytes: bytes,
          directoryName: "dir_name",
        );
        _stopLoading();
        _displayResult(res);
        print(res);
      }),
    );
  }

  /// Saves one of asset images to gallery
  Future<void> saveAssetImage() async {
    _startLoading();
    final urls = ["assets/sun.jpg"];
    List<Uint8List> bytesList = [];
    for (final url in urls) {
      final bytes = await rootBundle.load(url);
      bytesList.add(bytes.buffer.asUint8List());
    }
    final res = await _imageSaver.saveImages(imageBytes: bytesList);
    _stopLoading();
    _displayResult(res);
    print(res);
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Plugin example app'),
        ),
        body: Stack(
          children: <Widget>[
            Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: <Widget>[
                Container(),
                RaisedButton(
                  onPressed: () => saveNetworkImage(),
                  child: Text("Save image from web"),
                ),
                SizedBox(height: 16.0),
                RaisedButton(
                  onPressed: () => saveAssetImage(),
                  child: Text("Save image from assets"),
                ),
                AnimatedOpacity(
                  opacity: _showResult ? 1.0 : 0.0,
                  duration: Duration(seconds: 1),
                  child: Text(
                    _resultText,
                    style: TextStyle(color: _resultColor),
                  ),
                )
              ],
            ),
            _progressIndictaor,
          ],
        ),
      ),
    );
  }

  Widget get _progressIndictaor {
    return _isLoading
        ? Container(
            child: Center(child: CircularProgressIndicator()),
            color: Color.fromRGBO(0, 0, 0, 0.3),
          )
        : Container();
  }

  void _startLoading() {
    setState(() {
      _isLoading = true;
    });
  }

  void _stopLoading() {
    setState(() {
      _isLoading = false;
    });
  }

  void _displayResult(bool success) {
    _showResult = true;
    if (success) {
      _displaySuccessMessage();
    } else {
      _displayErrorMessage();
    }
    Timer(Duration(seconds: 2), () {
      _hideResult();
    });
  }

  void _displaySuccessMessage() {
    setState(() {
      _resultText = "Images saved successfullty";
      _resultColor = Colors.green;
    });
  }

  void _displayErrorMessage() {
    setState(() {
      _resultText = "An error occurred while saving images";
      _resultColor = Colors.red;
    });
  }

  void _hideResult() {
    setState(() {
      _showResult = false;
    });
  }
}

Use this package as a library

1. Depend on it

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


dependencies:
  save_in_gallery: ^0.1.3

2. Install it

You can install packages from the command line:

with Flutter:


$ flutter pub get

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:save_in_gallery/save_in_gallery.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
85
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
100
Overall:
Weighted score of the above. [more]
92
Learn more about scoring.

We analyzed this package on Jul 8, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.8.4
  • pana: 0.13.14
  • Flutter: 1.17.5

Analysis suggestions

Package does not support Flutter platform linux

Because:

  • package:save_in_gallery/save_in_gallery.dart that declares support for platforms: android, ios

Package does not support Flutter platform macos

Because:

  • package:save_in_gallery/save_in_gallery.dart that declares support for platforms: android, ios

Package does not support Flutter platform web

Because:

  • package:save_in_gallery/save_in_gallery.dart that declares support for platforms: android, ios

Package does not support Flutter platform windows

Because:

  • package:save_in_gallery/save_in_gallery.dart that declares support for platforms: android, ios

Package not compatible with SDK dart

Because:

  • save_in_gallery that is a package requiring null.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.2.2 <3.0.0
flutter 0.0.0
Transitive dependencies
collection 1.14.12 1.14.13
meta 1.1.8 1.2.1
sky_engine 0.0.99
typed_data 1.1.6 1.2.0
vector_math 2.0.8
Dev dependencies
flutter_test