Android相机框架实战项目:自定义相机应用从零搭建 - 第2节
2.1 CameraX 是什么?
CameraX 是 Google 推出的官方 Jetpack 相机库,旨在简化 Android 相机应用的开发。它封装了底层 Camera2 API 的复杂性,提供了一套易于使用、生命周期感知且向后兼容的接口。开发者无需关心设备碎片化问题,CameraX 会自动处理不同厂商、不同 Android 版本的差异。
核心优势: 减少约 70% 的相机样板代码,自动处理设备兼容性,内置生命周期管理。
2.2 CameraX 架构概览
CameraX 采用分层架构设计,核心思想是将相机功能抽象为独立的“用例”(UseCase),开发者通过组合这些用例来构建相机应用。
2.3 生命周期感知:自动绑定,无需手动管理
CameraX 与 LifecycleOwner(如 AppCompatActivity)深度集成。当你在 onCreate 中绑定相机后,CameraX 会自动响应以下生命周期事件:
| 生命周期事件 | CameraX 自动行为 |
|---|---|
onStart |
打开相机设备,开始预览 |
onResume |
恢复预览流,确保取景器实时更新 |
onPause |
暂停预览流,释放部分资源以降低功耗 |
onStop |
关闭相机设备,释放相机资源 |
onDestroy |
完全清理所有 CameraX 绑定资源 |
最佳实践: 在
onCreate 中一次性配置好所有用例,CameraX 会接管后续的生命周期管理。不要在 onResume 中重复绑定,这会导致不必要的性能开销。
2.4 三大核心用例详解
CameraX 提供了三个开箱即用的核心用例,覆盖了绝大多数相机应用场景。你可以同时绑定多个用例,它们会共享同一相机会话。
2.4.1 Preview(预览)
负责将相机传感器数据实时渲染到 PreviewView 上。你只需要配置分辨率、缩放比例等参数,CameraX 会自动处理 Surface 的创建和更新。
// 创建 Preview 用例
Preview preview = new Preview.Builder()
.setTargetResolution(new Size(1920, 1080))
.build();
// 将 PreviewView 与 Preview 用例绑定
preview.setSurfaceProvider(previewView.getSurfaceProvider());
2.4.2 ImageCapture(拍照)
提供拍照功能,支持 JPEG 格式输出,并内置了拍照前的自动对焦(AF)、自动曝光(AE)和自动白平衡(AWB)处理。你可以设置闪光灯模式、旋转角度等。
// 创建 ImageCapture 用例
ImageCapture imageCapture = new ImageCapture.Builder()
.setFlashMode(ImageCapture.FLASH_MODE_AUTO)
.setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
.build();
// 执行拍照
imageCapture.takePicture(
context,
outputFileOptions,
ContextCompat.getMainExecutor(context),
new ImageCapture.OnImageSavedCallback() {
@Override
public void onImageSaved(@NonNull ImageCapture.OutputFileResults output) {
// 照片已保存
}
@Override
public void onError(@NonNull ImageCaptureException exception) {
// 处理错误
}
});
2.4.3 ImageAnalysis(图像分析)
允许你访问原始相机帧数据(YUV_420_888 格式)进行实时处理,例如二维码扫描、人脸检测、物体识别等。你可以设置分析器的执行线程和帧率。
// 创建 ImageAnalysis 用例
ImageAnalysis imageAnalysis = new ImageAnalysis.Builder()
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.setTargetResolution(new Size(640, 480))
.build();
// 设置分析器
imageAnalysis.setAnalyzer(Executors.newSingleThreadExecutor(), image -> {
// 处理每一帧图像数据
// 注意:处理完成后必须调用 image.close() 释放资源
image.close();
});
2.5 用例组合与数据流
在实际应用中,这三个用例通常协同工作。下面的 SVG 图展示了从相机传感器到最终输出的完整数据流。
2.6 用例对比与选择
| 特性 | Preview | ImageCapture | ImageAnalysis |
|---|---|---|---|
| 主要用途 | 显示实时取景 | 拍摄高质量照片 | 实时帧数据处理 |
| 输出格式 | Surface(渲染到 View) | JPEG / ByteArray | ImageProxy(YUV_420_888) |
| 分辨率 | 通常匹配屏幕分辨率 | 最高可达传感器原生分辨率 | 建议使用较低分辨率(如 640x480) |
| 帧率 | 30fps(与屏幕刷新率同步) | 单次触发 | 可配置,通常 10-30fps |
| 资源消耗 | 中等(持续渲染) | 低(瞬时高负载) | 高(CPU 密集型处理) |
性能警告: ImageAnalysis 的回调运行在独立线程中,切勿在回调中执行耗时操作(如网络请求、大量文件 I/O)。如果处理时间超过帧间隔,会导致帧丢失或 ANR。建议使用
STRATEGY_KEEP_ONLY_LATEST 策略丢弃积压帧。
2.7 本章小结
CameraX 通过生命周期感知和用例抽象,大幅降低了 Android 相机开发的复杂度。你只需要关注业务逻辑:
- Preview 负责“看”到画面
- ImageCapture 负责“拍”下照片
- ImageAnalysis 负责“分析”每一帧