4. CameraX 用例配置:Preview、ImageCapture、ImageAnalysis 的基本配置
CameraX 将相机功能抽象为三个核心用例(UseCase):Preview(实时预览)、ImageCapture(拍照)、ImageAnalysis(帧分析)。每个用例独立配置,生命周期由绑定的 LifecycleOwner 自动管理。本章从原理、关键 API 到完整配置步骤逐一展开,并给出常见错误与性能建议。
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。
调试技巧:在
查看 Logcat 中
CameraXConfig 中启用日志:CameraXConfig.Builder().setCameraExecutor(…) .setLogger(…) .build()查看 Logcat 中
CameraX 标签的输出,可快速定位绑定失败或配置冲突的原因。