Android CameraX: Control and Query the Camera.

Husayn Hakeem
ProAndroidDev
Published in
5 min readNov 4, 2019

--

Introduction

Since its announcement and Alpha launch during this year’s Google I/O, there’s been a lot of excitement around CameraX, which is part of the Jetpack suite of libraries that aim to help developers build high quality apps easier. This post takes a step back from CameraX’s use cases, and goes over a couple of APIs that allow querying and controlling the camera.

If you’re new to CameraX or would like a refresher, check out this article.

Control the Camera

An API that allows you to control the camera directly, which in consequence affects the output of all bound use cases. CameraControl can be used to configure the camera’s zoom, exposure compensation, focus and metering and enabling or disabling the torch (if the camera supports it).

CameraControl can immediately be used after getting a Camera instance. Yet the operations it provides are asynchronous, and uses the ListenableFuture API to provide callbacks for the operation’s success or failure.

Query the Camera

An API that allows querying the camera to retrieve information about it. It provides the following information:

  • Zoom state: Wraps information about the current zoom ratio and linear zoom, as well as the min and max zoom values the camera supports.
  • Torch state and flash availability: CameraInfo provides the state of the camera’s torch, which is either on or off, and allows querying whether the camera supports flash.
  • Exposure state: Provides information about the camera’s exposure compensation, such as its index, range and step. The exposure compensation index and step define the camera’s exposure value as follows:
Exposure Value = Exposure Index * Exposure Step
  • Sensor rotation: CameraInfo provides the camera’s sensor rotation in degrees both relative to the device’s natural orientation (Portrait in general, but can also be landscape for wide device, like tablets) and relative to a given rotation.

CameraInfo provides most of the above information wrapped in LiveData, this allows you to continually observe their changes. If you only need the current value of one of them, you can use LiveData.getValue().

Get a CameraInfo instance

Tap-To-Focus

Autofocus is provided by default when using CameraX, but you can also manually specify the region the camera should focus on. This can be done with the help of the MeteringPointFactory class, which allows converting coordinates from a Surface (e.g. the preview Surface) into a MeteringPoint with corresponding camera sensor coordinates.

Tap-to-focus is dependent on a viewfinder. CameraX’s recommended viewfinder API, PreviewView provides a MeteringPointFactory out of the box which allows converting UI coordinates into camera sensor coordinates. You can use it to focus on tapped regions on the viewfinder.

Set up tap to focus

A couple of things are happening here.

  • An OnTouchListener is attached to the camera’s viewfinder, where only events of type ACTION_UP are handled. This event is received at the end of the tap gesture, once the pointer (e.g. the finger) is raised off the screen.
  • Using the coordinates of the tap, a MeteringPoint is created using the MeteringPointFactory from PreviewView. This factory takes in a set of preview coordinates, and creates a MeteringPoint that specifies a region in sensor coordinates for focusing and/or metering. This conversion takes into account the device’s orientation and any transformations that are applied to the camera preview such as cropping, translation and rotation.
  • A FocusMeteringAction is then created in order to configure and trigger a focus and/or metering action, this action takes in one or multiple focus/metering areas, and optionally MeteringModes that specify how these areas are used for 3A (auto focus, auto exposure, auto white balancing) regions.
  • The FocusMeteringAction is then passed to CameraControl in order to initiate the focus and metering action. Since this is an asynchronous operation, a ListenableFuture is returned. You can use it to be notified when the focus and metering action finishes successfully or fails. You can also use this as a signal if you’re displaying a focus animation, such as fading in, displaying then fading out a focus ring around the focus region.

Pinch-To-Zoom

CameraX allows you to enable pinch-to-zoom, where the camera zooms in and out depending on how the user pinches the viewfinder. The implementation is straightforward, and requires attaching a ScaleGestureDetector to the viewfinder.

Below is an example demonstrating pinch-to-zoom with PreviewView.

Set up pinch to zoom

In the snippet above:

  • An OnTouchListener is attached to the viewfinder. Each incoming event is passed to a ScaleGestureDetector.
  • A ScaleGestureDetector is created using a context and an OnGestureDetectedListener.
  • Inside the OnScaleGestureListener is where the camera’s zoom ratio is updated. The current camera zoom ratio is retrieved using CameraInfo, and then multiplied by the gesture’s scale delta, which represents by how much the scale has changed, and depends on the pinch gesture. The result is passed to CameraControl.setZoomRatio(), which updates both the zoom ratio and linear zoom value, as thus changes the output of the preview (and any other bound use cases).

Zoom Slider

CameraX provides a way to enable zooming in and out using a slider, where the zoom changes linearly between the min zoom and max zoom, represented by 0 and 1 respectively.

Set up a zoom slider

In the snippet above, a SeekBar is used as a slider, its value ranges from 0 to 100. CameraControl.setZoomPercentage() expects a -float- value between 0 and 1. Calling this method updates the preview and both the zoom ratio and percentage used by the camera.

Conclusion

In summary:

  • Control the camera independently of the use cases using the high level CameraControl class. Any changes made through CameraControl, such as updating the zoom ratio, affects the output of all the bound use cases.
  • Query camera related information and observe their changes using CameraInfo. It allows retrieving the camera’s zoom ratio, torch state, and much more.
  • Have more control over focus regions by implementing tap-to-focus, it’s simple to sett up using CameraX’s recommender viewfinder, PreviewView.
  • Zoom in and out of the camera by either implementing pinch-to-zoom or using a zoom slider.

Want more CameraX goodness? Check out:

For more on Java, Kotlin and Android, follow me to get notified when I write new posts, or let’s connect on Github and Twitter!

--

--