1. Overview
CameraX is a Jetpack support library, if you are not familiar with Jetpack then you can imagine this is a collection of libraries, tools and guidelines to help developers develop applications easily with limited. Boring code, simple complex tasks. You can refer to Jetpack here
CameraX will help you build camera applications easily by providing APIs suitable for Android 5.0 devices (API 21). Compared to Camera2, using CameraX helps you not to worry about compatibility issues with devices.
Advantages when using CameraX:
- Easy to use
CameraX introduces a number of use cases that allow you to focus on the work to be done:
- Preview : display an image preview
- Image analysis : allows CPU buffer access for analysis to use machine learning algorithms like MLKit
- Image capture : capture and save images
- Consistency between devices
Camera management in the application is not easy such as: aspect ratio, orientation, rotation, preview size, high-resolution image size. But with CameraX, it will be much simpler,
- New experience
CameraX has an add-on called Extensions that allows you to access the features provided for the camera. Some of the features that this extension offers are: Portrait, HDR, Night, Beauty.
2. Camerax Architecture
Let’s explore the CameraX example:
1 2 3 4 5 6 7 8 9 | val preview <span class="token operator">=</span> Preview <span class="token punctuation">.</span> <span class="token function">Builder</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token function">build</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> val viewFinder <span class="token operator">:</span> PreviewView <span class="token operator">=</span> <span class="token function">findViewById</span> <span class="token punctuation">(</span> R <span class="token punctuation">.</span> id <span class="token punctuation">.</span> previewView <span class="token punctuation">)</span> <span class="token comment">// PreviewView has a built-in surface provider and is the recommended provider</span> preview <span class="token punctuation">.</span> <span class="token function">setSurfaceProvider</span> <span class="token punctuation">(</span> viewFinder <span class="token punctuation">.</span> previewSurfaceProvider <span class="token punctuation">)</span> <span class="token comment">// The use case is bound to an Android Lifecycle with the following code</span> cameraProvider <span class="token punctuation">.</span> <span class="token function">bindToLifecycle</span> <span class="token punctuation">(</span> lifecycleOwner <span class="token punctuation">,</span> cameraSelector <span class="token punctuation">,</span> preview <span class="token punctuation">)</span> |
CameraX is linked to the application life cycle using the bindToLifecycle () method. CameraX listens to the life cycle to decide when to turn on the camera, when to take a picture, when to turn off the camera. And use CameraX.unbindAll () when you want to unlink the life cycle.
- Config
CameraX automatically provides the specified feature of the device on which the application will be run, i.e. CameraX will automatically determine the best resolution to use if you do not provide the specified resolution or if the resolution Your installation is not supported on the device. The purpose of CameraX is to successfully initiate a session with the camera, which means CameraX will compromise the resolution and aspect ratio based on the device’s permission.
1 2 3 4 5 6 7 | val imageCapture = ImageCapture.Builder() .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY) .setTargetAspectRatio(screenAspectRatio) .setTargetRotation(rotation) .setTargetResolution(resolution) .build() |
3. Preview
To add a preview to the application, using the PreviewView , this view can crop, scale, rotate
- Config CameraXConfig.Provider
Implement CameraXConfig.Provider in the Application class
1 2 3 4 5 6 7 8 9 | <span class="token keyword">import</span> androidx <span class="token punctuation">.</span> camera <span class="token punctuation">.</span> camera2 <span class="token punctuation">.</span> Camera2Config <span class="token keyword">import</span> androidx <span class="token punctuation">.</span> camera <span class="token punctuation">.</span> core <span class="token punctuation">.</span> CameraXConfig <span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">MyCameraXApplication</span> <span class="token operator">:</span> <span class="token function">Application</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">,</span> CameraXConfig <span class="token punctuation">.</span> Provider <span class="token punctuation">{</span> override fun <span class="token function">getCameraXConfig</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">:</span> CameraXConfig <span class="token punctuation">{</span> <span class="token keyword">return</span> Camera2Config <span class="token punctuation">.</span> <span class="token function">defaultConfig</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
- Add PreviewView to the layout
1 2 3 4 5 6 | <span class="token operator"><</span> FrameLayout android <span class="token operator">:</span> id <span class="token operator">=</span> <span class="token string">"@+id/container"</span> <span class="token operator">></span> <span class="token operator"><</span> androidx <span class="token punctuation">.</span> camera <span class="token punctuation">.</span> view <span class="token punctuation">.</span> PreviewView android <span class="token operator">:</span> id <span class="token operator">=</span> <span class="token string">"@+id/preview_view"</span> <span class="token operator">/</span> <span class="token operator">></span> <span class="token operator"><</span> <span class="token operator">/</span> FrameLayout <span class="token operator">></span> |
- Request CameraProvider
1 2 3 4 5 6 7 8 9 10 | <span class="token keyword">import</span> androidx <span class="token punctuation">.</span> camera <span class="token punctuation">.</span> lifecycle <span class="token punctuation">.</span> ProcessCameraProvider <span class="token keyword">import</span> com <span class="token punctuation">.</span> google <span class="token punctuation">.</span> common <span class="token punctuation">.</span> util <span class="token punctuation">.</span> concurrent <span class="token punctuation">.</span> ListenableFuture <span class="token keyword">class</span> <span class="token class-name">MainActivity</span> <span class="token operator">:</span> <span class="token function">AppCompatActivity</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">private</span> lateinit var cameraProviderFuture <span class="token operator">:</span> ListenableFuture <span class="token generics function"><span class="token punctuation"><</span> ProcessCameraProvider <span class="token punctuation">></span></span> override fun <span class="token function">onCreate</span> <span class="token punctuation">(</span> savedInstanceState <span class="token operator">:</span> Bundle <span class="token operator">?</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> cameraProviderFuture <span class="token operator">=</span> ProcessCameraProvider <span class="token punctuation">.</span> <span class="token function">getInstance</span> <span class="token punctuation">(</span> <span class="token keyword">this</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
- Check CameraProvider
1 2 3 4 5 | cameraProviderFuture <span class="token punctuation">.</span> <span class="token function">addListener</span> <span class="token punctuation">(</span> Runnable <span class="token punctuation">{</span> val cameraProvider <span class="token operator">=</span> cameraProviderFuture <span class="token punctuation">.</span> <span class="token function">get</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token function">bindPreview</span> <span class="token punctuation">(</span> cameraProvider <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> ContextCompat <span class="token punctuation">.</span> <span class="token function">getMainExecutor</span> <span class="token punctuation">(</span> <span class="token keyword">this</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> |
- Select the camera and link to the lifecycle
Once CameraProvider has been successfully created and checked, perform the following steps:
- Create Preview and connect with PreviewView
- Specify the LensFacing camera option
- Associated with lifecycle
1 2 3 4 5 6 7 8 9 10 11 12 13 | fun <span class="token function">bindPreview</span> <span class="token punctuation">(</span> cameraProvider <span class="token operator">:</span> ProcessCameraProvider <span class="token punctuation">)</span> <span class="token punctuation">{</span> var preview <span class="token operator">:</span> Preview <span class="token operator">=</span> Preview <span class="token punctuation">.</span> <span class="token function">Builder</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token function">build</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> previewView <span class="token punctuation">.</span> <span class="token function">setSurfaceProvider</span> <span class="token punctuation">(</span> previewView <span class="token punctuation">.</span> previewSurfaceProvider <span class="token punctuation">)</span> var cameraSelector <span class="token operator">:</span> CameraSelector <span class="token operator">=</span> CameraSelector <span class="token punctuation">.</span> <span class="token function">Builder</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token function">requireLensFacing</span> <span class="token punctuation">(</span> CameraSelector <span class="token punctuation">.</span> LENS_FACING_BACK <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token function">build</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> cameraProvider <span class="token punctuation">.</span> <span class="token function">bindToLifecycle</span> <span class="token punctuation">(</span> <span class="token keyword">this</span> as LifecycleOwner <span class="token punctuation">,</span> cameraSelector <span class="token punctuation">,</span> preview <span class="token punctuation">)</span> <span class="token punctuation">}</span> |
4. Analyze Image
Image analysis provides CPU buffers to perform image analysis tasks using computer vision, machine learning.
1 2 3 4 5 6 7 8 9 10 11 12 | val imageAnalysis <span class="token operator">=</span> ImageAnalysis <span class="token punctuation">.</span> <span class="token function">Builder</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token function">setTargetResolution</span> <span class="token punctuation">(</span> <span class="token function">Size</span> <span class="token punctuation">(</span> <span class="token number">1280</span> <span class="token punctuation">,</span> <span class="token number">720</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token function">setBackpressureStrategy</span> <span class="token punctuation">(</span> ImageAnalysis <span class="token punctuation">.</span> STRATEGY_KEEP_ONLY_LATEST <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token function">build</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> imageAnalysis <span class="token punctuation">.</span> <span class="token function">setAnalyzer</span> <span class="token punctuation">(</span> executor <span class="token punctuation">,</span> ImageAnalysis <span class="token punctuation">.</span> Analyzer <span class="token punctuation">{</span> image <span class="token operator">-</span> <span class="token operator">></span> val rotationDegrees <span class="token operator">=</span> image <span class="token punctuation">.</span> imageInfo <span class="token punctuation">.</span> rotationDegrees <span class="token comment">// insert your code here.</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> cameraProvider <span class="token punctuation">.</span> <span class="token function">bindToLifecycle</span> <span class="token punctuation">(</span> <span class="token keyword">this</span> as LifecycleOwner <span class="token punctuation">,</span> cameraSelector <span class="token punctuation">,</span> imageAnalysis <span class="token punctuation">,</span> preview <span class="token punctuation">)</span> |
Image analysis can work in two modes: blocking and non-blocking.
The blocking mode is enabled using setBackpressureStrategy () with the value STRATEGY_BLOCK_PRODUCER. In this mode, the runtime receives frames from the camera in sequential order.
Non-blocking mode uses setBackpressureStrategy () with STRATEGY_KEEP_ONLY_LATEST value, this mode will only receive the last frame from the camera
After configuring the modes, use the setAnalyzer () method to use image analysis methods and don’t forget to bind to the Lifecycle.
5. Image Capture
After configuring the camera in the above steps, you can now capture the image and save it
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | fun <span class="token function">onClick</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> val outputFileOptions <span class="token operator">=</span> ImageCapture <span class="token punctuation">.</span> OutputFileOptions <span class="token punctuation">.</span> <span class="token function">Builder</span> <span class="token punctuation">(</span> <span class="token function">File</span> <span class="token punctuation">(</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> imageCapture <span class="token punctuation">.</span> <span class="token function">takePicture</span> <span class="token punctuation">(</span> outputFileOptions <span class="token punctuation">,</span> object <span class="token operator">:</span> ImageCapture <span class="token punctuation">.</span> OnImageSavedListener <span class="token punctuation">{</span> override fun <span class="token function">onError</span> <span class="token punctuation">(</span> error <span class="token operator">:</span> ImageCapture <span class="token punctuation">.</span> ImageCaptureError <span class="token punctuation">,</span> message <span class="token operator">:</span> String <span class="token punctuation">,</span> exc <span class="token operator">:</span> Throwable <span class="token operator">?</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// insert your code here.</span> <span class="token punctuation">}</span> override fun <span class="token function">onImageSaved</span> <span class="token punctuation">(</span> outputFileResults <span class="token operator">:</span> ImageCapture <span class="token punctuation">.</span> OutputFileResults <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// insert your code here.</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> |
The article here is also long enough, please make an appointment to read the next article I will write more about the awesome and extremely magical extensions of this CameraX such as HDR, Bokeh, …
Refer
https://developer.android.com/training/camerax
https://codelabs.developers.google.com/codelabs/camerax-getting-started/#0