Using the Camera on Flutter

See how to integrate the device camera into your Flutter app for iOS and Android. By Sagar Suri.

Leave a rating/review
Download materials
Save for later
Share
You are currently viewing page 2 of 2 of this article. Click here to view the first page.

Displaying the Camera Preview

From this point you’ll need to be on a physical device. Run the project and you should see the following screen:

Camera preview

Amazing! You’ve just integrated the camera feature into your app!

But as you can see, there is no way to switch between the front and back camera, and if you press the capture button nothing happens. You’ll implement those features next.

Switching Cameras

Update _cameraTogglesRowWidget() to look as follows:

Widget _cameraTogglesRowWidget() {
  if (cameras == null || cameras.isEmpty) {
    return Spacer();
  }

  CameraDescription selectedCamera = cameras[selectedCameraIdx];
  CameraLensDirection lensDirection = selectedCamera.lensDirection;

  return Expanded(
    child: Align(
      alignment: Alignment.centerLeft,
      child: FlatButton.icon(
          onPressed: _onSwitchCamera,
          icon: Icon(_getCameraLensIcon(lensDirection)),
          label: Text(
              "${lensDirection.toString().substring(lensDirection.toString().indexOf('.') + 1)}")),
    ),
  );
}

In the above code, you are just showing an icon to the user which indicates the currently selected camera (front or back). On pressing the FlatButton you can toggle between front and back camera.

Now add the _getCameraLensIcon() method:

IconData _getCameraLensIcon(CameraLensDirection direction) {
  switch (direction) {
    case CameraLensDirection.back:
      return Icons.camera_rear;
    case CameraLensDirection.front:
      return Icons.camera_front;
    case CameraLensDirection.external:
      return Icons.camera;
    default:
      return Icons.device_unknown;
  }
}

_getCameraLensIcon() just returns a specific icon based on the camera selected.

Next, add the logic to toggle between the front and back camera. Create the method _onSwitchCamera():

void _onSwitchCamera() {
  selectedCameraIdx =
  selectedCameraIdx < cameras.length - 1 ? selectedCameraIdx + 1 : 0;
  CameraDescription selectedCamera = cameras[selectedCameraIdx];
  _initCameraController(selectedCamera);
}

In the above code, you are just changing the index, i.e. 0 for the back camera and 1 for the front camera. You are creating a new CameraDescription which will hold the camera object based on the updated index and then again initialize the CameraController object by calling _initCameraController().

Build and run the app to your device. Tap the icon at the bottom-left corner of the screen to toggle between the front and back camera. The screens should look as follows:

back camera

front camera

Taking a Picture

It’s time you start taking some awesome images using this camera app you’ve built!

Update the _onCapturePressed() to look as follows:

void _onCapturePressed(context) async {
  try {
    // 1
    final path = join(
      (await getTemporaryDirectory()).path,
      '${DateTime.now()}.png',
    );
    // 2
    await controller.takePicture(path);
    // 3
    Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => PreviewImageScreen(imagePath: path),
      ),
    );
  } catch (e) {
    print(e);
  }
}

You’ll see some errors at this point. You need to import the appropriate packages to make the errors go away. Click on each red line and use option+return or Alt+Enter to import the packages.

The above code step-by-step is as follows:

  1. join(..) will take different paths and join them to make a final path. For example: p.join('path', 'to', 'foo'); // -> 'path/to/foo'
  2. takePicture(path) will capture a raw image and write it to the path provided as an argument.
  3. After the picture is saved successfully to the specified path, you navigate to PreviewImageScreen to preview the image and share it with your friends.

Run the app and you will be able to take a picture, which will navigate to the PreviewScreen:

Preview screen

 Sharing the Image

If you click on the Share Button you will be presented with a Bottomsheet Dialog through which you can share the image you have just clicked.

Share screen

Open the preview_screen.dart file in order to see the code behind the share button.

The getBytesFromFile() method converts the image file into ByteData:

Future<ByteData> getBytesFromFile() async {
  Uint8List bytes = File(widget.imagePath).readAsBytesSync() as Uint8List;
  return ByteData.view(bytes.buffer);
}

The onPressed handler for the share button calls getBytesFromFile().

onPressed: () {
  getBytesFromFile().then((bytes) {
    Share.file('Share via:', basename(widget.imagePath),
        bytes.buffer.asUint8List(), 'image/png');
  });
},

After that call returns, the bytes from the file are passed to the file() method of Share class. The Share class is a part of esys_flutter_share plugin which you already added in the starter project.

You’ve successfully integrated the camera, and it’s time to play around with the app you just created. Take some amazing pictures and share them with your friends to demonstrate your photography skills!

Happy camera face

Where to Go From Here?

Check out the final completed project by clicking the Download Materials button at the top of bottom of the tutorial.

You can read more about using a camera with Flutter in the official Flutter documentation.

You can explore more about the various plugins we just used in this tutorial:

Try adding them to other Flutter projects by yourself.

I hope you enjoyed this tutorial on integrating the camera into your Flutter app! Feel free to share your feedback, findings or ask any questions in the comments below or in the forums.