CameraX is supposed to be the "easy" camera API, but developers still run into the dreaded "Black Preview" screen. This usually isn't a bug in the library, but a mismatch in lifecycle or surface binding.

SurfaceProvider Binding

Ensure you're binding your Preview use case to the PreviewView correctly. If you call setSurfaceProvider too late or on the wrong thread, the surface won't initialize, resulting in a black screen.

Correct Preview Setup val preview = Preview.Builder().build()
preview.setSurfaceProvider(previewView.surfaceProvider)

Handling Aspect Ratio

A black screen can also occur if the system can't find a resolution that matches your requested aspect ratio. Instead of forcing a specific resolution, use setTargetAspectRatio to let CameraX choose the best fit for the device hardware.

Resilient Aspect Ratio val imageCapture = ImageCapture.Builder()
.setTargetAspectRatio(AspectRatio.RATIO_4_3)
.build()

The Golden Rule

Always unbind all use cases before re-binding them (e.g., during a camera switch). If you try to bind multiple camera instances to the same provider, the system will prioritize the first one, leaving the second one blank.

Lifecycle Re-binding cameraProvider.unbindAll()
cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, preview, imageCapture)

Summary

CameraX is lifecycle-aware, but you still need to manage your surface providers and aspect ratios. Clear your use cases before re-binding, and your previews will always be bright!