3. Android Camera历史演进:从Camera API 1到Camera2 API再到CameraX
Android Camera框架自2008年诞生以来,经历了三次重大架构迭代。每一次演进都不是简单的接口增补,而是针对硬件能力升级、应用场景复杂化以及碎片化治理需求做出的根本性重构。理解这段演进史,不仅有助于开发者选择正确的API,更能深刻理解Android系统在硬件抽象、进程模型和兼容性策略上的设计哲学。本章将系统梳理Camera API 1、Camera2 API与CameraX的设计动机、核心差异与适用场景,并通过对比表格和案例拆解,帮助你在实际项目中做出合理的技术选型。
3.1 Camera API 1:早期Android的权宜之计
核心原理:基于单例Camera对象的同步模型
Camera API 1(android.hardware.Camera)诞生于Android 1.0时代,其设计初衷是提供最基础的拍照与录像能力。它采用单例模式,通过Camera.open()获取设备独占访问权,所有操作(预览、对焦、拍照)均为同步阻塞调用。底层通过Binder与CameraService通信,但上层暴露给开发者的接口极其简单——一个Camera对象承载了所有功能。
该API的核心设计缺陷在于:它将硬件能力抽象为一个黑盒。开发者只能调用预设的setParameters()方法,传入厂商定义的键值对(如focus-mode、scene-mode),无法精确控制传感器参数。同时,预览回调(onPreviewFrame())运行在Binder线程,若处理不当极易导致ANR。
判断方法:识别老代码中的典型特征
- 代码结构:存在
Camera类直接引用,而非CameraDevice或CameraManager。 - 权限声明:仅需
CAMERA权限,无需CAMERA2相关权限。 - 回调模式:使用
Camera.PreviewCallback或Camera.PictureCallback,而非CaptureCallback。 - 参数设置:通过
Parameters对象设置,而非CaptureRequest.Builder。
案例拆解:老项目维护中的典型问题
某OEM相机应用(targetSdk 22)在Android 10设备上出现预览黑屏问题。通过日志分析发现,设备返回的getSupportedPreviewSizes()列表与setPreviewSize()实际生效尺寸不一致。这是因为API 1的Parameters机制依赖厂商HAL实现,部分新设备在HAL层已不再完整支持旧接口的尺寸协商逻辑。最终解决方案是升级到Camera2 API,但迁移成本极高——原有3000行相机逻辑代码几乎全部重写。
复盘经验:Camera API 1的"简单"是建立在牺牲控制能力和可预测性之上的。对于任何新项目,都不应再考虑使用该API。
3.2 Camera2 API:面向专业能力的架构重构
核心原理:管道化异步架构与精细控制
Camera2 API(android.hardware.camera2)在Android 5.0(API 21)引入,彻底抛弃了单例模式,改为CameraDevice + CaptureSession + CaptureRequest的三层模型。其核心设计思想是模拟单反相机的操作流程:
- CameraManager:负责枚举摄像头、查询能力(
CameraCharacteristics)。 - CameraDevice:代表物理摄像头,通过异步回调
onOpened()获取。 - CaptureRequest:描述一次捕获的完整参数(对焦、曝光、ISO、帧率等),通过Builder构建。
- CaptureSession:管理请求队列,支持多路输出(预览+拍照+RAW)。
该架构的关键优势在于请求-响应流水线:应用可以连续提交多个CaptureRequest,系统按序处理并异步返回结果(CaptureCallback)。这使得连拍、HDR、夜景模式等高级功能成为可能。
操作流程:构建一个基础预览会话
// 1. 获取CameraManager
CameraManager manager = (CameraManager) getSystemService(CAMERA_SERVICE);
// 2. 打开摄像头(异步)
manager.openCamera(cameraId, stateCallback, backgroundHandler);
// 3. 在onOpened中创建预览请求
CaptureRequest.Builder previewBuilder = device.createCaptureRequest(TEMPLATE_PREVIEW);
previewBuilder.addTarget(surfaceView.getHolder().getSurface());
// 4. 创建会话
device.createCaptureSession(Arrays.asList(surface), sessionCallback, backgroundHandler);
// 5. 在onConfigured中提交请求
session.setRepeatingRequest(previewBuilder.build(), captureCallback, backgroundHandler);
案例拆解:实现专业级手动对焦
某专业相机App需要支持峰值对焦功能。使用Camera2 API,开发者可以精确控制CONTROL_AF_MODE为OFF,然后通过LENS_FOCUS_DISTANCE设置具体对焦距离(单位:屈光度)。同时,通过CaptureResult中的LENS_FOCUS_DISTANCE读取实际对焦位置,结合图像边缘检测算法实现峰值显示。
关键代码片段:
// 设置手动对焦
requestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_OFF);
requestBuilder.set(CaptureRequest.LENS_FOCUS_DISTANCE, 2.0f); // 0.5米
// 读取对焦结果
float focusDistance = result.get(CaptureResult.LENS_FOCUS_DISTANCE);
性能对比:在相同硬件(IMX586传感器)上,Camera2 API的对焦响应时间比API 1缩短约40%,且支持更精细的步进控制(0.001屈光度)。
3.3 CameraX:平衡能力与易用性的现代选择
核心原理:基于UseCase的生命周期感知封装
CameraX(androidx.camera)于2019年发布,是Jetpack家族成员。它并非全新的底层实现,而是在Camera2之上构建的抽象层,核心设计理念是"用例驱动"(UseCase)。开发者不再直接操作CameraDevice,而是声明需要什么功能:
- Preview:预览用例,自动处理Surface生命周期。
- ImageCapture:拍照用例,支持闪关灯、旋转、降噪。
- ImageAnalysis:帧分析用例,用于人脸检测、OCR等。
- VideoCapture:录像用例(1.1+版本)。
CameraX的核心价值在于生命周期感知:它自动绑定到LifecycleOwner(如Activity/Fragment),在onStart时打开相机,onStop时自动释放,无需开发者手动管理。同时,它内置了CameraControl和CameraInfo,提供统一的缩放、对焦、曝光控制接口。
判断方法:何时选择CameraX而非Camera2
| 需求特征 | 推荐方案 | 理由 |
|---|---|---|
| 快速实现标准拍照/录像 | CameraX | 代码量减少60%,自动处理兼容性 |
| 需要RAW或DNG输出 | Camera2 | CameraX暂不支持RAW |
| 多摄像头同时预览 | Camera2 | CameraX 1.1+支持但限制较多 |
| 高帧率慢动作(≥240fps) | Camera2 | CameraX对高帧率支持有限 |
| 需要与ML Kit等集成 | CameraX | 官方推荐组合,有现成扩展 |
案例拆解:用CameraX实现二维码扫描
某物流App需要集成扫码功能。使用CameraX的ImageAnalysis用例,仅需约50行代码即可实现:
// 1. 创建ImageAnalysis用例
ImageAnalysis analysis = new ImageAnalysis.Builder()
.setBackpressureStrategy(STRATEGY_KEEP_ONLY_LATEST)
.build();
analysis.setAnalyzer(executor, imageProxy -> {
// 2. 将ImageProxy转为Bitmap并送入ML Kit
InputImage image = InputImage.fromMediaImage(
imageProxy.getImage(), imageProxy.getImageInfo().getRotationDegrees());
scanner.process(image)
.addOnSuccessListener(barcodes -> { /* 处理结果 */ })
.addOnCompleteListener(task -> imageProxy.close());
});
// 3. 绑定到生命周期
cameraProvider.bindToLifecycle(this, cameraSelector, preview, analysis);
结果对比:相比传统Camera2实现,CameraX版本代码量减少70%,且无需处理摄像头旋转、Surface生命周期、线程切换等复杂逻辑。在低端设备(如Redmi 9A)上,帧率稳定在25fps以上,满足扫码需求。
3.4 三版API对比与迁移策略
核心差异总览
| 维度 | Camera API 1 | Camera2 API | CameraX |
|---|---|---|---|
| 推出时间 | 2009 (API 1) | 2014 (API 21) | 2019 (AndroidX) |
| 架构模式 | 单例+同步 | 管道+异步 | UseCase+生命周期 |
| 控制粒度 | 预设参数 | 全参数手动 | 常用参数自动 |
| 线程模型 | UI线程回调 | 多线程异步 | 自动管理 |
| 兼容性 | 碎片化严重 | 厂商差异大 | 自动兼容层 |
| 学习成本 | 低 | 高 | 中低 |
| 维护状态 | 废弃 | 稳定维护 | 积极迭代 |
迁移路径与注意事项
- 从API 1迁移到CameraX:这是最平滑的路径。CameraX提供了
CameraXConfig和ProcessCameraProvider,可以逐步替换原有Camera代码,且无需修改UI层。 - 从API 1迁移到Camera2:仅当需要RAW或手动控制时考虑。迁移前需评估工作量,因为线程模型和回调机制完全不同。
- 从Camera2迁移到CameraX:如果现有Camera2代码稳定且无特殊需求,不建议迁移。但新功能模块建议使用CameraX。
CAMERA)和运行时权限请求。CameraX虽然简化了生命周期管理,但权限逻辑仍需开发者自行实现。此外,在Android 10+设备上,还需注意android:requestLegacyExternalStorage对图片保存路径的影响。
总结复盘:演进背后的设计哲学
Android Camera API的演进反映了三个核心趋势:从黑盒到白盒(控制粒度逐步开放)、从同步到异步(性能与响应性提升)、从碎片到统一(兼容性治理)。Camera API 1是移动时代的"功能机",Camera2是"专业单反",而CameraX则是"智能相机"——它牺牲了部分极限能力,换来了绝大多数场景下的最佳实践。
作为开发者,你的选择不应基于"哪个更先进",而应基于业务需求与团队能力。如果团队对Camera2有深入理解且需要极致性能,直接使用Camera2完全合理;如果追求开发效率和稳定性,CameraX是更明智的长期投资。无论选择哪条路径,理解底层Camera2的管道模型都是必要的——因为CameraX的抽象层最终仍会映射到Camera2的请求-响应机制上。