Flutter Camera and Location Plugins
Phones carry cameras, GPS chips, and sensors that make apps feel alive. Flutter reaches these features through plugins. A plugin is a package that contains Dart code plus native Android and iOS code. Your app calls a simple Dart method, and the plugin talks to the hardware for you.
How Plugins Work
Your Dart code
│ calls pickImage()
▼
Plugin (Dart layer)
│ platform channel
▼
Native code (Kotlin on Android, Swift on iOS)
│
▼
Phone hardware: camera, GPS
Permissions: The User Decides
Cameras and locations are private. Android and iOS require every app to ask permission before it touches them. Users can refuse, and the app must keep working. Treat the permission prompt as a conversation: explain why the app needs access before the system dialog appears.
- Request only the permissions the feature needs.
- Ask at the moment the user taps the related button.
- Show a helpful message when the user declines.
- Publish a clear privacy policy that explains how the app handles camera images and location data.
Picking Photos with image_picker
The image_picker plugin opens the camera or the gallery and returns the chosen file.
flutter pub add image_picker
import 'dart:io';
import 'package:image_picker/image_picker.dart';
class PhotoScreen extends StatefulWidget {
@override
State<PhotoScreen> createState() => _PhotoScreenState();
}
class _PhotoScreenState extends State<PhotoScreen> {
File? _photo;
final ImagePicker _picker = ImagePicker();
Future<void> _takePhoto() async {
final XFile? picked = await _picker.pickImage(source: ImageSource.camera);
if (picked != null) {
setState(() {
_photo = File(picked.path);
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: _photo == null ? Text('No photo yet') : Image.file(_photo!),
),
floatingActionButton: FloatingActionButton(
onPressed: _takePhoto,
child: Icon(Icons.camera_alt),
),
);
}
}
Change ImageSource.camera to ImageSource.gallery to choose an existing picture. The method returns null when the user cancels, so always check before use.
Declaring Permissions
Native projects must describe why the app needs access.
Android
Open android/app/src/main/AndroidManifest.xml and add permission lines above the application tag:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
iOS
Open ios/Runner/Info.plist and add a plain-language reason for each permission:
<key>NSCameraUsageDescription</key>
<string>The camera lets you attach a photo to your note.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Your location shows nearby stores on the map.</string>
Apple rejects apps with vague or missing reasons.
Reading Location with geolocator
flutter pub add geolocator
A safe location request checks three things: the location service is on, the permission is granted, and the permission is not blocked forever.
import 'package:geolocator/geolocator.dart';
Future<Position?> getCurrentLocation() async {
bool serviceOn = await Geolocator.isLocationServiceEnabled();
if (!serviceOn) {
return null;
}
LocationPermission permission = await Geolocator.checkPermission();
if (permission == LocationPermission.denied) {
permission = await Geolocator.requestPermission();
}
if (permission == LocationPermission.denied ||
permission == LocationPermission.deniedForever) {
return null;
}
return Geolocator.getCurrentPosition();
}
Service on? ── no ──→ ask user to turn on GPS
│ yes
▼
Permission granted? ── no ──→ request it
│ yes │ refused
▼ ▼
Read position show a friendly message
Showing the Result
final pos = await getCurrentLocation();
if (pos != null) {
print('Latitude: ${pos.latitude}, Longitude: ${pos.longitude}');
}
Live Tracking with a Stream
The method Geolocator.getPositionStream() returns a stream of positions while the user moves. Pair it with StreamBuilder to update a screen. Stop the stream when the screen closes to save battery.
Camera Preview with the camera Plugin
The image_picker plugin opens the system camera. Apps that need a live preview, custom buttons, or video recording use the camera plugin. It exposes a CameraController and a CameraPreview widget. Always call controller.dispose() when the screen closes to release the camera for other apps.
Choosing Plugins Wisely
| Check | Why It Matters |
|---|---|
| Recent updates | Active maintenance means fewer bugs |
| Pub points and likes | Signals quality and popularity |
| Supported platforms | Confirms Android, iOS, and web coverage |
| Setup instructions | Native steps change between versions |
Read the plugin's installation page on pub.dev before you start, because native setup steps change often.
Respecting User Privacy
Photos and locations reveal personal details. Handle both with care. Collect data only when the feature needs it, store it securely, and delete it when it has served its purpose. Tell users in plain words what happens to their data, and give them a way to remove it. Both Google Play and the Apple App Store review how apps use sensitive permissions, and clear explanations speed up that review.
Practice Ideas
Build a photo note app that attaches one picture and the current coordinates to each note. Show a friendly message when the user declines either permission. Test the denied path by switching the permission off in device settings.
