2. Camera API 演进:Camera1 vs Camera2 vs CameraX 架构差异与选型策略

Android 相机 API 自诞生以来经历了三次重大迭代:Camera1(旧版 API)、Camera2(新版 API)和 CameraX(Jetpack 扩展库)。每一次演进都解决了前一代的核心痛点,同时也引入了新的架构复杂度。理解这三者的差异,是正确设计预览数据通路的前提。

选型黄金法则: 新项目优先 CameraX;需要精细控制(如 RAW、多摄像头同步)时选 Camera2;Camera1 仅用于兼容 Android 4.4 以下设备或极简快照场景。

2.1 架构演进总览

下图展示了三代 API 在应用层与 HAL 层之间的架构位置与核心组件差异:

Camera API 架构演进对比 Camera1(旧版 API) android.hardware.Camera setPreviewDisplay(SurfaceHolder) setPreviewCallback(byte[]) 阻塞式 Camera.open() 单线程预览 + 回调 无 BufferQueue 抽象 SurfaceView 强绑定 Camera2(新版 API) CameraManager + CameraDevice CameraCaptureSession Surface + BufferQueue 管道 异步 CaptureRequest 模型 多路 Surface 输出 支持 CameraCharacteristics 兼容 TextureView/SurfaceView CameraX(Jetpack) ProcessCameraProvider Preview / ImageCapture / ImageAnalysis UseCase 生命周期绑定 自动 CameraXConfig 设备兼容性适配层 PreviewView 封装 生命周期感知 + 旋转处理

2.2 核心差异对比表

对比维度 Camera1 Camera2 CameraX
引入版本 Android 1.0 (API 1) Android 5.0 (API 21) Android 5.0+ (Jetpack)
架构模型 阻塞式单线程 异步管道 + 状态机 UseCase 组合 + 生命周期绑定
Surface 绑定方式 setPreviewDisplay(SurfaceHolder) Session 创建时传入 Surface 列表 PreviewView 自动绑定 SurfaceProvider
预览数据回调 setPreviewCallback(byte[] NV21) ImageReader Surface + OnImageAvailableListener ImageAnalysis.Analyzer (YUV_420_888)
多路输出 不支持(需手动拷贝) 原生支持多 Surface 多 UseCase 自动合并
设备兼容性 差(厂商定制差异大) 中(需 LEVEL 判断) 好(内置兼容层)
生命周期管理 手动 onResume/onPause 手动 open/close 自动绑定 LifecycleOwner
旋转处理 手动 setDisplayOrientation 手动配置 SensorOrientation 自动旋转 + 预览适配

2.3 Camera1:历史包袱与局限

Camera1 是 Android 最早的相机 API,设计上采用阻塞式单线程模型。开发者通过 android.hardware.Camera 类直接操作硬件,预览流程如下:

  1. 打开相机: Camera.open() 是阻塞调用,可能耗时 100-500ms。
  2. 配置参数: 通过 Camera.Parameters 设置预览尺寸、帧率、对焦模式。
  3. 绑定 Surface: setPreviewDisplay(SurfaceHolder) 将预览画面输出到 SurfaceView。
  4. 启动预览: startPreview() 开始数据流。
  5. 获取帧数据: setPreviewCallback() 在预览线程中回调 byte[] 数据(NV21 格式)。
Camera1 致命缺陷: 预览回调运行在相机服务线程,不能做耗时操作;多路输出需要手动拷贝 NV21 数据,内存和性能开销极大;厂商定制导致 Parameters 行为不一致。

2.4 Camera2:异步管道与精细控制

Camera2 重新设计了相机架构,引入 CaptureRequest / CaptureResult 异步模型和 BufferQueue 数据通路。核心组件包括:

  • CameraManager: 系统服务代理,负责枚举摄像头、获取特性。
  • CameraDevice: 代表打开的相机设备,异步回调方式操作。
  • CameraCaptureSession: 管理 Surface 输出管道,支持多路复用。
  • CaptureRequest: 描述一次捕获的参数和目标 Surface 列表。
  • ImageReader: 提供 Surface 供 Session 写入,通过 OnImageAvailableListener 异步获取 Image 对象。

Camera2 预览数据通路的关键代码片段:

// 1. 获取 CameraManager
CameraManager manager = (CameraManager) getSystemService(CAMERA_SERVICE);

// 2. 打开相机(异步)
manager.openCamera(cameraId, new CameraDevice.StateCallback() {
    @Override
    public void onOpened(@NonNull CameraDevice camera) {
        // 3. 创建 CaptureSession
        List<Surface> outputs = new ArrayList<>();
        Surface previewSurface = surfaceView.getHolder().getSurface();
        outputs.add(previewSurface);

        // 可选:ImageReader 用于帧分析
        ImageReader reader = ImageReader.newInstance(width, height, ImageFormat.YUV_420_888, 2);
        reader.setOnImageAvailableListener(readerListener, backgroundHandler);
        outputs.add(reader.getSurface());

        camera.createCaptureSession(outputs, sessionCallback, backgroundHandler);
    }
}, backgroundHandler);

