Flutter: Taking Pictures with the Bloc Pattern

Flutter: Taking Pictures with the Bloc Pattern

We are going to see how we can use Bloc Design Pattern to take photos, making our app more robust and easily testable. Working with Flutter makes it really easy to build applications using the camera. I created a simple app named MyPhotos using Bloc to take some pictures and show them on the home page.

Working with flutter makes it really easy to build applications using the camera. Just by following the small example of the camera_plugin we can successfully take pictures with minimum lines of code.

However when the moment comes to cover the camera with tests, things get harder. In this article we are going to see how we can use Bloc Design Pattern to take photos, making our app more robust and easily testable.

For the purpose of this article, I created a simple app named MyPhotos (available on GitHub) using Bloc to take some pictures and show them on the home page:

Image for post

MyPhotos Demo

The app contains two blocs:

  • PhotosBloc, in charge of loading, adding and deleting the photos.
  • CameraBloc, in charge of the interactions with the CameraController.

We are going to focus on the CameraBloc as it is the purpose of this article.

Bloc Construction

CameraBloc events:

We only need 3 events to manage the camera.

  • CameraInitialized to start the camera (ask for permission and stream the camera).
  • CameraStopped to release the resources used by the camera.
  • CameraCaptured to take a picture.

CameraBloc states:

Depending on the events the bloc can emit 6 states:

  • CameraInitial for the initial state.
  • CameraReady when the camera is ready to take a picture.
  • CameraFailure when the camera failed to initialize.
  • CameraCaptureInProgress when the camera is taking a picture.
  • CameraCaptureSuccess when the camera successfully took a picture.
  • CameraCaptureFailure when an error happened during the capture.

CameraBloc logic:

To be able to mock the camera’s controller during the tests, we need to pass it through dependency injection. We could directly pass an instance of CameraController through the constructor, but I prefer to use a class with a method in charge to instantiate the controller to be able to catch any error inside of the bloc.

class CameraUtils {
  Future<CameraController> getCameraController(
      ResolutionPreset resolutionPreset,
      CameraLensDirection cameraLensDirection) async {
    final cameras = await availableCameras();
    final camera = cameras
        .firstWhere((camera) => camera.lensDirection == cameraLensDirection);

    return CameraController(camera, resolutionPreset, enableAudio: false);
  }

  Future<String> getPath() async => join(
        (await getTemporaryDirectory()).path,
        '${DateTime.now()}.png',
      );
}

By passing an object of CameraUtils we will then be able to mock all of its methods. In a more complex example we could add methods to compress, crop…

class CameraBloc extends Bloc<CameraEvent, CameraState> {
  final CameraUtils cameraUtils;
  final ResolutionPreset resolutionPreset;
  final CameraLensDirection cameraLensDirection;

  CameraController _controller;

  CameraBloc({
    @required this.cameraUtils,
    this.resolutionPreset = ResolutionPreset.high,
    this.cameraLensDirection = CameraLensDirection.back,
  }) : super(CameraInitial());
  // ...
}

When the user opens the camera’s screen, the event CameraInitialized is sent. The camera’s controller is created and initialized.

  Stream<CameraState> _mapCameraInitializedToState(CameraInitialized event) async* {
    try {
      _controller = await cameraUtils
          .getCameraController(resolutionPreset, cameraLensDirection);
      await _controller.initialize();
      yield CameraReady();
    } on CameraException catch (error) {
      _controller?.dispose();
      yield CameraFailure(error: error.description);
    } catch (error) {
      yield CameraFailure(error: error.toString());
    }
  }

If an error occurred when selecting a camera (or if there is no camera) the second catch will handle the exception and emits CameraFailure .

By calling _controller.initialize() the plugin automatically checks if the permissions are granted and if not, opens a pop-up to ask for the permissions.

  • If the user denies the permission, the method throws a CameraException and the bloc emits CameraFailure.
  • If the user accepts, the bloc emits CameraReady.

flutter mobile-apps programming developer web-development

Bootstrap 5 Complete Course with Examples

Bootstrap 5 Tutorial - Bootstrap 5 Crash Course for Beginners

Nest.JS Tutorial for Beginners

Hello Vue 3: A First Look at Vue 3 and the Composition API

Building a simple Applications with Vue 3

Deno Crash Course: Explore Deno and Create a full REST API with Deno

How to Build a Real-time Chat App with Deno and WebSockets

Convert HTML to Markdown Online

HTML entity encoder decoder Online

How long does it take to develop/build an app?

This article covers A-Z about the mobile and web app development process and answers your question on how long does it take to develop/build an app.

Top Mobile App Developers & Leading App Development Companies in UK

Profusely examined top Mobile App Development companies in UK with ratings & reviews to help find the best Mobile App Development solution providers.

Top 25 Flutter Mobile App Templates in 2020

Flutter has been booming worldwide from the past few years. While there are many popular mobile app development technologies out there, Flutter has managed to leave its mark in the mobile application development world. In this article, we’ve curated the best Flutter app templates available on the market as of July 2020.

Mobile App Development North Carolina

Mobile App Development North Carolina In the era of globalization, technology has forced the businesses and industries to jump into the space of competition. Technology has both tangible and intangible benefits that help businesses from different ind...

Top 7 Mobile App Development Companies in Delhi NCR

Looking for a Mobile app development company in Delhi NCR? Here it a list of top mobile app development companies in Delhi for Android & iOS app Development.