Android Camera2 API锁定AF后持续处于ACTIVE SCAN状态的解决咨询
解决Android AF锁定后停留在ACTIVE_SCAN状态的问题
问题根源分析
你的代码存在以下几个关键问题:
- 未处理AF_STATE_ACTIVE_SCAN状态:在
STATE_WAIT_LOCK分支中,只判断了对焦锁定成功/失败的状态,完全忽略了AF_STATE_ACTIVE_SCAN,导致对焦一直在扫描时没有任何处理逻辑,程序陷入无限等待。 - 缺少AF扫描超时机制:没有设置超时逻辑,当硬件无法完成对焦时,不会主动终止扫描流程。
- 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
相关产品推荐
相关产品推荐

