Paramclasses Academy - Blog

Tutorials Details

←
Post 32 of 40
→

Flutter Camera, Permissions and Device Features: A Practical Guide

Flutter Camera, Permissions and Device Features: A Practical Guide

November 3, 2026

❖ Welcome to Param Classes!

Modern mobile applications use different device features to provide a better user experience. A camera app captures photos, a document scanning app scans certificates, and a profile management app allows users to upload their pictures.

Flutter provides packages that help developers access mobile device features such as cameras, images, location, microphone and other hardware capabilities.

In this tutorial, you will learn how to use the camera in Flutter, capture pictures, select images from the gallery and manage camera permissions.

We will build a simple Flutter Camera App where users can capture an image, preview it and select an existing image from their phone gallery.

✦ 1. Understanding Camera and Device Features

A smartphone contains different hardware and software features that applications can use.

Some common device features are:

  • Camera – Capture photos and videos.

  • Gallery – Select existing images.

  • Location – Get geographical coordinates.

  • Microphone – Record audio.

  • Storage – Access supported files.

  • Sensors – Detect device movement and orientation.

Flutter applications can access these features through plugins.

For this practical project, we will focus on camera and image selection.

✦ 2. Create a Flutter Project

First, create a new Flutter project.

Open Android Studio or VS Code and run:

flutter create flutter_camera_app

Move into the project directory:

cd flutter_camera_app

Open the project in your code editor.

✦ 3. Install Required Packages

We will use two Flutter packages.

1. camera

The camera package provides access to the device camera. It allows developers to display a camera preview and capture pictures.

2. image_picker

The image_picker package allows users to select images from their gallery or capture images using the camera through the platform's picker interface.

Run these commands:

flutter pub add camera
flutter pub add image_picker

Then run:

flutter pub get

Official package documentation:

✦ 4. Add Camera Permission for Android

Before using the camera, your application needs the appropriate permission.

Open:

android/app/src/main/AndroidManifest.xml

Add this permission above the <application> element:

<uses-permission android:name="android.permission.CAMERA"/>

If your app saves images to a custom location or uses other storage features, additional configuration may be required depending on the Android version and storage approach.

Important: Adding a permission to the manifest does not automatically grant it. The user must approve camera access when requested by the application.

✦ 5. Create a Camera Screen

Now open:

lib/main.dart

We will create a simple application with:

  • Camera preview

  • Capture photo button

  • Gallery selection button

  • Captured image preview

Use the following code:

import 'dart:io';

import 'package:flutter/material.dart';
import 'package:camera/camera.dart';
import 'package:image_picker/image_picker.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  final cameras = await availableCameras();

  runApp(MyApp(cameras: cameras));
}

class MyApp extends StatelessWidget {
  final List<CameraDescription> cameras;

  const MyApp({
    super.key,
    required this.cameras,
  });

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Flutter Camera App',
      theme: ThemeData(
        colorSchemeSeed: Colors.blue,
        useMaterial3: true,
      ),
      home: CameraScreen(cameras: cameras),
    );
  }
}

class CameraScreen extends StatefulWidget {
  final List<CameraDescription> cameras;

  const CameraScreen({
    super.key,
    required this.cameras,
  });

  @override
  State<CameraScreen> createState() => _CameraScreenState();
}

class _CameraScreenState extends State<CameraScreen> {
  CameraController? cameraController;

  File? selectedImage;

  bool isCameraReady = false;
  bool isTakingPicture = false;

  final ImagePicker picker = ImagePicker();

  @override
  void initState() {
    super.initState();
    initializeCamera();
  }

  Future<void> initializeCamera() async {
    if (widget.cameras.isEmpty) {
      return;
    }

    try {
      cameraController = CameraController(
        widget.cameras.first,
        ResolutionPreset.medium,
        enableAudio: false,
      );

      await cameraController!.initialize();

      if (!mounted) return;

      setState(() {
        isCameraReady = true;
      });
    } on CameraException catch (e) {
      debugPrint('Camera error: ${e.description}');
    }
  }

  Future<void> captureImage() async {
    if (cameraController == null ||
        !cameraController!.value.isInitialized ||
        isTakingPicture) {
      return;
    }

    setState(() {
      isTakingPicture = true;
    });

    try {
      final XFile image =
          await cameraController!.takePicture();

      if (!mounted) return;

      setState(() {
        selectedImage = File(image.path);
      });
    } on CameraException catch (e) {
      debugPrint('Capture error: ${e.description}');
    } finally {
      if (mounted) {
        setState(() {
          isTakingPicture = false;
        });
      }
    }
  }

  Future<void> selectFromGallery() async {
    try {
      final XFile? image = await picker.pickImage(
        source: ImageSource.gallery,
      );

      if (image == null) return;

      if (!mounted) return;

      setState(() {
        selectedImage = File(image.path);
      });
    } catch (e) {
      debugPrint('Gallery error: $e');
    }
  }

  @override
  void dispose() {
    cameraController?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter Camera App'),
        backgroundColor: Colors.blue,
        foregroundColor: Colors.white,
      ),

