CameraX lifecycle, capture, analysis, rotation, and backpressure
CameraX models camera work as use cases:
Previewsupplies a display surface;ImageCaptureproduces a still image;ImageAnalysisexposes CPU-readable frames;VideoCapturerecords encoded media.
Bind only a hardware-supported combination to a LifecycleOwner.
val preview = Preview.Builder().build().also {
it.surfaceProvider = previewView.surfaceProvider
}
val capture = ImageCapture.Builder().build()
val analysis = ImageAnalysis.Builder()
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.build()
cameraProvider.unbindAll()
cameraProvider.bindToLifecycle(
lifecycleOwner,
CameraSelector.DEFAULT_BACK_CAMERA,
preview,
capture,
analysis,
)
Backpressure is a product decision
KEEP_ONLY_LATEST drops intermediate frames while analysis is busy—good for barcode scanning where only the newest view matters. BLOCK_PRODUCER queues up to configured depth and can block other bound use cases, including preview—appropriate only when every frame matters and processing keeps up.
analysis.setAnalyzer(executor) { image ->
try {
scanner.process(
image = image,
rotationDegrees = image.imageInfo.rotationDegrees,
)
} finally {
image.close() // mandatory, including errors
}
}
Do not retain ImageProxy beyond its processing ownership. Copy only necessary bounded data if downstream work outlives the callback.
Rotation has three meanings
- device/display rotation;
- use-case target rotation;
- buffer rotation metadata (
rotationDegrees).
Update target rotation when needed, including orientation-locked/multi-display cases. Use image metadata/EXIF when displaying saved output; do not blindly rotate pixels twice.
Coordinate transforms
Analysis coordinates may differ from PreviewView because of rotation, crop, aspect ratio, and scale type. Overlaying a detected barcode rectangle requires the camera transformation/mapping to preview coordinates—not simply multiplying by view width/height.
Capture state
Unbound -> Binding -> Ready -> Capturing -> Saving -> Saved
↘ Error / PermissionLost / CameraUnavailable
Disable duplicate capture while an operation is in flight or assign operation identity. Capture callbacks can arrive after UI navigation; keep file/domain persistence outside a destroyed screen and avoid leaking Activity references.
Device variation
Front/back/external lenses, flash, focus, zoom, resolution, concurrent use-case combinations, extensions, and camera availability differ. Query CameraInfo/capabilities, catch bind errors, select fallbacks, and test real low/mid/high-tier hardware.
Storage exhaustion, provider failure, process death, or asynchronous capture error can occur after the shutter UI. Mark content ready only from the final save callback and validate durable output.
Sources
Exercise
Build a document scanner design with preview, edge analysis, capture, perspective correction, rotation, low-light fallback, retake, process death during saving, and upload outbox integration.