3. Camera2核心组件:CameraManager、CameraDevice、CameraCaptureSession的角色与生命周期

Camera2 API 摒弃了 Camera1 的单体式设计,将相机控制抽象为三个核心组件:CameraManager(系统服务代理)、CameraDevice(相机设备句柄)和 CameraCaptureSession(捕获会话)。理解三者的角色划分与生命周期管理,是构建高性能预览通路的前提。

3.1 组件角色总览

下表从职责、创建方式、线程模型三个维度对比三个核心组件:

组件 核心职责 创建方式 线程模型
CameraManager 系统级相机服务代理,负责枚举相机、查询特性、打开设备 context.getSystemService(CAMERA_SERVICE) 主线程安全,回调在指定 Looper 线程
CameraDevice 单个物理相机的连接句柄,负责创建捕获会话、配置流 manager.openCamera(id, callback, handler) 回调在 Handler 线程,操作线程安全
CameraCaptureSession 数据通路运行时容器,管理 Surface 绑定与请求提交 device.createCaptureSession(config, callback, handler) 回调在 Handler 线程,请求提交需加锁
设计意图: CameraManager 是“发现者”,CameraDevice 是“连接者”,CameraCaptureSession 是“执行者”。三者职责分离,使得预览流配置与设备生命周期解耦。

3.2 生命周期状态机

每个组件都拥有明确的状态转换路径。下图展示了三者在一次完整预览启动过程中的状态流转:

Camera2 核心组件生命周期状态机 Camera2 核心组件生命周期状态机 CameraManager IDLE getSystemService() AVAILABLE openCamera() DISCONNECTED CameraDevice 关闭 CameraDevice INITIALIZED onOpened() 回调 CONFIGURING createCaptureSession() ACTIVE 会话创建成功 CLOSED close() 或异常断开 CaptureSession CREATING 配置验证中 READY onConfigured() ACTIVE setRepeatingRequest() CLOSED close() 或设备断开 openCamera() createSession()
关键生命周期规则:
  • CameraDevice 必须在 onOpened() 回调中创建会话,不能在构造函数或主线程直接调用。
  • CameraCaptureSession 的 onConfigured() 回调表示底层流管道已就绪,此时才能提交重复请求。
  • 任何组件调用 close() 后,其下层的所有子组件自动失效(如关闭 Device 会隐式关闭 Session)。

3.3 组件间协作流程

一次典型的预览启动,三个组件按以下顺序协作:

  1. CameraManager 查询与打开
    • 调用 getCameraIdList() 获取可用相机列表
    • 调用 getCameraCharacteristics(id) 获取传感器方向、输出尺寸等元数据
    • 调用 openCamera(id, callback, handler) 请求打开设备
  2. CameraDevice 配置与创建会话
    • 在 onOpened() 回调中构造 Surface 列表(预览 Surface + 拍照 Surface)
    • 调用 createCaptureSession(config, callback, handler) 提交配置
  3. CameraCaptureSession 提交请求
    • 在 onConfigured() 回调中构造 CaptureRequest(绑定目标 Surface)
    • 调用 setRepeatingRequest(request, callback, handler) 启动预览流
常见陷阱: 在 onOpened() 中直接调用 setRepeatingRequest() 会导致 IllegalStateException。必须先等待 onConfigured() 回调确认会话就绪。

3.4 生命周期管理最佳实践

在 Android Activity/Fragment 中管理这三个组件时,应遵循以下原则:

组件 创建时机 关闭时机 异常处理
CameraManager Application 或 Activity 创建时 无需主动关闭(系统服务) 捕获 CameraAccessException
CameraDevice onResume() 或 onStart() onPause() 中调用 close() 实现 onDisconnected() 回调
CameraCaptureSession onOpened() 回调中 onPause() 中先关闭会话再关闭设备 实现 onConfigureFailed() 回调
推荐模式: 使用 LifecycleObserver 或 CameraX 的 ProcessCameraProvider 自动管理生命周期。若使用原生 Camera2,建议在 ViewModel 中持有组件引用,避免旋转重建导致资源泄漏。

3.5 代码骨架示例

以下代码展示了三个组件在预览场景下的标准协作模式:

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

// 2. 打开 CameraDevice
manager.openCamera(cameraId, new CameraDevice.StateCallback() {
    @Override
    public void onOpened(@NonNull CameraDevice device) {
        // 3. 创建 CaptureSession
        List<Surface> outputs = Arrays.asList(previewSurface);
        device.createCaptureSession(outputs, new CameraCaptureSession.StateCallback() {
            @Override
            public void onConfigured(@NonNull CameraCaptureSession session) {
                // 4. 提交重复请求
                CaptureRequest request = device.createCaptureRequest(TEMPLATE_PREVIEW);
                request.addTarget(previewSurface);
                session.setRepeatingRequest(request.build(), null, null);
            }

            @Override
            public void onConfigureFailed(@NonNull CameraCaptureSession session) {
                Log.e("Camera2", "Session 配置失败");
            }
        }, backgroundHandler);
    }

    @Override
    public void onDisconnected(@NonNull CameraDevice device) {
        device.close();
    }

    @Override
    public void onError(@NonNull CameraDevice device, int error) {
        device.close();
    }
}, backgroundHandler);
生命周期顺序总结:
  1. CameraManager.openCamera() → 触发 onOpened()
  2. CameraDevice.createCaptureSession() → 触发 onConfigured()
  3. CameraCaptureSession.setRepeatingRequest() → 预览数据开始流动
  4. 关闭顺序严格反向:先 session.close(),再 device.close()