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 生命周期状态机
每个组件都拥有明确的状态转换路径。下图展示了三者在一次完整预览启动过程中的状态流转:
关键生命周期规则:
- CameraDevice 必须在
onOpened()回调中创建会话,不能在构造函数或主线程直接调用。 - CameraCaptureSession 的
onConfigured()回调表示底层流管道已就绪,此时才能提交重复请求。 - 任何组件调用
close()后,其下层的所有子组件自动失效(如关闭 Device 会隐式关闭 Session)。
3.3 组件间协作流程
一次典型的预览启动,三个组件按以下顺序协作:
- CameraManager 查询与打开
- 调用
getCameraIdList()获取可用相机列表 - 调用
getCameraCharacteristics(id)获取传感器方向、输出尺寸等元数据 - 调用
openCamera(id, callback, handler)请求打开设备
- 调用
- CameraDevice 配置与创建会话
- 在
onOpened()回调中构造Surface列表(预览 Surface + 拍照 Surface) - 调用
createCaptureSession(config, callback, handler)提交配置
- 在
- 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);
生命周期顺序总结:
CameraManager.openCamera()→ 触发onOpened()CameraDevice.createCaptureSession()→ 触发onConfigured()CameraCaptureSession.setRepeatingRequest()→ 预览数据开始流动- 关闭顺序严格反向:先
session.close(),再device.close()