      body: SingleChildScrollView(
        child: Padding(
          padding: const EdgeInsets.all(16),

          child: Column(
            children: [
              if (isCameraReady &&
                  cameraController != null)
                AspectRatio(
                  aspectRatio:
                      cameraController!
                          .value.aspectRatio,
                  child: CameraPreview(cameraController!),
                )
              else
                Container(
                  height: 250,
                  color: Colors.black12,
                  alignment: Alignment.center,
                  child: Text(
                    widget.cameras.isEmpty
                        ? 'No camera available'
                        : 'Initializing Camera...',
                  ),
                ),

              const SizedBox(height: 20),

              ElevatedButton.icon(
                onPressed:
                    isCameraReady && !isTakingPicture
                        ? captureImage
                        : null,
                icon: const Icon(Icons.camera_alt),
                label: const Text('Capture Photo'),
              ),

              const SizedBox(height: 10),

              ElevatedButton.icon(
                onPressed: selectFromGallery,
                icon: const Icon(Icons.photo_library),
                label: const Text('Select From Gallery'),
              ),

              const SizedBox(height: 25),

              if (selectedImage != null) ...[
                const Text(
                  'Selected Image Preview',
                  style: TextStyle(
                    fontSize: 18,
                    fontWeight: FontWeight.bold,
                  ),
                ),

                const SizedBox(height: 10),

                Image.file(
                  selectedImage!,
                  height: 200,
                  fit: BoxFit.contain,
                ),
              ],
            ],
          ),
        ),
      ),
    );
  }
}

This example uses the camera package for a live camera preview and photo capture. The image_picker package provides gallery image selection.

✦ 6. Understand the Important Camera Code

Let's understand some important methods.

Initialize Camera

cameraController = CameraController(
  widget.cameras.first,
  ResolutionPreset.medium,
  enableAudio: false,
);

await cameraController!.initialize();

The CameraController manages the camera. The initialize() method prepares the camera for use.

Display Camera Preview

CameraPreview(cameraController!)

This widget displays the live camera preview on the screen.

Capture Photo

final XFile image =
    await cameraController!.takePicture();

This captures an image and returns an XFile containing the image path.

Select Image from Gallery

final XFile? image = await picker.pickImage(
  source: ImageSource.gallery,
);

This opens the image selection interface.

Display Image

Image.file(
  selectedImage!,
  height: 200,
)

This displays the selected image from its local file path.

✦ 7. Understand Camera Permissions

Mobile operating systems protect private device features through permissions.

For example, an application cannot access the camera without the required permission.

Common permission types include:

Device Feature Permission
Camera Camera access
Microphone Microphone access
Location Location access
Contacts Contacts access
Notifications Notification permission

When using a camera plugin, the plugin and platform configuration manage the relevant permission flow. Your application should handle cases where access is denied.

Permission Best Practices:

  • Explain why the camera is needed.

  • Request permission when the user starts a camera feature.

  • Handle permission denial gracefully.

  • Do not repeatedly request permission when it has been permanently denied.

  • Provide guidance to device settings when necessary.

✦ 8. Switch Between Front and Back Camera

Most smartphones have front and back cameras.

You can select a camera using its lens direction.

For example:

final cameras = await availableCameras();

final frontCamera = cameras.firstWhere(
  (camera) =>
      camera.lensDirection == CameraLensDirection.front,
);

You can then create a CameraController using frontCamera instead of widget.cameras.first.

In a complete application, check whether a front camera exists before selecting it.

✦ 9. Test Your Flutter Camera Application

Follow these steps:

  1. Connect an Android device with a working camera.

  2. Run your Flutter application.

  3. Grant camera permission when requested by the operating system.

  4. Check whether the live camera preview appears.

  5. Tap Capture Photo.

  6. Check the captured image preview.

  7. Tap Select From Gallery.

  8. Choose an existing image.

  9. Check whether the selected image appears.

Note: A real Android device is recommended for camera testing. Emulator camera support depends on the emulator configuration.

✦ 10. Common Camera Errors

Error 1: Camera Permission Denied

The user may have denied camera access. Handle this case and guide the user to app settings if permission is permanently denied.

Error 2: Camera Not Available

The device may not have a camera, or another application may be using it.

Error 3: Camera Preview Not Displaying

Check whether the camera controller has been initialized successfully.

Error 4: Image Not Displaying

Check the returned image path and confirm that the selected file still exists.

Error 5: Camera Resources Not Released

Always dispose of the camera controller when the screen is removed. This releases camera resources.

✦ 11. Other Useful Flutter Device Features

Once you understand camera access, you can explore other device features.

1. Location

Use Geolocator to retrieve geographical coordinates.

Package: https://pub.dev/packages/geolocator

2. File Selection

Use File Picker to select PDFs, documents and other supported files.

Package: https://pub.dev/packages/file_picker

3. Notifications

Use Firebase Cloud Messaging to receive push notifications.

Documentation: https://firebase.google.com/docs/cloud-messaging/flutter/client

4. Sensors

Use the Sensors Plus package to access supported device sensors.

Package: https://pub.dev/packages/sensors_plus

These packages allow Flutter developers to build applications that interact with smartphone hardware.

✦ 12. What You Learned

In this tutorial, you learned how to:

  • Create a Flutter camera project.

  • Install the camera and image picker packages.

  • Add Android camera permission.

  • Initialize a camera controller.

  • Display a live camera preview.

  • Capture photos.

  • Select images from the gallery.

  • Display selected images.

  • Understand device permission handling.

  • Switch between front and back cameras.

  • Release camera resources properly.

❖ Conclusion

Camera integration is an important feature in modern mobile applications. Flutter makes it possible to capture photos, display camera previews and select images from the gallery using simple packages.

You can use these concepts to develop profile photo upload systems, document scanning applications, product photography apps and many other real-world projects.

At Param Classes, we focus on practical programming lessons that help beginners understand application development step by step. Keep practising and try adding image upload functionality to this camera project.

Learn Today, Grow Tomorrow – Param Classes.

←
Post 32 of 40
→