// 4. 发送重复预览请求
CaptureRequest.Builder builder = camera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
builder.addTarget(previewSurface);
session.setRepeatingRequest(builder.build(), null, backgroundHandler);
Camera2 优势: 原生多路 Surface 输出(预览 + 分析 + 拍照可同时进行);异步模型不阻塞 UI 线程;支持 CameraCharacteristics 查询硬件能力(如 RAW、HDR、光学防抖)。

2.5 CameraX:Jetpack 生态的易用性封装

CameraX 是 Google 在 2019 年推出的 Jetpack 相机库,本质上是 Camera2 的上层封装,但解决了 Camera2 最令人头疼的兼容性问题。其核心设计思想是 UseCase:

UseCase 功能 输出类型 典型场景
Preview 实时预览 PreviewView(Surface) 取景器显示
ImageCapture 拍照 JPEG / RAW 文件 快门拍照
ImageAnalysis 帧分析 ImageProxy(YUV_420_888) 二维码扫描、人脸检测
VideoCapture 视频录制 MediaRecorder / MediaCodec 录像

CameraX 预览绑定 Surface 的代码极为简洁:

// 1. 获取 ProcessCameraProvider
ProcessCameraProvider provider = ProcessCameraProvider.getInstance(context).get();

// 2. 绑定 Preview UseCase
Preview preview = new Preview.Builder()
    .setTargetResolution(new Size(1920, 1080))
    .build();

// 3. 设置 SurfaceProvider(自动绑定 PreviewView)
preview.setSurfaceProvider(previewView.getSurfaceProvider());

// 4. 绑定生命周期
Camera camera = provider.bindToLifecycle(
    lifecycleOwner,
    CameraSelector.DEFAULT_BACK_CAMERA,
    preview,
    imageAnalysis  // 可选:同时绑定分析 UseCase
);
CameraX 核心优势: 自动处理设备兼容性(内置 Camera2 兼容层);生命周期感知(自动释放相机资源);旋转和缩放自动适配;多 UseCase 自动合并 Surface 输出。

2.6 选型决策树

根据项目需求选择 Camera API 的决策流程:

Camera API 选型决策树 项目启动 最低支持 API 级别 < 21? Camera1(兼容模式) 仅限 Android 4.4 以下 需要精细控制? (RAW/多摄像头/高速连拍) Camera2 需处理兼容性 CameraX 推荐新项目首选 需要自定义 Surface 输出? CameraX + 自定义 SurfaceProvider Camera2 + 原生 Surface

2.7 性能与数据通路对比

从预览数据通路的视角,三代 API 在延迟、内存开销和灵活性上的差异:

指标 Camera1 Camera2 CameraX
预览启动延迟 200-500ms(阻塞) 100-300ms(异步) 100-250ms(异步 + 预热)
帧数据获取延迟 高(回调线程阻塞) 低(ImageReader 异步) 低(ImageProxy 封装)
多路输出内存 高(手动拷贝) 低(共享 BufferQueue) 低(自动合并 Surface)
兼容性适配成本 高(每个厂商单独适配) 中(需 LEVEL 判断 + 降级) 低(内置兼容层)
代码量(预览 + 分析) ~200 行 ~400 行 ~50 行
数据通路关键结论: Camera2 和 CameraX 都基于 BufferQueue 实现零拷贝 Surface 传递,但 CameraX 额外封装了线程调度和生命周期管理,减少了开发者对数据通路的手动干预。Camera1 的 byte[] 回调模式在 Android 10 之后已被标记为 deprecated。

2.8 迁移建议与兼容策略

  • 从 Camera1 迁移到 Camera2: 重点替换 Camera.open() 为 CameraManager.openCamera() 异步回调;将 setPreviewCallback 替换为 ImageReader + OnImageAvailableListener。
  • 从 Camera2 迁移到 CameraX: 将 CameraDevice / CaptureSession 管理替换为 ProcessCameraProvider.bindToLifecycle();将 ImageReader 替换为 ImageAnalysis UseCase。
  • 混合使用: CameraX 内部仍使用 Camera2 API,可通过 CameraXConfig 自定义底层 Camera2 参数(如 Camera2CameraImpl)。
  • 兼容性检测: 使用 CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL 判断设备 Camera2 支持级别(LEGACY / LIMITED / FULL / LEVEL_3)。
注意: CameraX 目前不支持多摄像头同时打开(如前后双摄同时预览),此类场景仍需回退到 Camera2 原生 API。CameraX 的 VideoCapture UseCase 在部分设备上存在帧率不稳定问题,生产环境建议充分测试。