A Flutter plugin for iOS and Android for picking images from the image library, and taking new pictures with the camera.
Android | iOS | Linux | macOS | Web | Windows | |
---|---|---|---|---|---|---|
Support | SDK 21+ | iOS 11+ | Any | 10.14+ | See image_picker_for_web | Windows 10+ |
First, add image_picker
as a dependency in your pubspec.yaml file.
Starting with version 0.8.1 the iOS implementation uses PHPicker to pick (multiple) images on iOS 14 or higher. As a result of implementing PHPicker it becomes impossible to pick HEIC images on the iOS simulator in iOS 14+. This is a known issue. Please test this on a real device, or test with non-HEIC images until Apple solves this issue. 63426347 - Apple known issue
Add the following keys to your Info.plist file, located in <project root>/ios/Runner/Info.plist
:
NSPhotoLibraryUsageDescription
- describe why your app needs permission for the photo library. This is called Privacy - Photo Library Usage Description in the visual editor.false
for requestFullMetadata
, but App Store policy requires including the plist entry.NSCameraUsageDescription
- describe why your app needs access to the camera. This is called Privacy - Camera Usage Description in the visual editor.NSMicrophoneUsageDescription
- describe why your app needs access to the microphone, if you intend to record videos. This is called Privacy - Microphone Usage Description in the visual editor.Starting with version 0.8.1 the Android implementation support to pick (multiple) images on Android 4.3 or higher.
No configuration required - the plugin should work out of the box. It is however highly recommended to prepare for Android killing the application when low on memory. How to prepare for this is discussed in the Handling MainActivity destruction on Android section.
It is no longer required to add android:requestLegacyExternalStorage="true"
as an attribute to the <application>
tag in AndroidManifest.xml, as image_picker
has been updated to make use of scoped storage.
When under high memory pressure the Android system may kill the MainActivity of the application using the image_picker. On Android the image_picker makes use of the default Intent.ACTION_GET_CONTENT
or MediaStore.ACTION_IMAGE_CAPTURE
intents. This means that while the intent is executing the source application is moved to the background and becomes eligible for cleanup when the system is low on memory. When the intent finishes executing, Android will restart the application. Since the data is never returned to the original call use the ImagePicker.retrieveLostData()
method to retrieve the lost data. For example:
Future<void> getLostData() async { final ImagePicker picker = ImagePicker(); final LostDataResponse response = await picker.retrieveLostData(); if (response.isEmpty) { return; } final List<XFile>? files = response.files; if (files != null) { _handleLostFiles(files); } else { _handleError(response.exception); } }
This check should always be run at startup in order to detect and handle this case. Please refer to the example app for a more complete example of handling this flow.
Images and videos picked using the camera are saved to your application's local cache, and should therefore be expected to only be around temporarily. If you require your picked image to be stored permanently, it is your responsibility to move it to a more permanent location.
This package has optional Android Photo Picker functionality. Learn how to use it.
launchMode: singleInstance
Launching the image picker from an Activity
with launchMode: singleInstance
will always return RESULT_CANCELED
. In this launch mode, new activities are created in a separate Task. As activities cannot communicate between tasks, the image picker activity cannot send back its eventual result to the calling activity. To work around this problem, consider using launchMode: singleTask
instead.
This plugin currently has limited support for the three desktop platforms, serving as a wrapper around the file_selector
plugin with appropriate file type filters set. Selection modification options, such as max width and height, are not yet supported.
By default, ImageSource.camera
is not supported, since unlike on Android and iOS there is no system-provided UI for taking photos. However, the desktop implementations allow delegating to a camera handler by setting a cameraDelegate
before using image_picker
, such as in main()
:
import 'package:image_picker_platform_interface/image_picker_platform_interface.dart'; // ··· class MyCameraDelegate extends ImagePickerCameraDelegate { @override Future<XFile?> takePhoto( {ImagePickerCameraDelegateOptions options = const ImagePickerCameraDelegateOptions()}) async { return _takeAPhoto(options.preferredCameraDevice); } @override Future<XFile?> takeVideo( {ImagePickerCameraDelegateOptions options = const ImagePickerCameraDelegateOptions()}) async { return _takeAVideo(options.preferredCameraDevice); } } // ··· void setUpCameraDelegate() { final ImagePickerPlatform instance = ImagePickerPlatform.instance; if (instance is CameraDelegatingImagePickerPlatform) { instance.cameraDelegate = MyCameraDelegate(); } }
Once you have set a cameraDelegate
, image_picker
calls with ImageSource.camera
will work as normal, calling your provided delegate. We encourage the community to build packages that implement ImagePickerCameraDelegate
, to provide options for desktop camera UI.
Since the macOS implementation uses file_selector
, you will need to add a filesystem access [entitlement][https://docs.flutter.dev/platform-integration/macos/building#entitlements-and-the-app-sandbox]:
<key>com.apple.security.files.user-selected.read-only</key> <true/>
final ImagePicker picker = ImagePicker(); // Pick an image. final XFile? image = await picker.pickImage(source: ImageSource.gallery); // Capture a photo. final XFile? photo = await picker.pickImage(source: ImageSource.camera); // Pick a video. final XFile? galleryVideo = await picker.pickVideo(source: ImageSource.gallery); // Capture a video. final XFile? cameraVideo = await picker.pickVideo(source: ImageSource.camera); // Pick multiple images. final List<XFile> images = await picker.pickMultiImage(); // Pick singe image or video. final XFile? media = await picker.pickMedia(); // Pick multiple images and videos. final List<XFile> medias = await picker.pickMultipleMedia();
Starting with version 0.8.2 of the image_picker plugin, new methods were added that return XFile
instances (from the cross_file package) rather than the plugin's own PickedFile
instances. The previous methods were supported through 0.8.9, and removed in 1.0.0.
Old API | New API |
---|---|
PickedFile image = await _picker.getImage(...) | XFile image = await _picker.pickImage(...) |
List<PickedFile> images = await _picker.getMultiImage(...) | List<XFile> images = await _picker.pickMultiImage(...) |
PickedFile video = await _picker.getVideo(...) | XFile video = await _picker.pickVideo(...) |
LostData response = await _picker.getLostData() | LostDataResponse response = await _picker.retrieveLostData() |