CameraX currently provides
View that displays a preview of the camera, while also providing methods to take pictures, control the camera, and query camera information.
CameraView clearly takes on more responsibilities than a
View should, as it participates in the
View hierarchy and displays content, while also owning camera resources that exist outside the scope and lifecycle of the
CameraView violates the separation of concerns principle, making it harder to guarantee its robustness in all corner cases. As a result, it will be marked as deprecated and removed before CameraX’s view artifact reaches Beta. It has been split up into two parts that you should use instead:
PreviewView which handles its view-related tasks, and
CameraController which handles the camera operations.
PreviewView has been available in CameraX’s view artifact for a while.
CameraController, however, was introduced recently in version alpha19. It’s a high-level, all-in-one API that provides a way to easily access and manipulate core camera features, including displaying a camera preview, taking a picture, and analyzing camera frames. It does so while matching the output of its use cases to the viewfinder’s preview, thus providing a “What You See Is What You Get” (WYSIWYG) experience, a highly requested feature by developers that makes CameraX’s usage very intuitive. It also takes care of initializing the camera and adapting its output to device rotation.
To offload the burden of starting, stopping, and closing the camera, CameraX also introduced
LifecycleCameraController, which offers all the convenience of
CameraController with the added benefit of binding the camera’s lifecycle to that of a
LifecycleOwner, typically the lifecycle of a
Activity. This allows the lifecycle’s state to control when the camera is opened, stopped, and closed.
CameraController is fairly simple, and can be done as follows:
The following sections list the mappings from
CameraController. You can use them to migrate from
CameraController provides a
ListenableFuture to monitor its initialization. It’s an asynchronous operation during which
CameraController initializes CameraX and binds its use cases. The benefit of using this
ListenableFuture is twofold:
- Once it successfully completes, you can allow your users to start interacting with the camera, for example by taking pictures and zooming in and out of the viewfinder.
- In case it fails, you can gracefully handle the error and communicate it to your users.
In case you aren’t familiar with
ListenableFuture: it wraps an asynchronous operation and allows you to attach a listener that’s invoked on its completion. In case the operation has already finished, the future returns immediately.
LifecycleCameraController ties control of the camera to a lifecycle. You must bind a valid
LifecycleOwner to the controller for it to be operational.
LifecycleCameraController provides an additional
unbind() method which allows you to prematurely close the camera before the lifecycle that it’s bound to comes to an end. This is useful in cases in which the camera isn’t integral to a screen and isn’t needed for its entire lifecycle. Alternatively, you can define your custom
LifecycleOwner to control when to close the camera, but
unbind() can be more convenient in some cases.
CameraController allows you to observe the camera’s zoom state via a
LiveData instance. This state becomes available once the camera is open, and holds both static information, like the maximum and minimum zoom ratios, and dynamic information, like the current zoom ratio. You can verify whether zoom is supported using the maximum zoom ratio as follows:
CameraController additionally provides methods to get and set linear zoom, which can vary between 0 (minimum zoom) and 1 (maximum zoom).
CameraController allows you to enable or disable pinch-to-zoom. When enabled,
CameraController handles pinch gestures on its attached
PreviewView to zoom the camera in and out.
CameraController provides similar methods as
CameraView to set and query the image capture’s flash mode, but unlike
CameraView, it allows observing changes in the camera’s torch state via a
LiveData instance, which emits
CameraView automatically acquires focus on any region of the viewfinder that is tapped,
CameraController provides more flexibility by allowing you to enable or disable tap-to-focus functionality. When enabled,
CameraController handles touch events on its attached
PreviewView by focusing the camera on tapped regions.
CameraController provides you with more control over which camera to use by allowing you to specify a
CameraSelector to select the camera it uses. This allows you to rotate between various cameras when toggling cameras, instead of only the default front and back cameras, which was a limitation of
CameraView.toggleCamera(). You can still implement this fairly easily, though, using
CameraController as follows.
Camera Use Cases
CameraController supports all of CameraX’s use cases:
ImageCapture, thus making it a more robust camera solution compared to
CameraView. It also matches the output of
ImageCapture to the preview’s display, thereby providing a WYSIWYG experience.
CameraController’s default state enables preview, image analysis, and image capture. The
Preview use case is always enabled, so you can choose the remaining use cases to enable or disable depending on your camera usage needs.
CameraView which wraps (and thus hides) a
PreviewView instance and forwards method calls to it,
CameraController is decoupled from
PreviewView. This means you have more control over the viewfinder, and can access and manipulate it directly.
CameraController supports the
ImageAnalysis use case. You can set and clear its
Analyzer, while also configuring its image-processing pipeline.
CameraController provides the same methods as
CameraView to take a picture, specify the image save destination, and provide the image capture callbacks.
One thing to note is that
CameraController mirrors an image captured with a front-facing camera, unless you disable this in the
OutputFileOptions’s metadata by calling
CameraViewis handling the responsibilities of both a view and a controller in the MVC sense, CameraX is deprecating it and splitting it into
PreviewViewand the newly introduced
CameraControllerhandles camera initialization, as well as the creation and configuration of its use cases.
CameraControllerprovides a WYSIWYG experience by matching the output of its use cases to
CameraControllerlistens to the device’s motion sensor to correctly rotate the output of its use cases.
CameraControlleradds support for the
ImageAnalysisuse case, making it a more robust camera solution that provides easy access to all of CameraX’s use cases.
CameraControllersupports all of
CameraView’s features and more, such as enabling and disabling tap-to-focus, getting and setting linear zoom, and observing dynamic camera information like the zoom and torch states.
CameraControllerthat binds the camera’s lifecycle to that of a
LifecycleOwner, typically the lifecycle of the UI.
Want more CameraX goodness? Check out: