You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android/Temi机器人CameraX拍照DeferrableSurface聚焦异常问题

问题分析与解决方案

问题概述

开发的Temi机器人自定义Android应用,通过CameraX 1.3.0实现移动拍照功能,在白墙、纯色墙面、近距离物体等难对焦场景下,会随机出现拍照失败甚至应用崩溃的情况,仅在失败时出现DeferrableSurface相关日志,无其他明确错误提示。已排除内存问题,升级CameraX版本后问题仍存在。

技术环境

  • MinSdkVersion: 24
  • Target SDK version: 33
  • 语言兼容: Java 1.8 / Kotlin 1.8.22
  • CameraX版本: 1.3.0

解决方案

1. 优化对焦策略,添加超时与 fallback

难对焦场景下自动对焦可能无法锁定,可强制触发单次对焦并设置超时,超时后切换至手动固定焦距:

// 初始化对焦控制器,以屏幕中心为对焦点
val autoFocusPoint = SurfaceOrientedMeteringPointFactory(
    previewView.width.toFloat(), previewView.height.toFloat()
).createPoint(0.5f, 0.5f)

val focusMeteringAction = FocusMeteringAction.Builder(
    autoFocusPoint,
    FocusMeteringAction.FLAG_AF
).apply {
    // 设置3秒对焦超时
    setAutoCancelDuration(3000, TimeUnit.MILLISECONDS)
}.build()

// 执行对焦并监听结果
camera?.cameraControl?.startFocusAndMetering(focusMeteringAction)
    ?.addListener({ result ->
        if (!result.isFocusSuccessful) {
            // 对焦失败,切换到固定焦距(可根据场景调整参数)
            camera?.cameraControl?.setLinearZoom(0.5f)
        }
        // 对焦完成后执行拍照
        takePicture()
    }, ContextCompat.getMainExecutor(context))

2. 捕获拍照异常,避免应用崩溃

在拍照回调中捕获所有异常,包括DeferrableSurface相关错误,防止应用崩溃并可添加重试逻辑:

private fun takePicture() {
    val outputOptions = ImageCapture.OutputFileOptions.Builder(getOutputFile()).build()
    imageCapture.takePicture(
        outputOptions,
        ContextCompat.getMainExecutor(context),
        object : ImageCapture.OnImageSavedCallback {
            override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
                // 拍照成功逻辑
            }

            override fun onError(exception: ImageCaptureException) {
                Log.e("CameraX", "拍照失败", exception)
                // 可添加有限次数的重试逻辑
                retryTakePicture()
            }
        }
    )
}

3. 确保拍照前Surface就绪

检查预览Surface的有效性,确认就绪后再执行拍照,避免因Surface未初始化导致的错误:

private fun checkSurfaceReadyThenTakePicture() {
    val surface = previewView.surfaceProvider.surface
    if (surface.isValid) {
        takePicture()
    } else {
        // 延迟500ms重试
        Handler(Looper.getMainLooper()).postDelayed({
            checkSurfaceReadyThenTakePicture()
        }, 500)
    }
}

4. 配置连续自动对焦模式

在CameraX初始化阶段,设置连续自动对焦模式,提升复杂场景下的对焦稳定性:

val cameraProviderFuture = ProcessCameraProvider.getInstance(context)
cameraProviderFuture.addListener({
    val cameraProvider = cameraProviderFuture.get()
    val preview = Preview.Builder().build().also {
        it.setSurfaceProvider(previewView.surfaceProvider)
    }
    val imageCapture = ImageCapture.Builder()
        .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
        .build()
    val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA

    // 绑定生命周期并设置连续自动对焦
    val camera = cameraProvider.bindToLifecycle(
        this, cameraSelector, preview, imageCapture
    )
    camera.cameraControl.setMode(CameraControl.FOCUS_MODE_CONTINUOUS_PICTURE)
}, ContextCompat.getMainExecutor(context))

内容的提问来源于stack exchange,提问作者Justinfailber

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 07:42:01