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

Android Camera2 API锁定AF后持续处于ACTIVE SCAN状态的解决咨询

解决Android AF锁定后停留在ACTIVE_SCAN状态的问题

问题根源分析

你的代码存在以下几个关键问题:

  1. 未处理AF_STATE_ACTIVE_SCAN状态:在STATE_WAIT_LOCK分支中,只判断了对焦锁定成功/失败的状态,完全忽略了AF_STATE_ACTIVE_SCAN,导致对焦一直在扫描时没有任何处理逻辑,程序陷入无限等待。
  2. 缺少AF扫描超时机制:没有设置超时逻辑,当硬件无法完成对焦时,不会主动终止扫描流程。
  3. unLockFocus方法不完整:仅取消了AF触发,但没有将AF模式重置回预览阶段的默认模式,导致后续对焦逻辑混乱。

具体修复方案

1. 添加AF扫描超时处理

在类中定义超时相关的Handler和Runnable:

private Handler mFocusTimeoutHandler = new Handler(Looper.getMainLooper());
private Runnable mFocusTimeoutRunnable = new Runnable() {
    @Override
    public void run() {
        if (mCaptureState == STATE_WAIT_LOCK) {
            // 超时后主动解锁对焦,重置状态
            unLockFocus();
            Log.w(TAG, "AF scan timed out, resetting focus state");
        }
    }
};

2. 修改lockFocus方法,启动超时任务

在触发AF扫描时启动超时计时(建议设置3-5秒,根据需求调整):

private void lockFocus(int focusLockState) {
    mCaptureState = STATE_WAIT_LOCK;
    mFocusLockState = focusLockState;
    // 先移除之前的超时任务,避免重复触发
    mFocusTimeoutHandler.removeCallbacks(mFocusTimeoutRunnable);
    // 启动5秒超时任务
    mFocusTimeoutHandler.postDelayed(mFocusTimeoutRunnable, 5000);
    
    mCaptureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_AUTO);
    mCaptureRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_START);
    CaptureRequest captureRequest = mCaptureRequestBuilder.build();
    try {
        mPreviewCaptureSession.capture(captureRequest, mPreviewCaptureCallback, mCameraThreadHandler);
    } catch (CameraAccessException e) {
        e.printStackTrace();
        // 异常时取消超时任务
        mFocusTimeoutHandler.removeCallbacks(mFocusTimeoutRunnable);
    }
}

3. 完善CaptureCallback的process方法,处理ACTIVE_SCAN状态

在STATE_WAIT_LOCK分支中增加对AF_STATE_ACTIVE_SCAN的判断,同时在对焦成功/失败时取消超时任务:

private void process(CaptureResult result) {
    switch (mCaptureState) {
        case STATE_PREVIEW:
            break;
        case STATE_WAIT_LOCK:
            Integer afState = result.get(CaptureResult.CONTROL_AF_STATE);
            if (afState == null) {
                mFocusTimeoutHandler.removeCallbacks(mFocusTimeoutRunnable);
                startStillCaptureRequest();
            } else if (CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED == afState ||
                    CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState) {
                // 对焦完成,取消超时任务
                mFocusTimeoutHandler.removeCallbacks(mFocusTimeoutRunnable);
                
                Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
                if (aeState == null ||
                        aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED) {
                    mCaptureState = STATE_PICTURE_TAKEN;
                    if (mFocusLockState == FOCUS_LOCK_STATE_TAKE_IMAGE) {
                        startStillCaptureRequest();
                    } else {
                        unLockFocus();
                    }
                } else {
                    runPrecaptureSequence();
                }
            } else if (CaptureResult.CONTROL_AF_STATE_ACTIVE_SCAN == afState) {
                // 正在扫描中,可以添加日志或其他处理,不改变状态
                Log.d(TAG, "AF is actively scanning...");
            }
            break;
        // 其他分支保持不变
        case STATE_WAITING_PRECAPTURE: {
            Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
            if (aeState == null ||
                    aeState == CaptureResult.CONTROL_AE_STATE_PRECAPTURE ||
                    aeState == CaptureRequest.CONTROL_AE_STATE_FLASH_REQUIRED) {
                mCaptureState = STATE_WAITING_NON_PRECAPTURE;
            }
            break;
        }
        case STATE_WAITING_NON_PRECAPTURE: {
            Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
            if (aeState == null || aeState != CaptureResult.CONTROL_AE_STATE_PRECAPTURE) {
                mCaptureState = STATE_PICTURE_TAKEN;
                startStillCaptureRequest();
            }
            break;
        }
    }
}

4. 修复unLockFocus方法,重置AF模式

取消AF触发后,将AF模式重置为预览阶段的默认模式(比如CONTROL_AF_MODE_CONTINUOUS_PICTURE,根据你的预览需求调整):

private void unLockFocus() {
    mCaptureState = STATE_PREVIEW;
    // 取消超时任务
    mFocusTimeoutHandler.removeCallbacks(mFocusTimeoutRunnable);
    
    mCaptureRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_CANCEL);
    // 重置AF模式为预览默认值
    mCaptureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
    CaptureRequest captureRequest = mCaptureRequestBuilder.build();
    try {
        mPreviewCaptureSession.capture(captureRequest, null, mCameraThreadHandler);
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}

额外建议

  • 测试不同场景下的超时时间,比如低光环境下可以适当延长超时时间
  • 在onCaptureFailed中也添加超时任务的取消逻辑,避免异常后任务仍在执行

内容的提问来源于stack exchange,提问作者AWSi-TS

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 04:05:40