CameraX 相机库
CameraX 是一个 Google 推出的 Jetpack 支持库,旨在帮助您简化相机应用的开发。它提供了一套一致且易于使用的 API,适用于大多数 Android 设备,并向后兼容至 Android 5.0(API 级别 21)。
核心优势
- 易用性:只需几行代码即可实现预览、拍照和视频录制。
- 一致性:自动处理不同设备上的兼容性问题(如长宽比、方向、旋转)。
- 扩展性:支持人像模式、HDR、夜间模式等扩展功能(取决于设备支持)。
1. 添加依赖
kotlin
[versions]
camerax = "1.3.4"
[libraries]
androidx-camera-core = { group = "androidx.camera", name = "camera-core", version.ref = "camerax" }
androidx-camera-camera2 = { group = "androidx.camera", name = "camera-camera2", version.ref = "camerax" }
androidx-camera-lifecycle = { group = "androidx.camera", name = "camera-lifecycle", version.ref = "camerax" }
androidx-camera-video = { group = "androidx.camera", name = "camera-video", version.ref = "camerax" }
androidx-camera-view = { group = "androidx.camera", name = "camera-view", version.ref = "camerax" }
androidx-camera-extensions = { group = "androidx.camera", name = "camera-extensions", version.ref = "camerax" }kotlin
dependencies {
implementation(libs.androidx.camera.core)
implementation(libs.androidx.camera.camera2)
implementation(libs.androidx.camera.lifecycle)
implementation(libs.androidx.camera.video)
implementation(libs.androidx.camera.view)
implementation(libs.androidx.camera.extensions)
}2. 核心用例 (Use Cases)
CameraX 的工作流程基于“用例”。常见的用例有:
- Preview: 显示相机实时预览。
- ImageCapture: 拍摄并保存照片。
- ImageAnalysis: 实时处理帧数据(如二维码识别)。
- VideoCapture: 录制视频。
3. 实现相机预览
权限注意
请确保在 AndroidManifest.xml 中声明了 android.permission.CAMERA 权限,并在运行时请求。
第一步:添加 PreviewView
在 XML 布局中添加相机预览容器:
xml
<androidx.camera.view.PreviewView
android:id="@+id/viewFinder"
android:layout_width="match_parent"
android:layout_height="match_parent" />第二步:启动相机逻辑
kotlin
private fun startCamera() {
val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
cameraProviderFuture.addListener({
// 用于将相机生命周期绑定到 LifecycleOwner
val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()
// 1. 配置 Preview 用例
val preview = Preview.Builder().build().also {
it.setSurfaceProvider(binding.viewFinder.surfaceProvider)
}
// 2. 配置 ImageCapture 用例
imageCapture = ImageCapture.Builder().build()
// 选择后置摄像头
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
try {
// 绑定前先解除所有绑定
cameraProvider.unbindAll()
// 将用例绑定到生命周期
cameraProvider.bindToLifecycle(
this, cameraSelector, preview, imageCapture
)
} catch(exc: Exception) {
Log.e(TAG, "绑定失败", exc)
}
}, ContextCompat.getMainExecutor(this))
}4. 拍摄照片
kotlin
private fun takePhoto() {
val imageCapture = imageCapture ?: return
// 创建保存位置
val name = SimpleDateFormat("yyyyMMdd-HHmmss", Locale.US).format(System.currentTimeMillis())
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, name)
put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
}
val outputOptions = ImageCapture.OutputFileOptions
.Builder(contentResolver, MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
.build()
// 执行拍摄
imageCapture.takePicture(
outputOptions,
ContextCompat.getMainExecutor(this),
object : ImageCapture.OnImageSavedCallback {
override fun onError(exc: ImageCaptureException) {
Log.e(TAG, "拍摄失败: \${exc.message}", exc)
}
override fun onImageSaved(output: ImageCapture.OutputFileResults) {
val msg = "照片保存成功: \${output.savedUri}"
Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show()
}
}
)
}5. 图像分析 (ImageAnalysis)
用于实时扫描码或进行人脸检测。
kotlin
val imageAnalysis = ImageAnalysis.Builder()
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.build()
imageAnalysis.setAnalyzer(executor) { imageProxy ->
val rotationDegrees = imageProxy.imageInfo.rotationDegrees
// 在这里处理图像数据
// 处理完成后务必释放
imageProxy.close()
}