初识 Camera:Android 摄像头开发的第一扇门
大家好,我是你们这门课的老朋友。今天咱们正式开篇,聊聊 Android 摄像头开发的那些事儿。
说实话,我第一次接触 Android 摄像头开发时,也是一头雾水。那时候市面上资料少,官方文档又晦涩,我踩了不少坑。所以这门课,我希望能帮你把路铺平一点。
这一章,我们先从最基础的东西说起——摄像头硬件长什么样?API 是怎么演变的?以及,怎么写出你的第一个预览程序?
1. 摄像头硬件架构概览
先别急着写代码。你得先知道,你调用的每一行代码,最终是怎么驱动硬件的。
一个典型的 Android 手机摄像头系统,大致分三层:
- 物理层:就是镜头、传感器(CMOS/CCD)、闪光灯这些硬件。传感器负责把光信号转成电信号。
- 驱动层:厂商写的底层驱动,负责跟硬件打交道。这部分你基本碰不到,但它的质量直接影响拍照速度和对焦精度。
- 框架层:Android 系统提供的 Camera API,你写的 App 就是通过它来调用驱动的。
我画了一张图,帮你理清这个关系:
说白了,你的 App 就是通过框架层,一层层往下传指令,最终让传感器开始工作。反过来,图像数据也是一层层往上送,最后显示在你的屏幕上。
2. Camera API 的发展历程
Android 的摄像头 API 经历了三个阶段。我按时间线给你捋一捋。
2.1 Camera1(古老但还在用)
这是 Android 最早期的 API,从 Android 1.0 就有了。它的设计很简单,但问题也很明显:
- 所有操作都在一个线程里,容易卡 UI。
- 不支持同时打开多个摄像头。
- 对焦、曝光等控制非常有限。
我记得 2014 年做一款扫码 App,用的就是 Camera1。那时候为了不让预览卡顿,我得自己开子线程处理帧数据,写起来特别痛苦。
2.2 Camera2(强大但复杂)
Android 5.0 引入了 Camera2 API。它彻底重写了架构,引入了「管道」的概念。说白了,就是把拍照流程拆成一个个步骤,你可以精细控制每一步。
Camera2 的核心概念包括:
- CameraManager:管理摄像头设备。
- CameraDevice:代表一个摄像头。
- CaptureRequest:一次拍照请求,可以设置对焦、曝光、白平衡等参数。
- CameraCaptureSession:管理请求的发送和结果的回调。
听起来很专业对吧?但实际用起来,代码量比 Camera1 多了好几倍。我刚开始用 Camera2 时,光写一个预览就花了半天,还老是报错。
📌 一句话总结: Camera2 功能强大,但学习曲线陡峭。如果你只是想快速实现一个拍照功能,它可能不是最佳选择。
2.3 CameraX(Google 的救星)
2019 年,Google 推出了 CameraX。它基于 Camera2 封装,但简化了使用方式。你想想看,Google 自己也觉得 Camera2 太难用了,所以才搞了 CameraX。
CameraX 的特点:
- 生命周期感知:自动绑定 Activity 或 Fragment 的生命周期。
- 用例驱动:预览、拍照、分析,每个用例就是一个模块。
- 兼容性好:自动处理不同厂商的差异。
我个人习惯用 CameraX 做快速原型开发。比如做一个简单的扫码功能,用 CameraX 十几行代码就能搞定。但如果你需要深度控制(比如手动对焦、RAW 格式输出),还是得回到 Camera2。
下面这个表格,帮你快速对比三个 API:
| 特性 | Camera1 | Camera2 | CameraX |
|---|---|---|---|
| 引入版本 | Android 1.0 | Android 5.0 | Android 5.0+(Jetpack) |
| 易用性 | 简单 | 复杂 | 简单 |
| 功能丰富度 | 低 | 高 | 中 |
| 生命周期管理 | 手动 | 手动 | 自动 |
| 多摄像头支持 | 不支持 | 支持 | 支持 |
| 推荐场景 | 老项目维护 | 专业摄影 App | 快速开发、通用场景 |
3. 第一个 Camera 预览程序
好了,理论说完了,咱们动手写代码。这里我用 CameraX 来实现,因为它最简单。
嗯,这里要注意:你需要先在 build.gradle 里添加依赖:
dependencies {
def camerax_version = "1.3.0"
implementation "androidx.camera:camera-core:${camerax_version}"
implementation "androidx.camera:camera-camera2:${camerax_version}"
implementation "androidx.camera:camera-lifecycle:${camerax_version}"
implementation "androidx.camera:camera-view:${camerax_version}"
}
然后在布局文件里放一个 PreviewView:
<androidx.camera.view.PreviewView
android:id="@+id/previewView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
最后在 Activity 里写核心代码:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val previewView = findViewById<PreviewView>(R.id.previewView)
val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
cameraProviderFuture.addListener({
val cameraProvider = cameraProviderFuture.get()
// 创建预览用例
val preview = Preview.Builder().build()
preview.setSurfaceProvider(previewView.surfaceProvider)
// 选择后置摄像头
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
// 绑定生命周期
try {
cameraProvider.unbindAll()
cameraProvider.bindToLifecycle(
this, cameraSelector, preview
)
} catch (e: Exception) {
e.printStackTrace()
}
}, ContextCompat.getMainExecutor(this))
}
}
就这么几行,你的手机屏幕上就能看到摄像头预览了。是不是很简单?
unbindAll(),结果导致摄像头被占用,第二次打开 App 时黑屏。所以每次绑定前,记得先解绑。
另外,别忘了在 AndroidManifest.xml 里声明摄像头权限:
<uses-permission android:name="android.permission.CAMERA" />
运行时也要动态申请权限。这部分代码我就不贴了,相信你已经会了。
好了,这一章的内容就到这里。你学会了摄像头硬件架构、API 的演变,还亲手写了一个预览程序。下一章,我们会深入 CameraX 的各个用例,看看怎么拍照、怎么分析帧数据。
记住,动手是最好的学习方式。打开 Android Studio,把上面的代码跑起来,你会发现自己离「摄像头开发专家」又近了一步。
公众号:蓝海资料掘金营,微信 deep3321