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

CheckWhy It Matters
Recent updatesActive maintenance means fewer bugs
Pub points and likesSignals quality and popularity
Supported platformsConfirms Android, iOS, and web coverage
Setup instructionsNative 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.