移动应用中的相机 — 是一种设备硬件模块,开发人员可通过系统API访问以捕获图像和视频。根据 Google Android Developers (2025),CameraX被用于超过85%需要相机功能的Android应用中。iOS上的AVFoundation和Android上的CameraX提供了隐藏硬件管理复杂性的高级接口。
要点
移动相机 — 是一个内置光学模块,由镜头、矩阵(传感器)和图像处理处理器(ISP)组成。开发人员通过操作系统使用特定框架访问相机。在Android上是Camera2 API(低级)和CameraX(基于Camera2的高级),在iOS上是AVFoundation和用于简单场景的UIKit。每个平台提供自己的工具集,但总体概念相同:应用初始化捕获会话,配置参数(分辨率、对焦、曝光)并接收帧流或单个图像。
现代移动相机支持多种拍摄模式:HDR、夜景模式、背景虚化的人像、慢动作和RAW格式录制。开发人员可以使用软件设置:ISO(矩阵灵敏度)、曝光时间、白平衡、对焦(自动和手动)和图像稳定。在旗舰设备上多达4个具有不同焦距的相机可用,应用可以根据ID选择特定相机。
在移动平台上存在几种用于相机工作的API,它们在抽象级别和功能上有所不同。具体API的选择取决于项目需求:对于简单的照片拍摄,CameraX或UIImagePickerController就足够了,对于专业应用需要Camera2或具有直接传感器控制的AVFoundation。以下是主要API的比较。
| API | 平台 | 级别 | 特点 |
|---|---|---|---|
| CameraX | Android | 高级 | 生命周期感知,95%设备 |
| Camera2 | Android | 低级 | 完全控制,RAW,连拍 |
| AVFoundation | iOS | 中级 | 完全捕获控制 |
| UIKit(UIImagePickerController) | iOS | 高级 | 现成UI,无法自定义 |
CameraX — 对于大多数不需要深度自定义的Android应用来说是最佳选择。该库自动管理Activity和Fragment的生命周期,支持权限和不同Android版本的兼容性。CameraX通过兼容层保证在95%的Android设备上具有相同的行为。如果需要相机预览(Preview)、照片捕获(ImageCapture)或流分析(ImageAnalysis) — CameraX无需编写复杂代码即可处理所有三个场景。
Camera2 — 用于专业场景的低级API:RAW录制、手动曝光设置、连拍(burst)、同时控制多个相机。Camera2要求开发人员深入了解图像捕获管道、StateMachine管理和回调处理。仅当CameraX不满足需求时才使用Camera2:例如,用于需要手动对焦的文档扫描应用或具有非标准分辨率的自定义相机。
访问相机需要在两个平台上获得用户的明确同意。在Android上,在清单中添加CAMERA权限,从Android 6.0开始还需要通过ActivityCompat.requestPermissions在运行时请求权限。在iOS上,在Info.plist中添加NSCameraUsageDescription键,附带相机使用原因的说明。没有此说明,应用在尝试访问相机时会崩溃。从iOS 14开始,权限对话框不仅显示应用名称,还显示所述原因 — 措辞应对用户可理解。
CameraX将相机工作简化为几行代码。要启动预览,需要创建Preview实例,将其绑定到LifecycleOwner并获取SurfaceProvider进行显示。对于照片捕获,使用带有保存目标的ImageCapture。以下是在Kotlin中使用CameraX启动相机和拍摄照片的完整示例。
val preview = Preview.Builder()
.build()
.also {
it.surfaceProvider = viewFinder.surfaceProvider
}
val imageCapture = ImageCapture.Builder()
.setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
.build()
val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
cameraProviderFuture.addListener(Runnable {
val cameraProvider = cameraProviderFuture.get()
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
try {
cameraProvider.unbindAll()
cameraProvider.bindToLifecycle(
this, cameraSelector, preview, imageCapture
)
} catch (e: Exception) {
Log.e("CameraX", "绑定失败", e)
}
}, ContextCompact.getMainExecutor(this))
bindToLifecycle方法将相机与Activity的生命周期绑定 — 在屏幕旋转或进入后台时,相机会自动释放。CameraSelector.DEFAULT_BACK_CAMERA选择后置相机,前置相机使用DEFAULT_FRONT_CAMERA。绑定后,Preview开始在PreviewView中显示相机图像,用户在屏幕上看到相机画面。
val photoFile = File(
externalMediaDirs.firstOrNull(),
"IMG_${System.currentTimeMillis()}.jpg"
)
val outputOptions = ImageCapture.OutputFileOptions
.Builder(photoFile)
.build()
imageCapture.takePicture(
outputOptions,
ContextCompact.getMainExecutor(this),
object : ImageCapture.OnImageSavedCallback {
override fun onImageSaved(output: ImageCapture.OutputFileResults) {
Log.d("CameraX", "Photo saved: ${photoFile.absolutePath}")
}
override fun onError(exception: ImageCaptureException) {
Log.e("CameraX", "捕获错误", exception)
}
}
)
takePicture方法从相机捕获帧并将其保存到文件。OutputFileOptions支持保存到File、ContentResolver和MediaStore。在onImageSaved回调中,应用收到成功保存的通知并可以更新UI。CAPTURE_MODE_MINIMIZE_LATENCY通过减少后处理确保最大快门速度。
在iOS上,访问相机由AVFoundation框架通过AVCaptureSession类提供。开发人员创建捕获会话,添加必要的输入(AVCaptureDeviceInput)和输出(AVCapturePhotoOutput、AVCaptureVideoDataOutput)并启动会话。预览显示使用AVCaptureVideoPreviewLayer。以下是在Swift中配置会话以捕获照片的示例。
import AVFoundation
let captureSession = AVCaptureSession()
captureSession.sessionPreset = .photo
guard let camera = AVCaptureDevice.default(
for: .video
) else { return }
guard let input = try? AVCaptureDeviceInput(device: camera)
else { return }
let output = AVCapturePhotoOutput()
captureSession.addInput(input)
captureSession.addOutput(output)
DispatchQueue.global(qos: .userInitiated).async {
captureSession.startRunning()
}
AVCaptureSessionPreset.photo设置照片的最佳分辨率(通常在现代设备上为12 MP)。输入是为设备相机创建的AVCaptureDeviceInput。添加输入和输出后,会话通过startRunning在后台线程中启动 — 在旧设备上会话启动可能需要长达200毫秒。要捕获照片,调用capturePhoto(with:delegate:),结果通过委托AVCapturePhotoCaptureDelegate返回。
在移动设备上使用相机时需考虑硬件限制:长时间拍摄时设备发热、高分辨率工作时电池消耗以及不同设备上相机质量各异。在Android上,生态系统碎片化导致相同的CameraX配置在不同型号上可能表现不同。在iOS上,限制主要涉及许可:在后台使用相机需要Apple的特别许可。同样重要的是要记住,模拟器无法访问真实相机 — 测试只能在物理设备上进行。
CameraX通过CameraXConfig兼容层解决Android碎片化问题 — 库自动应用针对制造商已知错误的解决方案。在iOS上,AVFoundation从iOS 6开始在所有设备上统一运行,但某些功能(如Portrait Mode或LiDAR)仅适用于iPhone 12及更新型号。在开发跨平台应用时,建议使用Flutter或React Native配合相机插件 — 它们抽象了平台差异并为两个操作系统提供统一的API。
常见问题
对于大多数应用,推荐使用CameraX,因为其使用简单、内置生命周期处理以及与95%设备的兼容性。Camera2仅在需要RAW、连拍或手动传感器控制时选择。
在Android上,在清单中添加CAMERA权限并在运行时通过ActivityCompat.requestPermissions请求。在iOS上,在Info.plist中添加NSCameraUsageDescription,附带相机使用原因的清晰说明。
在iOS上,后台使用相机受到严格限制 — 需要Apple的特别许可。在Android上,相机可以通过前台服务(foreground service)在后台工作,但这会对电池电量和设备发热产生负面影响。
iOS模拟器和Android模拟器无法访问硬件相机 — 它们不模拟物理传感器。要测试相机功能,始终使用物理设备或连接到计算机的外部相机。
ImageAnalysis — 来自CameraX的帧流分析器,它将每个帧传递给ImageAnalysis.Analyzer进行处理。用于QR码识别、人脸检测、文档扫描和其他计算机视觉任务。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。