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

ARCORE与Camera2 API共享相机拍照报未配置Surface错误如何解决?

问题根因

该异常核心是拍照用的ImageReader的Surface未被正确纳入CameraCaptureSession的输出配置,结合ARCore共享相机场景,代码存在三处典型错误:

  • 拍照用ImageReader在shotPhoto触发时才动态创建,此时预览对应的CameraCaptureSession已完成初始化,会话未包含该新增Surface,直接作为捕获请求目标就会触发未配置异常
  • 调用sharedCamera.setAppSurfaces时仅传入拍照用Surface,会覆盖之前已配置的预览用Surface,且调用后未等待ARCore完成配置、未重建捕获会话就直接发起请求
  • 获取输出尺寸时使用SurfaceTexture.class对应的配置,但ImageReader实际使用ImageFormat.JPEG格式,两者尺寸规则不匹配可能导致Surface本身无效

修复方案

1. 提前初始化拍照ImageReader

在相机初始化阶段(和预览ImageReader创建同阶段)就完成拍照ImageReader的创建,获取尺寸时匹配JPEG格式:

// 相机初始化阶段执行,不要放在shotPhoto方法内
CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(this.cameraId);
StreamConfigurationMap streamConfigurationMap = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
// 取JPEG格式对应的输出尺寸,不要用SurfaceTexture.class
Size[] jpegSizes = streamConfigurationMap.getOutputSizes(ImageFormat.JPEG);
// 按需选择分辨率,示例取第一个最大分辨率
Size captureSize = jpegSizes[0];
// 全局持有captureReader实例
captureReader = ImageReader.newInstance(
        captureSize.getWidth(),
        captureSize.getHeight(),
        ImageFormat.JPEG,
        2
);
captureReader.setOnImageAvailableListener(this, backgroundHandler);

2. 全量传入Surface给ARCore和捕获会话

调用setAppSurfaces时一次性传入所有需要用到的Surface(预览+拍照),同时创建CameraCaptureSession时也将两个Surface都作为输出参数传入:

// ARCore共享相机配置阶段执行
sharedCamera.setAppSurfaces(this.cameraId, Arrays.asList(previewReader.getSurface(), captureReader.getSurface()));

// 创建CameraCaptureSession时传入所有输出Surface
cameraDevice.createCaptureSession(Arrays.asList(previewReader.getSurface(), captureReader.getSurface()), sessionStateCallback, backgroundHandler);

3. 简化拍照逻辑

拍照时直接使用提前初始化好的captureReader的Surface作为捕获目标即可:

public void shotPhoto() {
    try {
        CaptureRequest.Builder captureRequestBuilder = cameraDevice.createCaptureRequest(cameraDevice.TEMPLATE_STILL_CAPTURE);
        captureRequestBuilder.addTarget(captureReader.getSurface());
        captureRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION, SensorOrientation);
        CaptureRequest captureRequest = captureRequestBuilder.build();
        captureSession.capture(captureRequest, cameraCaptureCallback, backgroundHandler);
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}

补充说明

如果业务必须动态添加拍照Surface,调用setAppSurfaces后必须等待ARCore共享相机的配置完成回调,再重建CameraCaptureSession加入新的Surface,之后才能发起捕获请求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 00:15:04