How to Pick Images from Gallery and Camera Using the Image Picker Flutter Package
Use the image_picker plugin to call ImagePicker().pickImage() with source: ImageSource.gallery or ImageSource.camera, which returns an XFile object containing the path to the selected or captured image.
To implement an image picker flutter solution, the official image_picker plugin (maintained within the flutter/flutter ecosystem) abstracts native Android and iOS APIs behind a unified Dart interface. The plugin handles platform-specific implementations—including permission requests, MIME type detection, and temporary file management—through method channels defined in image_picker.dart, allowing you to launch the camera or gallery with minimal boilerplate.
Installing the Image Picker Dependency
Add the image_picker package to your pubspec.yaml to access the core Dart API:
dependencies:
flutter:
sdk: flutter
image_picker: ^0.8.7+4
After running flutter pub get, the plugin automatically bundles the platform-specific implementations (image_picker_android, image_picker_ios, etc.) that communicate with Flutter through method channels.
Implementing Gallery and Camera Selection
The primary entry point is the ImagePicker class instantiated in your widget. Calling pickImage() with the appropriate ImageSource enum value launches the corresponding native UI.
Selecting the Image Source
Pass ImageSource.gallery to open the device photo library or ImageSource.camera to launch the native camera interface:
import 'package:image_picker/image_picker.dart';
final ImagePicker _picker = ImagePicker();
// Open gallery
final XFile? image = await _picker.pickImage(source: ImageSource.gallery);
// Launch camera
final XFile? photo = await _picker.pickImage(source: ImageSource.camera);
Complete Implementation with Error Handling
The following StatefulWidget demonstrates both sources, image constraints, and comprehensive error handling as implemented in the plugin’s architecture:
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:image_picker/image_picker.dart';
class ImagePickerDemo extends StatefulWidget {
const ImagePickerDemo({Key? key}) : super(key: key);
@override
_ImagePickerDemoState createState() => _ImagePickerDemoState();
}
class _ImagePickerDemoState extends State<ImagePickerDemo> {
XFile? _imageFile;
final ImagePicker _picker = ImagePicker();
Future<void> _pickImage(ImageSource source) async {
try {
final XFile? picked = await _picker.pickImage(
source: source,
maxWidth: 1080,
maxHeight: 1080,
imageQuality: 85,
);
// `picked` is null when the user cancels the picker.
setState(() => _imageFile = picked);
} on PlatformException catch (e) {
// Handles permission denial or other platform errors.
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Error: ${e.message}')),
);
} catch (e) {
// Any other unexpected errors.
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Unexpected error: $e')),
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Image Picker Demo')),
body: Column(
children: [
if (_imageFile != null)
Expanded(
child: Image.file(
File(_imageFile!.path),
fit: BoxFit.contain,
),
)
else
const Expanded(
child: Center(child: Text('No image selected')),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton.icon(
onPressed: () => _pickImage(ImageSource.gallery),
icon: const Icon(Icons.photo),
label: const Text('Gallery'),
),
ElevatedButton.icon(
onPressed: () => _pickImage(ImageSource.camera),
icon: const Icon(Icons.camera_alt),
label: const Text('Camera'),
),
],
),
const SizedBox(height: 16),
],
),
);
}
}
Understanding the Native Implementation
When you invoke pickImage(), the plugin serializes the request into a method-channel message (pickImage) sent to the platform-specific code.
Platform-Specific Bridges
- Android: The
image_picker_androidimplementation receives the method call and launches anIntentforACTION_PICK(gallery) orACTION_IMAGE_CAPTURE(camera), handling the native activity result. - iOS: The
image_picker_iosimplementation presents aUIImagePickerControllermodally and manages the delegate callbacks.
After user selection, the native side copies the image to a temporary directory and returns the file path to Dart, where the plugin wraps it in an XFile object.
Configuring Platform Permissions
While the image picker flutter plugin requests runtime permissions automatically, you must declare the required permissions in your platform configuration files.
Android Permissions
Add to android/app/src/main/AndroidManifest.xml:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
iOS Usage Descriptions
Add to ios/Runner/Info.plist:
<key>NSCameraUsageDescription</key>
<string>This app requires camera access to take photos</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>This app requires photo library access to select images</string>
Processing the XFile Result
The pickImage() method returns an XFile? that is null if the user cancels the operation. When valid, the XFile provides methods to access the image data:
path— Absolute path to the temporary file on the device.readAsBytes()— Returns aFuture<List<int>>of the file contents.openRead()— Returns aStream<List<int>>for memory-efficient processing.length()— Returns the file size in bytes.
if (_imageFile != null) {
final bytes = await _imageFile!.readAsBytes();
final size = await _imageFile!.length();
debugPrint('Image path: ${_imageFile!.path}, Size: $size bytes');
}
Summary
- The image picker flutter plugin abstracts native camera and gallery APIs through the
ImagePickerclass andpickImage()method defined inimage_picker.dart. - Specify
ImageSource.cameraorImageSource.galleryto control which native UI launches via method channels. - The plugin returns an
XFileobject containing a temporary file path, ornullif the user cancels. - Platform implementations in
image_picker_androidandimage_picker_ioshandle native permission flows and activity results. - Wrap picker calls in try-catch blocks to handle
PlatformExceptionerrors for permission denials.
Frequently Asked Questions
How do I restrict the image size or quality when picking from the gallery or camera?
Pass the maxWidth, maxHeight, and imageQuality parameters (0-100) to pickImage(). The native implementations in image_picker_android and image_picker_ios apply these constraints before returning the file path, reducing memory usage and upload sizes.
Why does pickImage() return null instead of an XFile?
The method returns null when the user dismisses the native picker without selecting an image or capturing a photo. This is expected behavior—always check for null before updating your UI or processing the file.
Do I need to request camera and storage permissions manually in my Dart code?
No, the image_picker plugin handles runtime permission requests internally when calling pickImage(). However, you must declare the required permissions in AndroidManifest.xml and Info.plist as shown above; otherwise, the app will crash when accessing protected resources.
Can I use the image picker flutter package on desktop platforms?
Yes, the plugin supports macOS through image_picker_macos, which utilizes NSOpenPanel for gallery selection and AVCapture for camera functionality. Windows and Linux support depends on the specific implementation versions available in the Flutter plugins repository.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →