Take a Picture using Flutter Camera

Navin Kumar
4 min readNov 16, 2019

--

Intro

Flutter mainly provides two plugins to implement camera functionality to your app,

  1. camera
  2. image_picker

Most of the blogs covers only about image_picker plugin, 90% percent will go with image_picker only, so i came up with camera plugin, ok first lets see the differents between them,

  • camera plugin allows you to integrate the camera feature within your app as a Widget, where you can customise the widget.
  • image_picker will launch camera application to take photo and gallery application to pick image, then return taken/selected image as aFile.

Hope you are clear with these plugins, Ok Lets implement camera plugin to our Flutter app.

Add dependencies

  • Add below dependency in pubspec.yaml file, under dependencies:
dependencies:
flutter:
sdk: flutter
camera:
path_provider:
path:

- iOS

Add two rows to the ios/Runner/Info.plist:

<key>NSCameraUsageDescription</key>
<string>Enable myApp to access your camera to capture your photo</string>
<key>NSMicrophoneUsageDescription</key>
<string>Enable myApp to access mic to record your voice</string>

- Android

Change the minimum Android sdk version to 21 (or higher) in your android/app/build.gradle file.

minSdkVersion 21
  • Now add header file import ‘package:camera/camera.dart’;

Initialize Camera

  • first we need to initialize camera on initState(),
CameraController _controller;
Future<void> _initializeControllerFuture;
isCameraReady = false;
showCapturedPhoto = false;
var ImagePath;
@override
void initState() {
super.initState();
_initializeCamera();

}
Future<void> _initializeCamera() async {
final cameras = await availableCameras();
final firstCamera = cameras.first;
_controller = CameraController(firstCamera,ResolutionPreset.high);
_initializeControllerFuture = _controller.initialize();
if (!mounted) {
return;
}
setState(() {
isCameraReady = true;
});
}
  • availableCameras() will return list of avalaible cameras in the device, first camera from list will be passed to cameraController.
_controller = CameraController(firstCamera,ResolutionPreset.high);
  • cameraController controlls the camera functionality, firstCamera and ResolutionPreset as a parameter, we can set ResolutionPreset as high, medium, low, max, ultraHigh, veryHigh, values.
  • Then Initialize the controller , which returns Future.
_initializeControllerFuture = _controller.initialize();
  • now set isCameraReady as true and update the state.

- Android

  • In Android, when app goes to background (onPause() )android core will automatically dispose the camera list, so while resuming the app, it will be freezed and cant accessible.
  • So that we need to initailse the camera on onResume() also
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.resumed) {
_controller != null
? _initializeControllerFuture = _controller.initialize()
: null; //on pause camera is disposed, so we need to call again "issue is only for android"
}
}

Display CameraPreview

  • Use the CameraPreview widget from the camera package to display a preview of the camera’s feed.
final size = MediaQuery.of(context).size;
final deviceRatio = size.width / size.height
FutureBuilder<void>(
future: _initializeControllerFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
// If the Future is complete, display the preview.
return Transform.scale(
scale: _controller.value.aspectRatio / deviceRatio,
child: Center(
child: AspectRatio(
aspectRatio: _controller.value.aspectRatio,
child: CameraPreview(_controller), //cameraPreview
),
));
} else {
return Center(
child:
CircularProgressIndicator()); // Otherwise, display a loading indicator.
}
},
),
  • CameraPreview is wrapped with Transform widget to fit perfect to all device ratio without stretching.
  • _initializeControllerFuture will returns on future, So FutureBuilder is used.
  • Then builder builds the CameraPreview Widget once future is returned, if not CircularProgressIndicator() will be shown until camera is ready.
  • pass _controller as parameter of CameraPreview(_controller).

Take a picture with the CameraController

  • create a Button that takes a picture using the CameraController when a user taps on the button call onCaptureButtonPressed() method,
void onCaptureButtonPressed() async {  //on camera button press
try {

final path = join(
(await getTemporaryDirectory()).path, //Temporary path
'$pageStatus${DateTime.now()}.png',
);
ImagePath = path;
await _controller.takePicture(path); //take photo

setState(() {
showCapturedPhoto = true;
});
} catch (e) {
print(e);
}
}
  • To take a picture we should provide a path to the _controller, where the taken photo want to be stored.
  • getTemporaryDirectory() method returns available tempory path, update this path with timeStamp and extension of the file(.png or .jpg).
  • _controller.takePicture(path) will capture the photo and store the photo in given path.

Show the taken picture with an Image widget

Center(child: Image.file(File(ImagePath)));
  • Taken photo is displayed by Image widget.

Dispose controller

  • Finally dont forget to dispose camera _controller
@override
void dispose() {
// TODO: implement dispose
_controller?.dispose();
super.dispose();
}

Issues

- Android

  • On Android while asking camera permission at first time, app will be crashed, this due to some technical issue on camera plugin, Dont worry i found a solution for this,if this issue occurs please follow this solution.
  • You should modify some code inside flutter camera package.
..GoTo flutter/.pub-cache/hosted/pub.dartlang.org/camera-0.5.5+1/android/src/main/java/io/flutter/plugins/camera/Camera.java

Add below code on the line 424

public void startPreview() throws CameraAccessException {
if (pictureImageReader != null) //add this line as
createCaptureSession(CameraDevice.TEMPLATE_PREVIEW, pictureImageReader.getSurface());
}

solution link: https://github.com/flutter/flutter/issues/19595#issuecomment-540402580

Wrapping Up

Wow great 🎉, In this blog we have learned about how to take photo and display taken photo using Flutter camera plugin and also handled possible issues.Hope this blog is helpfull.

This article helped you? Long press on the 👏 button as long as you can.

I got something wrong? Mention it in the comments. I would love to improve.

I am NavinKumar, Android and Flutter developer. You can find me on Linkedin or stalk me on GitHub.

--

--

Navin Kumar
Navin Kumar

Written by Navin Kumar

Lead Application Developer @IBM

Responses (9)