We are very excited to share with everyone that CameraX is now available as Beta! We want to thank our entire developer community who made this possible. With this release you will find a camera API foundation that will remain unchanged and get better with time via bug and device compatibility fixes.

In addition to expanded testing, we have many apps using CameraX in production giving us the confidence to recommend developers to start experimenting and (if suitable) rolling out CameraX in production on the Play Store. We do expect to have some bugs and are committed to ensuring that your apps have the best possible camera experience. Should you need help please reach out to us for support via either the discussion mailing list or opening an issue.

In this blog post, we will provide a brief overview of CameraX Jetpack Library and share what’s new in Beta. Reaching beta status means that a Jetpack library is considered to be ready for production use, but may still contain some non-critical bugs.

For up-to-date resources, check out the documentation, review the official sample, and join our online developer community.

CameraX logo

CameraX recap

First, let’s do a very quick review of what CameraX is all about. If you are already familiar with CameraX, you can probably skip this section. You can also take a look at other resources like this Android Developer Summit session or its corresponding blog post.

Device compatibility

As a Jetpack library, CameraX is compatible not only with Android devices running API level 21 and above, but also with the great diversity of hardware devices no matter the form factor, camera configuration or device-implementation details.

Lifecycle awareness

A core property of CameraX is lifecycle awareness. Instead of having to manually open and close the camera, we simply bind our camera use cases to a lifecycle owner. When the associated lifecycle owner (activity, fragment, etc.) starts or stops, so does the camera.

CameraX use cases

The main use cases provided by CameraX that are part of the beta release are:

Preview : Used to display a viewfinder of what the camera is pointing at.

: Used to display a viewfinder of what the camera is pointing at. ImageAnalysis : Used to parse information from the camera stream.

: Used to parse information from the camera stream. ImageCapture: Used to capture a high-quality photo.

Portrait mode

What has changed in Beta?

A few things have changed since the last time we talked about CameraX, and they are captured within the documentation, the official sample, or our online developer community.

Initialization

CameraX must be explicitly initialized by developers via ProcessCameraProvider, it looks something like this:

val cameraProviderFuture: ListenableFuture<ProcessCameraProvider> =

ProcessCameraProvider.getInstance(context) // The listener will be triggered once the future’s value is ready

cameraProviderFuture.addListener(Runnable { // Camera provider is now guaranteed to be available

val cameraProvider = cameraProviderFuture.get()

…

}, executor)

Picking a camera

Choosing which camera will be used for our use cases is done via CameraSelector. This works by creating a CameraSelector object with a set of optional constraints, then CameraX will pick the most suitable camera available that fits those requirements:

val cameraSelector = CameraSelector.Builder()

.requireLensFacing(CameraSelector.LENS_FACING_BACK)

.build()

If you want a simple selector to pick either front or back facing, you can use the static fields CameraSelector.DEFAULT_BACK_CAMERA or CameraSelector.DEFAULT_FRONT_CAMERA.

Camera preview

Even though it is not technically part of the beta release, the view module is now in alpha08 and PreviewView is the recommended way of implementing camera preview. First, you add it to your XML layout:

<androidx.camera.view.PreviewView

android:layout_width=”match_parent”

android:layout_height=”match_parent”/>

Then make sure that your Preview use case is using the surface from PreviewView:

val preview: Preview = …

val viewFinder: PreviewView = … // for example findViewById()

preview.setSurfaceProvider(viewFinder.previewSurfaceProvider)

If you want to use your own surface (from TextureView , for example), then you must implement your own surface provider as well as making sure that you handle sizing and orientation appropriately, which can be tricky.

Camera controls

You can query and modify certain aspects of the camera, like focus, zoom, and flash using the camera object returned by CameraProcessProvider.bindToLifecycle(). For example, you can get a LiveData object with the latest camera states via the CameraInfo object like this:

val camera = cameraProvider.bindToLifecycle(…)

val zoomState: LiveData<ZoomState> = camera.cameraInfo.zoomState

val torchState: LiveData<Int> = camera.cameraInfo.torchState

Conversely, you can control those values with the corresponding CameraControl object:

val camera = cameraProvider.bindToLifecycle(…)

camera.cameraControl.enableTorch(true)

camera.cameraControl.setLinearZoom(0.5f)

camera.cameraControl.startFocusAndMetering(…)

What’s next?

We acknowledge that camera development is hard and are committed to making CameraX easier to use by (a) continued investment in the CameraX test suite (b) adding new devices into our automated test farm and (c) addressing internal and external bug reports. We encourage you to start using CameraX Beta and join us in improving camera on Android for all our users.

To learn more about CameraX, check out the documentation and the official sample, or join our online developer community. Stay tuned for future blog posts and updates!