When to use Image Picker
The **Image Picker** package is a lightweight, cross‑platform plugin that enables Flutter applications to access the native image library on Android and iOS, as well as launch the device camera for on‑the‑fly photo capture. By abstracting the underlying platform APIs, it lets developers work with a single, idiomatic Dart interface while still delivering a native‑looking experience for end users. Whether you are building a social feed, a profile editor, or a document scanner, Image Picker provides a reliable bridge between Flutter UI code and the device's media capabilities.
When to use Image Picker? The package shines in scenarios where you need a quick, user‑friendly way to obtain photos without building a custom camera UI. It is ideal for forms that require a profile picture, chat applications that allow image sharing, or e‑commerce apps where sellers upload product photos. Because the plugin returns a `XFile` object, you can seamlessly integrate it with other libraries such as `path_provider`, `firebase_storage`, or any HTTP client for uploading to a backend. The simplicity of the API also makes it a perfect teaching tool for beginners learning how to handle permissions, asynchronous calls, and file handling in Flutter.
From an architectural standpoint, Image Picker sits at the edge of your app's data flow. In a clean‑architecture or MVVM setup, the plugin is typically called from a repository or a use‑case class, keeping UI widgets free of platform‑specific logic. For state‑management solutions like Provider, Riverpod, or Bloc, you can emit a state change once the image is selected, allowing the UI to react instantly. The returned `XFile` can be stored in a temporary directory, cached, or uploaded directly, giving you flexibility to decide where the image lives in your domain layer. This separation ensures that the plugin does not become a hidden dependency in your presentation layer.
Setting up Image Picker is straightforward, but there are a few platform‑specific steps you must not overlook. After adding the dependency with `flutter pub add image_picker`, Android projects need the `READ_EXTERNAL_STORAGE` and `CAMERA` permissions declared in `AndroidManifest.xml`, and iOS projects require `NSPhotoLibraryUsageDescription` and `NSCameraUsageDescription` keys in the `Info.plist`. Starting with Android 13, you may also need to request the new `READ_MEDIA_IMAGES` permission. The package handles runtime permission requests on both platforms, but you should still test edge cases such as denied permissions or devices without a camera to avoid crashes in production.
In production environments, consider the performance and security implications of handling raw image files. Large photos can quickly consume memory, so it is advisable to downscale images before displaying or uploading them. The `image_picker` API includes a `maxWidth`, `maxHeight`, and `imageQuality` parameter that lets you control the size and compression level at the time of selection. Additionally, always validate the file type and size on the server side, as client‑side checks can be bypassed. For apps that need more advanced editing capabilities—such as cropping, rotating, or applying filters—pair Image Picker with a dedicated image‑editing package rather than extending its core functionality.
Overall, Image Picker offers a balanced mix of simplicity, reliability, and native performance. Its small footprint and clear documentation make it a go‑to choice for most Flutter projects that need to interact with the device's photo library or camera. By following the setup notes, respecting platform permissions, and handling image data responsibly, developers can deliver a smooth and secure image‑selection experience across Android and iOS devices.
Pros
- simple API
- native performance
- supports both gallery and camera
- configurable image size and quality
- well‑documented
Watch outs
- no built‑in editing tools
- limited to mobile platforms
- requires manual permission handling
Setup notes
Add the dependency with: ``` flutter pub add image_picker ``` **Android**: Open `android/app/src/main/AndroidManifest.xml` and add: ```xml <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!-- For Android 13+ --> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /> ``` **iOS**: Open `ios/Runner/Info.plist` and insert: ```xml <key>NSCameraUsageDescription</key> <string>We need access to the camera to let you take photos.</string> <key>NSPhotoLibraryUsageDescription</key> <string>We need access to your photo library to select images.</string> ``` Run `flutter pub get` and rebuild the app. The plugin works with Flutter 3.0+ and requires a minimum Android SDK of 21 and iOS 11.0.
Supports Android (API 21+) and iOS (11.0+). Requires runtime permission handling for camera and storage. Works with Flutter stable channel 3.0 and later. Not compatible with web or desktop out of the box.
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
class PhotoPicker extends StatefulWidget {
const PhotoPicker({Key? key}) : super(key: key);
@override
State<PhotoPicker> createState() => _PhotoPickerState();
}
class _PhotoPickerState extends State<PhotoPicker> {
XFile? _image;
final ImagePicker _picker = ImagePicker();
Future<void> _pickFromGallery() async {
final XFile? image = await _picker.pickImage(
source: ImageSource.gallery,
maxWidth: 800,
imageQuality: 80,
);
setState(() => _image = image);
}
Future<void> _captureWithCamera() async {
final XFile? photo = await _picker.pickImage(
source: ImageSource.camera,
maxWidth: 800,
imageQuality: 80,
);
setState(() => _image = photo);
}
@override
Widget build(BuildContext context) {
return Column(
children: [
if (_image != null) Image.file(File(_image!.path)),
ElevatedButton(onPressed: _pickFromGallery, child: const Text('Gallery')),
ElevatedButton(onPressed: _captureWithCamera, child: const Text('Camera')),
],
);
}
}