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

基于OpenCV Android教程修改预览分辨率后应用频繁崩溃求助

解决OpenCV Android硬设预览分辨率后频繁崩溃的问题

我来帮你拆解下这个问题——你遇到的IllegalStateException: Session has been closed崩溃,本质是硬编码640x480分辨率时,破坏了Camera2会话和预览控件的适配逻辑,导致会话被系统强制关闭。下面是具体的原因分析和解决方案:

为什么会崩溃?

你直接注释掉calcPreviewSize函数的操作,跳过了OpenCV官方教程里的核心适配逻辑:

  • 这个函数的作用是匹配相机支持的分辨率和预览控件(SurfaceView/TextureView)的尺寸比例,避免出现分辨率和显示控件不兼容的情况。
  • Camera2的CaptureSession对配置一致性要求极高,如果预览分辨率和Surface的尺寸比例不匹配,或者资源加载出现冲突,系统会直接关闭会话,触发未捕获的IllegalStateException。
  • 虽然你看到预览成功了,但这种适配缺失会在相机状态变更(比如后台切前台、屏幕旋转)时触发崩溃。

具体解决方案

方案1:修改calcPreviewSize,优先选择640x480

不要直接删除这个函数,而是修改它的逻辑,让它优先返回你想要的640x480,同时保留原有的适配逻辑作为 fallback:

private Size calcPreviewSize(List<Size> sizes, int width, int height) {
    // 优先查找640x480分辨率
    for (Size size : sizes) {
        if (size.getWidth() == 640 && size.getHeight() == 480) {
            return size;
        }
    }
    // 如果找不到目标分辨率,执行原教程的适配逻辑(保证和控件比例匹配)
    Size optimalSize = null;
    float targetRatio = (float) width / height;
    float minDiff = Float.MAX_VALUE;

    for (Size size : sizes) {
        float ratio = (float) size.getWidth() / size.getHeight();
        if (Math.abs(ratio - targetRatio) < minDiff) {
            minDiff = Math.abs(ratio - targetRatio);
            optimalSize = size;
        }
    }
    return optimalSize;
}

这样既保证了用你需要的分辨率,又不会破坏Camera2会话的兼容性。

方案2:强制预览控件和640x480比例一致

640x480是4:3的比例,你可以在布局里给预览控件设置固定的宽高比,避免尺寸不匹配:

<!-- 比如使用TextureView作为预览控件 -->
<TextureView
    android:id="@+id/camera_preview"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_aspectRatio="4:3"
    app:layout_constraintTop_toTopOf="parent" />

如果你的设备API低于26,可以在代码里动态计算控件尺寸,保证4:3的比例。

方案3:添加会话崩溃后的重试逻辑(治标)

如果暂时无法修改适配逻辑,可以在错误回调里添加重试机制,避免直接崩溃:
在JavaCamera2View的错误处理部分修改:

@Override
public void onConfigureFailed(CameraCaptureSession session) {
    Log.e(TAG, "createCaptureSession failed " + e.getMessage());
    // 延迟1秒后重新初始化相机
    postDelayed(() -> {
        stopCamera();
        startCamera();
    }, 1000);
}

注意:这只是临时解决方案,优先用前两个方法解决根本问题。

额外注意事项

  • 确认设备真的支持640x480预览:可以通过CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP获取所有支持的尺寸,打印出来验证。
  • 不要忽略Camera2的状态回调:一定要处理onClosed、onError等回调,避免未捕获异常导致崩溃。

内容的提问来源于stack exchange,提问作者Alex Yo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:23:39