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

Camera2 API自动对焦锁定异常:调用AF后连拍卡顿问题

问题分析与修复方案

核心问题定位

从日志可见,afState持续为4(对应CaptureResult.CONTROL_AF_STATE_ACTIVE_SCAN),说明自动对焦始终处于扫描状态,未完成锁定。lockFocus()中focusLockLatch.await(500, TimeUnit.MILLISECONDS)超时后触发unlockFocus(),但流程中的线程处理、锁机制存在多处问题,最终导致拍摄时卡顿。

具体问题点及修复

1. focusLockLatch初始化时机错误

process()方法中才初始化focusLockLatch,但lockFocus()里已提前调用await(),会导致空指针或等待永远无法触发。

修复:
在lockFocus()触发对焦前初始化focusLockLatch:

protected void lockFocus() {
    Log.v(TAG, "lockFocus()");

    if (mCaptureSession == null) {
        return;
    }
    try {
        if (focusMode == Mode.AUTO) {
            // 提前初始化CountDownLatch
            focusLockLatch = new CountDownLatch(1);
            mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START);
            mState = STATE_WAITING_LOCK;
            mCaptureSession.capture(mPreviewRequestBuilder.build(), mCaptureCallback, mBackgroundHandler);

            if (focusLockLatch.await(500, TimeUnit.MILLISECONDS)) {
                startCapture();
            } else {
                unlockFocus();
            }
        } else {
            startCapture();
        }
    } catch (CameraAccessException e) {
        OnCameraErrorListener.handle(mCameraErrorCallback, e);
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }
}

同时移除process()中的初始化代码:

// 删除这段冗余初始化
if (focusLockLatch == null) {
    focusLockLatch = new CountDownLatch(1);
}

2. lockFocus()中await()阻塞主线程

若lockFocus()在主线程调用,await()会直接阻塞UI线程,引发应用卡顿。

修复:
将lockFocus()的核心逻辑移至后台线程执行,避免阻塞主线程:

protected void lockFocus() {
    Log.v(TAG, "lockFocus()");

    if (mCaptureSession == null) {
        return;
    }
    if (focusMode != Mode.AUTO) {
        startCapture();
        return;
    }
    // 切换到后台线程处理对焦等待逻辑
    mBackgroundHandler.post(() -> {
        try {
            focusLockLatch = new CountDownLatch(1);
            mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START);
            mState = STATE_WAITING_LOCK;
            mCaptureSession.capture(mPreviewRequestBuilder.build(), mCaptureCallback, mBackgroundHandler);

            if (focusLockLatch.await(500, TimeUnit.MILLISECONDS)) {
                // 若startCapture涉及UI操作,切回主线程执行
                runOnUiThread(this::startCapture);
            } else {
                runOnUiThread(this::unlockFocus);
            }
        } catch (CameraAccessException e) {
            OnCameraErrorListener.handle(mCameraErrorCallback, e);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    });
}

3. 重复定义unlockFocus()方法

代码中存在两个完全相同的unlockFocus()方法,编译时会报错,运行时也会导致逻辑混乱。

修复:
删除其中一个重复的方法,仅保留一份即可。

4. 自动对焦触发逻辑冗余

autoFocus()中调用setRepeatingRequest()触发对焦,lockFocus()中又再次触发一次对焦,导致对焦流程冲突。

修复:
调整流程:让autoFocus()仅负责启动对焦扫描,lockFocus()仅负责等待锁定状态并触发拍摄,避免重复触发对焦。

5. unlockFocus()中未重置focusLockLatch

未重置focusLockLatch会导致下一次对焦时状态异常。

修复:
在unlockFocus()末尾添加重置逻辑:

focusLockLatch = null;

额外优化建议

  • 增加对焦超时后的重试逻辑,避免单次超时就放弃对焦
  • 检查startCapture()方法,确保拍摄的耗时操作在后台线程执行
  • 日志中添加CONTROL_AF_MODE的打印,确认对焦模式设置正确

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 09:52:33