在 Android 应用开发中,相机功能是许多场景的核心 —— 从社交应用的自拍分享到扫码支付,从证件照拍摄到实时视频处理,都需要稳定高效的相机 API 支持。Android 系统历经多年迭代,相机 API 也从早期的 Camera1 演进到 Camera2,再到如今的 CameraX。不同 API 在功能、兼容性、开发复杂度上差异显著,选择合适的 API 直接影响开发效率和应用体验。本文将全面对比三者的优缺点,并结合实际开发场景总结常见问题及解决方案。
一、Camera1 API:经典但逐步淘汰的 "元老"
Camera1(android.hardware.Camera)是 Android 最早的相机 API,基于传统的 "相机设备 + 参数设置" 模型,从 Android 1.0 开始支持,至今仍有部分旧应用在使用。
核心特点与优势
1.开发简单直观
采用直接的方法调用模式(如open()打开相机、setPreviewDisplay()设置预览、takePicture()拍照),无需深入理解相机底层原理。核心流程仅需 5 步:
// 1. 打开相机(指定摄像头,0为后置,1为前置)
Camera camera = Camera.open(0);
// 2. 设置预览尺寸和参数
Camera.Parameters params = camera.getParameters();
params.setPreviewSize(1920, 1080);
camera.setParameters(params);
// 3. 设置预览界面(SurfaceView或TextureView)
camera.setPreviewDisplay(surfaceHolder);
// 4. 开始预览
camera.startPreview();
// 5. 拍照(回调中获取数据)
camera.takePicture(null, null, (data, camera) -> {
// 处理拍照数据(data为JPEG格式字节数组)
});
2.兼容性极佳
支持 Android 1.0(API 1)及以上所有版本,覆盖几乎所有 Android 设备,适合需要兼容低端机型的应用(如旧款 POS 机、工业设备)。
3.资源占用低
底层实现轻量,在性能有限的设备上(如 512MB 内存的嵌入式设备)也能稳定运行。
缺点与局限性
1.功能简陋,无法支持高级特性
不支持手动对焦区域选择、RAW 格式拍摄、曝光时间控制等进阶功能,无法满足专业场景(如夜景拍摄、手动曝光调节)。
2.回调机制落后
拍照和预览数据通过单一回调返回,无法并行处理(如预览时同时进行实时滤镜和人脸识别),且数据格式固定(预览为 YUV,拍照为 JPEG)。
3.线程安全问题
所有操作必须在同一线程执行(通常是主线程),否则可能导致相机崩溃,无法利用多线程提升处理效率。
4.官方已弃用
在 Android 5.0(API 21)后被标记为@Deprecated,未来可能从系统中移除,不建议新应用使用。
二、Camera2 API:功能强大但复杂的 "全能选手"
Camera2(android.hardware.camera2)在 Android 5.0(API 21)中推出,彻底重构了相机架构,采用 "相机设备 + 请求队列" 模型,支持几乎所有相机硬件特性。
核心特点与优势
1.全面的硬件控制能力
支持手动对焦、曝光时间、ISO、白平衡等参数调节,可拍摄 RAW 格式照片,甚至能控制闪光灯亮度和激光对焦。例如手动设置曝光参数:
// 创建拍照请求
CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
// 设置曝光时间(单位:纳秒)
captureBuilder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, 10000000L);
// 设置ISO
captureBuilder.set(CaptureRequest.SENSOR_SENSITIVITY, 400);
// 提交请求
captureSession.capture(captureBuilder.build(), null, null);
1.灵活的请求队列机制
通过CaptureSession提交请求队列,可并行处理预览、拍照、录像等任务(如预览时同时输出 YUV 数据用于实时检测,输出 JPEG 用于拍照)。
2.支持高级特性
支持 HDR 合成、连拍(burst capture)、零快门延迟(ZSL)等,能实现专业相机级体验(如夜景模式多帧合成)。
线程安全设计
操作可在不同线程执行(如在后台线程处理预览数据),通过Handler指定回调线程,避免主线程阻塞。
缺点与局限性
1.开发复杂度极高
需理解 "相机设备 - 会话 - 请求" 三级模型,创建一个简单的预览功能就需要至少 5 个回调接口和 100 行以上代码。例如初始化流程:
- 调用CameraManager.openCamera()打开设备(需权限回调)
- 创建CameraCaptureSession(需会话创建回调)
- 构建CaptureRequest并提交(需捕获回调)
2.兼容性碎片化
虽然 API 21 以上支持,但硬件特性(如 RAW 拍摄、手动曝光)依赖设备厂商实现,同一款 API 在不同机型上表现差异极大(如部分机型宣称支持 4K 拍摄,实际输出模糊)。
3.性能优化难度大
需手动管理缓冲区(如Surface的创建与释放),处理不当易导致内存泄漏或预览卡顿。
三、CameraX API:Jetpack 加持的 "现代简化版"
CameraX(androidx.camera)是 Jetpack 组件库中的相机解决方案,基于 Camera2 封装,在 Android 5.0(API 21)以上运行,2019 年正式发布稳定版。
核心特点与优势
1.极简开发体验
采用生命周期感知设计,自动处理相机打开 / 关闭、资源释放,几行代码即可实现预览:
// 1. 绑定预览用例到生命周期
val preview = Preview.Builder().build().also {
it.setSurfaceProvider(previewView.surfaceProvider)
}
// 2. 绑定相机生命周期
CameraX.bindToLifecycle(this, preview)
1.设备兼容性适配
自动处理不同设备的硬件差异(如摄像头方向、预览尺寸),无需手动判断机型特性。例如自动选择最佳预览尺寸:
val preview = Preview.Builder()
.setTargetAspectRatio(AspectRatio.RATIO_16_9) // 只需指定比例,尺寸由系统选择
.build()
2.功能模块化
基于 "用例(UseCase)" 设计,支持预览(Preview)、拍照(ImageCapture)、录像(VideoCapture)、图像分析(ImageAnalysis)等,可组合使用(如预览 + 实时分析)。
3.与 Jetpack 生态无缝集成
可直接与 Compose、Lifecycle、ViewModel 结合,例如在 Compose 中使用:
CameraPreview(
modifier = Modifier.fillMaxSize(),
onImageCaptured = { bitmap -> /* 处理拍照结果 */ }
)
缺点与局限性
1.高级功能封装有限
虽然支持基础手动参数调节,但部分 Camera2 的高级特性(如 RAW 格式连拍、激光对焦控制)未完全暴露,需通过Camera2Interop桥接调用原生 API。
2.依赖 Jetpack 版本
不同版本的 CameraX 可能存在 API 变动,升级时需注意兼容性(如 1.0.0 到 1.1.0 中部分方法被移除)。
3.性能开销略高
由于封装层存在,在极端场景(如 4K 60fps 预览 + 实时 AI 分析)下,性能略低于原生 Camera2。
四、三大 API 对比与选型建议
|
维度 |
Camera1 |
Camera2 |
CameraX |
|
API 版本支持 |
API 1+(已弃用) |
API 21+ |
API 21+(推荐 API 24+) |
|
开发复杂度 |
简单(100 行内实现预览) |
复杂(需处理多级回调) |
极简(基于用例设计) |
|
功能丰富度 |
基础(仅支持拍照 / 预览) |
全面(支持手动参数调节) |
均衡(基础 + 部分高级功能) |
|
兼容性 |
全设备支持 |
硬件依赖厂商实现 |
自动适配设备差异 |
|
性能 |
一般(单线程限制) |
最优(可多线程优化) |
良好(封装层略有开销) |
|
适用场景 |
旧应用维护、低端设备 |
专业相机应用、自定义需求 |
新应用开发、快速迭代 |
选型建议
- 选择 Camera1:仅当应用需兼容 Android 4.4 以下设备(如工业终端),且功能仅需基础拍照 / 预览。
- 选择 Camera2:开发专业相机应用(如手动曝光调节、RAW 格式处理),且团队有能力处理复杂逻辑。
- 选择 CameraX:新应用开发、快速实现相机功能,或需要与 Jetpack 生态结合(如 Compose 界面)。
五、开发常见问题及解决方案
(一)Camera1 常见问题
1.预览画面拉伸
原因:预览尺寸与SurfaceView比例不一致。
解决:从Camera.Parameters.getSupportedPreviewSizes()中选择与控件比例最接近的尺寸:
List<Camera.Size> sizes = params.getSupportedPreviewSizes();
Camera.Size optimalSize = findOptimalSize(sizes, surfaceWidth, surfaceHeight);
params.setPreviewSize(optimalSize.width, optimalSize.height);
2.拍照后预览黑屏
原因:takePicture()后相机进入拍照状态,需手动重启预览。
解决:在拍照回调中调用startPreview():
camera.takePicture(null, null, (data, camera) -> {
// 处理照片数据
camera.startPreview(); // 重启预览
});
(二)Camera2 常见问题
1.打开相机失败(权限已申请但返回 PERMISSION_DENIED)
原因:Android 10 + 需申请ACCESS_BACKGROUND_LOCATION(部分设备将相机与位置权限绑定)。
解决:在AndroidManifest.xml中添加位置权限,并动态申请。
2.预览帧率低(卡顿)
原因:CaptureRequest未设置合适的模板,或缓冲区配置不当。
解决:使用TEMPLATE_PREVIEW模板,并设置帧率范围:
CaptureRequest.Builder previewBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
// 设置帧率范围(最小15fps,最大30fps)
previewBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, new Range<>(15, 30));
(三)CameraX 常见问题
1.预览方向错误(画面旋转 90 度)
原因:CameraX 默认按自然方向输出,需手动适配设备旋转。
解决:通过Preview.Builder设置旋转监听:
Preview.Builder()
.setTargetRotation(previewView.display.rotation)
.build()
2.ImageAnalysis 处理延迟
原因:默认使用单线程处理,无法及时消费预览帧。
解决:配置线程池并设置缓冲区策略:
ImageAnalysis.Builder()
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) // 只保留最新帧
.setAnalyzer(Executors.newSingleThreadExecutor(), { image ->
// 处理图像
image.close() // 及时关闭,避免缓冲区耗尽
})
六、总结
Android 相机 API 的演进体现了 "从功能实现到体验优化" 的趋势:Camera1 满足了早期简单场景的需求,Camera2 释放了硬件潜力却带来了复杂度,CameraX 则在易用性和功能之间找到了平衡。
对于开发者而言,新应用应优先选择 CameraX—— 它大幅降低了开发成本,同时通过Camera2Interop保留了扩展空间;维护旧应用时,若需升级相机功能,建议逐步迁移到 CameraX 而非直接切换到 Camera2,以减少重构成本。
相机开发的核心挑战永远是 "兼容性" 与 "性能" 的平衡,无论选择哪种 API,都需在多机型上测试(尤其是国产定制 ROM),并针对常见问题做好容错处理(如相机被占用时的重试机制、权限被拒后的引导流程)。只有这样,才能打造出稳定流畅的相机体验。
1439

被折叠的 条评论
为什么被折叠?



