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

Camera2 API仅前5张照片可正常工作问题求助

解决Camera2 API手动模板下拍照多次后无响应的问题

首先,咱们先梳理下你遇到的核心问题:切换到CameraDevice.TEMPLATE_MANUAL模板后,前5次拍照能正常触发onCaptureCompleted,但之后就没响应,还触发错误码0的框架错误,且序列ID每次跳2,超过10就出问题。结合你的代码逻辑,我给你几个针对性的排查和解决方向:

1. 补全手动模板下的CaptureRequest核心参数

TEMPLATE_MANUAL不像预览或拍照模板会自动填充必要的捕获参数,你必须手动设置曝光时间、ISO、对焦模式、白平衡这些核心参数,否则相机框架可能无法正常处理请求,多次请求后会因为参数缺失积累错误。

你可以在创建mCaptureRequest(拍照请求)和mPreviewRequest(预览请求)时,确保设置了这些关键参数:

// 以拍照请求为例,手动设置基础参数
mCaptureRequest = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_MANUAL);
// 设置曝光时间(根据设备支持的范围,比如100000ns)
mCaptureRequest.set(CaptureRequest.SENSOR_EXPOSURE_TIME, 100000L);
// 设置ISO(比如100)
mCaptureRequest.set(CaptureRequest.SENSOR_SENSITIVITY, 100);
// 因为你不需要自动对焦,设置为固定对焦
mCaptureRequest.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_OFF);
// 白平衡设置为自动或固定值
mCaptureRequest.set(CaptureRequest.CONTROL_AWB_MODE, CaptureRequest.CONTROL_AWB_MODE_AUTO);
// 别忘了添加输出目标
mCaptureRequest.addTarget(mImageReader.getSurface());

2. 调整拍照流程,移除不必要的abortCaptures()调用

你的拍照逻辑里先调用stopRepeating(),接着立刻abortCaptures(),这可能会把刚提交的拍照请求也给终止掉,尤其是在框架还没来得及处理拍照请求的时候。多次调用abortCaptures()会打乱请求队列的顺序,导致后续请求无法正常触发回调。

建议修改拍照流程,确保预览停止后再提交拍照请求:

// 先停止重复预览,等待停止完成后再提交拍照请求
mCaptureSession.stopRepeating(new CameraCaptureSession.StateCallback() {
    @Override
    public void onConfigured(@NonNull CameraCaptureSession session) {
        // 预览已停止,提交拍照请求
        session.capture(mCaptureRequest, captureCallback, mBackgroundHandler);
    }

    @Override
    public void onConfigureFailed(@NonNull CameraCaptureSession session) {
        showToast("Stop preview failed");
    }
});

如果必须用abortCaptures(),也要放在stopRepeating的回调里确认预览停止后再执行,避免竞态条件。

3. 简化unlockFocus()逻辑,移除多余的单次预览请求

序列ID每次递增2,说明每次拍照时,除了你的拍照请求,还有一个额外的请求被提交——大概率是unlockFocus()里的mCaptureSession.capture(mPreviewRequest, null, mBackgroundHandler)这个单次预览请求。这个请求会和重复预览请求一起占用序列ID,多次积累后导致框架请求队列异常。

建议修改unlockFocus()逻辑,直接恢复重复预览即可:

private void unlockFocus() {
    // 不需要先提交单次预览请求,直接恢复重复预览
    mCaptureSession.setRepeatingRequest(mPreviewRequest, mPreviewCaptureCallback, mBackgroundHandler);
}

stopRepeating()后相机会话处于空闲状态,直接设置重复请求就能恢复预览,额外的单次请求只会增加不必要的队列负担。

4. 捕获框架错误的详细信息

错误码0是框架错误,你可以在onCaptureFailed里打印更详细的错误信息,帮你定位具体问题:

@Override
public void onCaptureFailed(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull CaptureFailure failure) {
    super.onCaptureFailed(session, request, failure);
    Log.e("Camera2", "Capture failed: reason=" + failure.getReason() + ", seqId=" + failure.getSequenceId());
    // 尝试恢复会话
    unlockFocus();
}

5. 确保ImageReader的Surface资源及时释放

多次拍照后,mImageReader的Surface可能因为缓存满了或者未及时处理图像数据而异常。你需要确保OnImageAvailableListener里及时关闭图像:

mImageReader.setOnImageAvailableListener(reader -> {
    Image image = reader.acquireLatestImage();
    if (image != null) {
        // 处理图像数据...
        image.close(); // 必须关闭,否则会导致Surface资源耗尽
    }
}, mBackgroundHandler);

按照这几个方向调整后,应该能解决多次拍照后无响应的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:29:18