Android相机框架实战项目:自定义相机应用从零搭建 - 第2节

2.1 CameraX 是什么?

CameraX 是 Google 推出的官方 Jetpack 相机库,旨在简化 Android 相机应用的开发。它封装了底层 Camera2 API 的复杂性,提供了一套易于使用、生命周期感知且向后兼容的接口。开发者无需关心设备碎片化问题,CameraX 会自动处理不同厂商、不同 Android 版本的差异。

核心优势: 减少约 70% 的相机样板代码,自动处理设备兼容性,内置生命周期管理。

2.2 CameraX 架构概览

CameraX 采用分层架构设计,核心思想是将相机功能抽象为独立的“用例”(UseCase),开发者通过组合这些用例来构建相机应用。

CameraX 分层架构图 应用层(你的 Activity / Fragment) 用例层(UseCase) Preview(预览) ImageCapture(拍照) ImageAnalysis(分析) 架构层(生命周期管理 + 设备适配) Camera2 API / 硬件抽象层(HAL)

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 图展示了从相机传感器到最终输出的完整数据流。

CameraX 用例数据流 相机传感器 Preview → PreviewView 显示 ImageCapture → JPEG 文件保存 ImageAnalysis → 帧数据回调 实时取景画面 (用户可见) 照片文件 (存储到磁盘) 分析结果 (回调给应用层) 关键说明 三个用例共享同一相机会话,同时运行互不干扰。ImageAnalysis 帧率通常低于 Preview。

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 负责“分析”每一帧