设备能力
设备能力 · androidx.camera
CameraX:用 use case 组装相机Camera 1.7.0-alpha03
PreviewView、Preview、ImageCapture、ImageAnalysis 与 VideoCapture 的完整管线。
最后更新 2026-08-01
复制即用:预览 + 拍照
class CameraFragment : Fragment() {
private var imageCapture: ImageCapture? = null
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val previewView = view.findViewById<PreviewView>(R.id.preview_view)
val providerFuture = ProcessCameraProvider.getInstance(requireContext())
providerFuture.addListener({
val provider = providerFuture.get()
val preview = Preview.Builder().build().also {
it.surfaceProvider = previewView.surfaceProvider
}
imageCapture = ImageCapture.Builder().build()
provider.unbindAll()
provider.bindToLifecycle(
viewLifecycleOwner,
CameraSelector.DEFAULT_BACK_CAMERA,
preview,
imageCapture,
)
}, ContextCompat.getMainExecutor(requireContext()))
}
fun takePhoto(onSaved: (Uri) -> Unit) {
val capture = imageCapture ?: return
val name = "photo_${System.currentTimeMillis()}.jpg"
val options = ImageCapture.OutputFileOptions.Builder(
File(externalMediaDirs.first(), name)
).build()
capture.takePicture(
options,
ContextCompat.getMainExecutor(requireContext()),
object : ImageCapture.OnImageSavedCallback {
override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
outputFileResults.savedUri?.let(onSaved)
}
override fun onError(exc: ImageCaptureException) {
// 处理错误
}
},
)
}
}四个 use case
| Use Case | 职责 |
|---|---|
Preview | 预览输出(绑定 surfaceProvider) |
ImageCapture | 单张照片 |
ImageAnalysis | 逐帧分析(二维码、人脸) |
VideoCapture | 录像 |
不要把所有工作塞进预览回调——每类 use case 职责独立。
ImageAnalysis:记得关闭帧
val analysis = ImageAnalysis.Builder()
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.build()
analysis.setAnalyzer(Executors.newSingleThreadExecutor()) { imageProxy ->
// 处理 imageProxy
try {
val buffer = imageProxy.planes[0].buffer
// ... 分析
} finally {
imageProxy.close() // 必须关闭,否则阻塞后续帧
}
}- 每个
ImageProxy处理完必须close()。 STRATEGY_KEEP_ONLY_LATEST:分析跟不上时丢弃旧帧保最新。- 分析器放独立线程(别阻塞相机回调)。
CameraSelector:前后摄
// 后摄(默认)
CameraSelector.DEFAULT_BACK_CAMERA
// 前摄
CameraSelector.DEFAULT_FRONT_CAMERA
// 根据需求选(如有前置摄像头)
val selector = CameraSelector.Builder()
.requireLensFacing(CameraSelector.LENS_FACING_FRONT)
.build()生命周期绑定
bindToLifecycle 把 use case 绑定到 LifecycleOwner:
- Fragment 用
viewLifecycleOwner(View 销毁解绑)。 - Activity 用
this。 - 离开页面自动释放相机;
unbindAll()手动释放。
常见陷阱
- 权限没申请:CameraX 不绕过平台权限,先
CAMERA权限。 - 忘 close ImageProxy:后续帧全阻塞。
- bindToLifecycle 用错 owner:用 Fragment lifecycle 而非 viewLifecycleOwner,View 销毁后相机还在。
- 拍照 URI 用错目录:
externalMediaDirs是 MediaStore 不可见的文件目录;要进相册用 MediaStore 或PickVisualMedia。 - provider 单例:
ProcessCameraProvider.getInstance是单例,重复拿无副作用。
依赖
implementation("androidx.camera:camera-core:1.7.0-alpha03")
implementation("androidx.camera:camera-camera2:1.7.0-alpha03")
implementation("androidx.camera:camera-lifecycle:1.7.0-alpha03")
implementation("androidx.camera:camera-view:1.7.0-alpha03")要点
- 四个 use case 各司其职;provider 绑定生命周期。
- ImageProxy 必须 close;KEEP_ONLY_LATEST 保最新帧。
- 权限与硬件独占需自行处理;CameraX 不做这些。
- Fragment 用 viewLifecycleOwner 绑定。