基于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
相关产品推荐
相关产品推荐

