CameraX: Getting Started

Learn how to implement camera features on Android using CameraX library By Tino Balint.

Leave a rating/review
Download materials
Save for later
Share

The camera is central to the mobile device experience, with many popular apps using it in some way. As a mobile developer, you’ll need to know how to integrate the camera into your apps. However, you’ll find that coding for the camera is hard work. You need to account for variations due to different versions of Android running on different devices, and edge cases tied to those differences.

You’ll have hours of coding ahead… unless you use CameraX!

CameraX is a new Jetpack library that simplifies the process of integrating the device camera into your Android app. Just picture all the time you’ll save!

In this tutorial, you’ll make an app that takes and stores photos using CameraX. The app will show the a camera preview in the bottom half of the screen and the most recent photo in the top half. You’ll also add a toolbar to save photos or add special effects.

By creating this app, you’ll learn how to:

  • Present a camera preview.
  • Access the camera to take photos.
  • Store the photos in memory or in a file.
  • Provide options for different special effects.
Note: This tutorial assumes you have previous experience developing for Android in Kotlin. If you’re unfamiliar with Kotlin, take a look at Kotlin for Android: An Introduction. If you’re also new to Android development, check out our Getting Started with Android tutorials.

You’ll start building your app in no time; first, you need to know more about CameraX.

What Is CameraX?

CameraX is a part of the growing Jetpack support library. It has backward compatibility down to Android API 21. It replaces Camera2 while supporting all the same devices — without the need for device-specific code!

Caution: CameraX is still in alpha, and is not considered ready for use in production apps.

The library provides abstractions for some helpful use cases, which are used to complete a specific task. The primary three are:

  • Preview
  • Image analysis
  • Image capture

Also of note, CameraX brings life to vendor extensions, which are features that display special effects on some devices. CameraX lets you add extensions to your app with just a few lines of code. Currently, the supported effects are:

  • Portrait
  • Bokeh
  • Night Mode
  • Beauty
  • HDR

Enough talk, you’re ready to build!

Getting Started

Click on the Download Materials button at the top or bottom of the page to access the begin and end projects for this tutorial.

Next, open Android Studio. From the welcome screen, select Open an existing Android Studio project. If you already have Android Studio open, click File ▸ New ▸ Import Project. Either way, select the top-level project folder for the begin project.

You’ll want to take a moment to familiarize yourself with the code that you’ll find in the begin project.

Pre-Built Kotlin Classes and Dependencies

Open the main package, com.raywenderlich.android.photosession. You’ll see six Kotlin classes:

  • ExtensionFeature.kt: An enum class that you’ll use to apply vendor extensions.
  • FileUtils.kt and FileUtilsImpl.kt: The interface and implementation for creating files and folders. You’ll use these to store images to a file.
  • ImagePopupView.kt: A class for displaying images as a pop-up. You’ll use this to view an image in full-screen mode.
  • PhotoActivity.kt: The main class for this tutorial, where you’ll write all camera-related code.
  • SplashActivity.kt: The class for displaying the splash screen of the app.

Also, notice that the app uses two CameraX dependencies, which you can see in the build.gradle file of the app module:

  • androidx.camera:camera-core
  • androidx.camera:camera-extensions

The core dependency consists of helper classes for:

  • Binding and unbinding the camera to the lifecycle.
  • Creating use cases like image preview or image capture.
  • Changing lens facing.

The core dependency gives you everything you need to support basic camera features.

The extensions dependency provides a way to apply vendor extensions like Night mode.

Note: Access to vendor extensions is currently limited to extensions dependency version 1.0.0-alpha03 or lower.

Now that you have a good overview of the key files for this project, it’s time to build and run the app. Your device will ask for permission to access the camera. After you accept the requested permissions, you’ll see a screen like this:

Screenshot of app's opening view

Familiarizing Yourself With the App Screen

The app’s main screen has a top and bottom half and a toolbar at the top. You’ll use the lower half to display the preview and the top half to show the most recent photo.

Notice that you already have a Save Image switch and a drop-down menu on the toolbar. Neither of these does anything now, but you’ll fix that soon!

The Save Image switch and drop-down menu

Creating a Camera Preview

To create a camera preview, you need to have a view that can display it. To do this, you’ll use TextureView.

Open activity_photo.xml and find a view at the bottom of the file with the id previewView. Change the view type to TextureView and delete the line that sets the background to black.

After those changes, your code should look like this:

  <TextureView
    android:id="@+id/previewView"
    android:layout_width="0dp"
    android:layout_height="0dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/takenImage" />

TextureView allows you to stream media content, like videos, which is exactly what you need to display a camera preview.

Next, you need a way to start the camera programmatically.

To implement this, open PhotoActivity.kt and add this new method to the class:

  private fun startCamera() {
    // 1
    CameraX.unbindAll()

    // 2
    val preview = createPreviewUseCase()

    preview.setOnPreviewOutputUpdateListener {
      // 3
      val parent = previewView.parent as ViewGroup
      parent.removeView(previewView)
      parent.addView(previewView, 0)

      previewView.surfaceTexture = it.surfaceTexture

      // 4
      updateTransform()
    }

    // 5
    imageCapture = createCaptureUseCase()

    // 6
    CameraX.bindToLifecycle(this, preview, imageCapture)
  }

Android Studio will show you compile errors with the above code, you’ll fix that in a moment. First, take a look at what you’re doing in startCamera:

  1. Unbind all use cases from the app lifecycle. This closes all currently open cameras and allows you to add your own use cases when you start the camera.
  2. Create a preview use case object. You haven’t added this method yet, you’ll do so in the next section.
  3. Set a listener that receives the data from the camera. When new data arrives, you release the previous TextureView and add a new one.
  4. Call updateTransform which sets the latest transformation to the TextureView. You haven’t added this method yet, you’ll do so in the next section.
  5. Create an image capture use case and bind the camera to the lifecycle. This binding controls the opening, starting, stopping and closing of the camera. You haven’t added this method yet, you’ll do so in the next section.
  6. Bind the three use cases to the camera lifecycle. This creates a camera session for them.

Next, you’ll add the missing implementations for createPreviewUseCase, updateTransform and createCaptureUseCase, starting with createPreviewUseCase.