4. CameraX 用例配置:Preview、ImageCapture、ImageAnalysis 的基本配置

CameraX 将相机功能抽象为三个核心用例(UseCase):Preview(实时预览)、ImageCapture(拍照)、ImageAnalysis(帧分析)。每个用例独立配置,生命周期由绑定的 LifecycleOwner 自动管理。本章从原理、关键 API 到完整配置步骤逐一展开,并给出常见错误与性能建议。

CameraX 用例绑定流程 LifecycleOwner CameraProvider Preview 实时取景 ImageCapture 拍照输出 ImageAnalysis 帧数据分析 Camera 说明 三个用例共享一个 CameraProvider,通过 bindToLifecycle() 同时绑定到同一个 LifecycleOwner。 用例一旦绑定,生命周期自动跟随 Activity/Fragment 的 start/stop/resume。 每个 UseCase 通过 Builder 模式构造,配置项包括分辨率、帧率、输出格式等。

4.1 Preview 用例配置

Preview 提供实时取景画面,需要将 PreviewView 嵌入布局,或通过 Composable 版的 AndroidView 包裹。核心配置项包括分辨率、镜头选择(前置/后置)、以及 SurfaceProvider 的绑定。

关键 API:Preview.Builder → setTargetResolution() → build();setSurfaceProvider() 将渲染目标传给 CameraX。
// Kotlin 示例:配置 Preview 用例
val preview = Preview.Builder()
    .setTargetResolution(Size(1280, 720))
    .build()

preview.setSurfaceProvider(previewView.surfaceProvider)

4.2 ImageCapture 用例配置

ImageCapture 用于拍摄静态照片,支持 JPEG / PNG 格式,可自定义闪光灯模式、旋转方向、输出文件路径。拍照时通过 takePicture() 方法触发,输出到 ImageCapture.OnImageSavedCallback 或 OnImageCapturedCallback。

// Kotlin 示例:配置 ImageCapture 用例
val imageCapture = ImageCapture.Builder()
    .setCaptureMode(ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY)
    .setFlashMode(ImageCapture.FLASH_MODE_AUTO)
    .setTargetRotation(Surface.ROTATION_0)
    .build()

// 触发拍照
imageCapture.takePicture(
    context,
    contentResolver,
    ImageCapture.OutputFileOptions.Builder(photoFile).build(),
    object : ImageCapture.OnImageSavedCallback {
        override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
            // 照片已保存到文件
        }
        override fun onError(exception: ImageCaptureException) {
            // 处理错误
        }
    }
)
常见错误:takePicture() 必须在绑定后才能调用;若 LifecycleOwner 处于非活跃状态,会抛出 CameraXException。建议在回调中添加状态检查。

4.3 ImageAnalysis 用例配置

ImageAnalysis 将每一帧以 ImageProxy 形式传递给自定义 analyzer。常用配置:分辨率、输出格式(YUV_420_888 / RGB)、帧率限制、背景执行线程。适用于条码扫描、人脸检测、物体识别等实时分析场景。

// Kotlin 示例:配置 ImageAnalysis 用例
val imageAnalysis = ImageAnalysis.Builder()
    .setTargetResolution(Size(640, 480))
    .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
    .setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_YUV_420_888)
    .build()

imageAnalysis.setAnalyzer(executor, ImageAnalysis.Analyzer { imageProxy ->
    // 处理帧数据,注意需要调用 imageProxy.close() 释放资源
    val image = imageProxy.image
    // 分析逻辑…
    imageProxy.close()
})
性能要点:STRATEGY_KEEP_ONLY_LATEST 可避免帧堆积;若分析速度跟不上帧率,CameraX 会自动丢弃旧帧。分析器中务必及时调用 imageProxy.close(),否则会导致管线阻塞。

4.4 用例配置对比

特性 Preview ImageCapture ImageAnalysis
UseCase 类 Preview ImageCapture ImageAnalysis
输出形式 实时画面(Surface) 静态文件 / Bitmap 帧数据(ImageProxy)
核心方法 setSurfaceProvider() takePicture() setAnalyzer()
关键 Builder 配置 目标分辨率 捕获模式、闪光灯、旋转 背压策略、输出格式

4.5 绑定到 CameraProvider

三个用例需要统一调用 cameraProvider.bindToLifecycle() 进行绑定。生命周期所有者(Activity/Fragment)的 onResume / onPause 会自动控制相机启动与停止。

// 获取 cameraProvider(假设已通过 ProcessCameraProvider.getInstance 异步获取)
val camera: Camera = cameraProvider.bindToLifecycle(
    lifecycleOwner,
    CameraSelector.DEFAULT_BACK_CAMERA,
    preview,        // Preview 用例
    imageCapture,   // ImageCapture 用例
    imageAnalysis   // ImageAnalysis 用例
)
部署注意:bindToLifecycle() 每次调用会解绑所有之前绑定的用例并重新绑定;若需动态切换用例组合,应使用 camera.unbindAll() 或 camera.bindToLifecycle() 替换。同一 CameraProvider 不支持同时绑定两个相同类型的 UseCase 到同一个 LifecycleOwner。

4.6 常见错误与稳定性建议

  • 重复绑定:多次调用 bindToLifecycle() 而未先 unbind() 会导致资源泄漏或异常。解决方案:在绑定新组合前,调用 cameraProvider.unbindAll()。
  • SurfaceProvider 未及时设置:Preview 的渲染目标必须在绑定之前或之后立即设置,否则预览黑屏。最佳实践:在 onResume() 中设置。
  • 帧分析堆积:若 ImageAnalysis 分析器处理时间超过帧间隔,可改用 STRATEGY_BLOCK_PRODUCER 以降低帧率,或提高线程池并行度。
  • 配置不兼容:某些分辨率、帧率组合在某些设备上不支持,应通过 CameraInfo 查询支持的范围。
  • 权限缺失:CAMERA 权限必须在绑定之前获取;若在运行时被收回,CameraX 2.5+ 会抛出 CameraStateException,建议监听 Camera.StateCallback。
调试技巧:在 CameraXConfig 中启用日志:
CameraXConfig.Builder().setCameraExecutor(…) .setLogger(…) .build()
查看 Logcat 中 CameraX 标签的输出,可快速定位绑定失败或配置冲突的原因。