拍照
捕获并保存图片
拍照 是 CoddyKit 上的免费 Android Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Android Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Android Academy 课程共包含 4 节课。
拍摄照片
屏幕上显示预览后,下一步就是拍照。CameRX 通过 ImageCapture 用例处理这项功能。
您将把 ImageCapture 与预览一起绑定,然后在用户点击快门按钮时调用 takePicture(),并将结果保存到设备图库。
构建 ImageCapture 用例
ImageCapture 通过 builder 进行配置。一个实用选项是拍摄模式,它用于在延迟和质量之间进行权衡:
CAPTURE_MODE_MINIMIZE_LATENCY——快门响应更快。CAPTURE_MODE_MAXIMIZE_QUALITY——图像质量最佳,但速度稍慢。
val imageCapture = ImageCapture.Builder()
.setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
.build()绑定 Preview + ImageCapture
您可以一次绑定多个用例。将 preview 和 imageCapture 都传给 bindToLifecycle,这样相机既能提供实时画面,也能随时拍照。
cameraProvider.unbindAll()
cameraProvider.bindToLifecycle(
lifecycleOwner,
CameraSelector.DEFAULT_BACK_CAMERA,
preview,
imageCapture
)保存位置:MediaStore
通过 MediaStore 保存照片,是现代且适合分区存储的方式。您可以使用 ContentValues 描述文件(名称、MIME 类型和文件夹),然后让系统将其放入共享的 Pictures 集合中。
在 Android 10 及更高版本上,这种方式无需旧版 WRITE_EXTERNAL_STORAGE 权限。
val name = "photo_${System.currentTimeMillis()}"
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, name)
put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/MyApp")
}输出选项
要告诉 CameraX 将 JPEG 写入何处,请使用内容解析器、目标集合 URI 和您的 ContentValues 构建 OutputFileOptions。
val outputOptions = ImageCapture.OutputFileOptions
.Builder(
context.contentResolver,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
contentValues
)
.build()调用 takePicture()
现在触发拍摄。takePicture() 接收输出选项、一个 Executor 和一个回调。CameRX 会异步报告成功或错误。
请使用 ContextCompat.getMainExecutor(context),确保回调在主线程上运行。
imageCapture.takePicture(
outputOptions,
ContextCompat.getMainExecutor(context),
object : ImageCapture.OnImageSavedCallback {
override fun onImageSaved(output: ImageCapture.OutputFileResults) {
val savedUri = output.savedUri
// Photo saved! Show a confirmation.
}
override fun onError(exc: ImageCaptureException) {
// Handle the failure.
}
}
)处理结果
成功时,OutputFileResults.savedUri 会提供已保存图像的 URI。您可以使用 Coil 显示它、分享它,或显示 Snackbar 来确认保存成功。
发生错误时,ImageCaptureException 会告知您具体原因——请记录错误并通知用户。
override fun onImageSaved(output: ImageCapture.OutputFileResults) {
val uri = output.savedUri ?: return
Toast.makeText(context, "Saved: $uri", Toast.LENGTH_SHORT).show()
}连接快门按钮
在 Compose 中,您可以使用 Box 将快门按钮叠加在预览上方。请将 ImageCapture 引用提升到更高层级,这样按钮的 onClick 就能调用 takePhoto。
Box(modifier = Modifier.fillMaxSize()) {
CameraPreview(imageCapture = imageCapture)
IconButton(
onClick = { takePhoto(context, imageCapture) },
modifier = Modifier
.align(Alignment.BottomCenter)
.padding(32.dp)
) {
Icon(Icons.Default.PhotoCamera, contentDescription = "Take photo")
}
}提取 takePhoto()
将拍摄逻辑移到辅助函数中,让可组合函数保持简洁。该函数接收上下文和 ImageCapture 用例,构建输出选项并调用 takePicture。
fun takePhoto(context: Context, imageCapture: ImageCapture) {
val values = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, "IMG_${System.currentTimeMillis()}")
put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
}
val options = ImageCapture.OutputFileOptions.Builder(
context.contentResolver,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
values
).build()
imageCapture.takePicture(
options,
ContextCompat.getMainExecutor(context),
object : ImageCapture.OnImageSavedCallback {
override fun onImageSaved(o: ImageCapture.OutputFileResults) {}
override fun onError(e: ImageCaptureException) {}
}
)
}闪光灯与旋转
最后再完成两项设置:
- 闪光灯:将
imageCapture.flashMode设置为FLASH_MODE_ON、OFF或AUTO。 - 旋转:CameRX 会使用目标旋转角度,正确设置已保存 JPEG 的方向;请及时更新该值,以确保方向准确。
imageCapture.flashMode = ImageCapture.FLASH_MODE_AUTO
// Update target rotation when the device rotates:
imageCapture.targetRotation = display.rotation整合所有功能
完整的拍照流程如下:构建 ImageCapture → 将其与预览绑定 → 点按快门时,构建 OutputFileOptions 并调用 takePicture → 处理 onImageSaved / onError。
只需几行代码,您就能完成一个可将照片保存到图库的完整相机。
快速检查
请确认您已理解拍照流程。
回顾
现在,您已经可以使用 CameRX 拍摄并保存照片:
- 构建
ImageCapture用例,并将其与预览绑定。 - 使用
ContentValues和MediaStore描述输出,以使用分区存储。 - 将
OutputFileOptions、执行器和OnImageSavedCallback传给takePicture()。 - 成功时读取
savedUri;发生错误时处理ImageCaptureException。
接下来,您将使用 VideoCapture 用例录制视频。
常见问题解答
「拍照」课时是免费的吗?
是的 — 「拍照」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Android Academy 课程的其余内容,请升级到 CoddyKit PRO。 Android Academy 课程共包含 4 节课。
「拍照」这节课中我会学到什么?
捕获并保存图片 你通过在浏览器中直接运行的动手代码来练习 Android Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Android Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Android Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「拍照」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Android Academy 课中编写并运行代码吗?
能。每节 Android Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。