---
name: android-camerax-pro
description: "Build camera features the modern way — Preview, ImageCapture, VideoCapture, ML Kit overlays. Production CameraX patterns: lifecycle binding, multi-use-case (preview + capture + analysis simultaneously), Concurrent Camera API, HDR, low-light boost, and the ML Kit overlay patterns for barcode/text/face detection."
license: MIT
---

# Android CameraX Pro

Production-grade CameraX patterns for Android engineers who are done fighting Camera2 boilerplate. This skill helps you wire up Preview, ImageCapture, VideoCapture, and ImageAnalysis against a single lifecycle, then layer ML Kit detection overlays on top — with the lifecycle, threading, and coordinate-mapping details that usually take a few painful release cycles to get right.

## When to use it

- You're adding a camera screen and want one correct lifecycle binding instead of leaked sessions on rotation.
- You need preview + photo capture + real-time analysis running at the same time (e.g. scan-a-barcode-while-previewing).
- You're drawing ML Kit results (barcodes, text blocks, face contours) and the boxes don't line up with the preview.
- You want HDR, low-light boost, or the Concurrent Camera API (front + back simultaneously) without guessing at device support.

## How it works

The core is `ProcessCameraProvider.getInstance(context)`, then `bindToLifecycle(lifecycleOwner, cameraSelector, ...useCases)`. You build use cases with their builders — `Preview.Builder`, `ImageCapture.Builder` (set `CAPTURE_MODE_MINIMIZE_LATENCY` or `MAXIMIZE_QUALITY`), and `VideoCapture.withOutput(Recorder)`. For analysis, `ImageAnalysis.Builder().setBackpressureStrategy(STRATEGY_KEEP_ONLY_LATEST)` feeds an `Analyzer` that hands the `ImageProxy` to ML Kit's `InputImage.fromMediaImage(image, rotationDegrees)`.

Capability gates use `CameraInfo`: check `ImageCapture.getImageCaptureCapabilities()` for HDR via `setDynamicRange`, `CameraInfo.isLowLightBoostSupported`, and `cameraProvider.getAvailableConcurrentCameraInfos()` before binding a `ConcurrentCamera`. Overlay alignment is handled with a `Matrix` mapping from analysis image space to view space (the same transform `MlKitAnalyzer` produces when you bind it directly to the controller).

## Usage

```kotlin
val provider = ProcessCameraProvider.getInstance(ctx).await()
val preview = Preview.Builder().build()
    .also { it.surfaceProvider = previewView.surfaceProvider }
val capture = ImageCapture.Builder()
    .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY).build()
val analysis = ImageAnalysis.Builder()
    .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST).build()
    .apply { setAnalyzer(executor, BarcodeAnalyzer(::onCodes)) }

provider.unbindAll()
provider.bindToLifecycle(owner, CameraSelector.DEFAULT_BACK_CAMERA,
    preview, capture, analysis)
```

Then ask: "add a face-contour overlay to my preview" or "make capture fall back when HDR isn't supported."

## Tips & gotchas

- Always call `unbindAll()` before rebinding; re-binding the same use case throws.
- In your analyzer, `imageProxy.close()` is mandatory — skip it and the pipeline silently stalls after a few frames.
- Pass `imageProxy.imageInfo.rotationDegrees` into `InputImage`; hardcoding 0 is the usual cause of "detection works in portrait only."
- Not every device allows preview + capture + analysis together. Check `isUseCasesCombinationSupported` rather than catching the bind exception.

## FAQ

**CameraX or the `camera-view` controller?** For most apps, `LifecycleCameraController` plus `PreviewView` is less code and gives you `MlKitAnalyzer` with automatic coordinate transforms. Drop to raw `CameraProvider` when you need fine-grained use-case control.

**Compose support?** Yes — wrap `PreviewView` in `AndroidView`, or use the `camera-compose` `CameraXViewfinder`. The binding logic is identical.

**Why is my video missing audio?** `Recorder` needs `withAudioEnabled()` plus the `RECORD_AUDIO` permission granted before `start()`.
