Android扫码调用startPreview出现RuntimeException崩溃问题咨询
问题原因分析
- 核心原因是异常捕获范围不足:Google Play Services Vision库的
CameraSource.start()方法仅声明抛出受检异常IOException,因此现有代码大概率只捕获了IOException,但系统相机APIandroid.hardware.Camera.startPreview()抛出的是不受检的RuntimeException,不在你的捕获范围内,因此会直接触发崩溃。 - 其他触发
startPreview failed的常见场景:- 调用启动逻辑时,相机硬件已被其他应用占用
- SurfaceView/TextureView的渲染层还未完成初始化就调用了启动逻辑
- 设置的预览分辨率不在当前设备相机支持的分辨率列表内
- 调用启动方法前,Camera实例已经被释放、处于无效状态
- LiveData异步回调时机晚于页面生命周期,相机已经释放后才触发启动逻辑
解决方案
- 扩大异常捕获范围
修改startCameraSource方法的异常捕获逻辑,在原有IOException捕获逻辑之外,新增RuntimeException的捕获,也可以添加Exception作为兜底,捕获所有启动阶段的异常,捕获后执行友好提示、关闭扫描页面、回收相机资源等降级逻辑:
try { cameraSource.start(surfaceHolder); } catch (IOException e) { // 原有IO异常处理逻辑 } catch (RuntimeException e) { // 新增捕获相机启动运行时异常,避免崩溃 Log.e(TAG, "相机启动失败", e); // 执行降级逻辑,比如提示用户无法启动相机,关闭当前页面 }
- 增加启动前状态校验
调用cameraSource.start()之前,先校验两个前提:一是SurfaceHolder已经完成初始化(已收到surfaceCreated回调),二是当前页面处于活跃状态、相机资源没有被提前释放。 - 适配预览分辨率
不要硬编码预览尺寸,先调用Camera.Parameters.getSupportedPreviewSizes()获取当前设备支持的所有预览分辨率,选择和你的布局尺寸最接近的分辨率设置,避免不支持的尺寸导致启动失败。 - 相机库迁移(可选优化)
老的android.hardware.CameraAPI已经被官方废弃,Google Vision库也停止维护,建议迁移到Jetpack CameraX库,该库对不同设备的兼容性做了大量适配,异常处理机制更完善,能大幅降低相机相关崩溃率。
内容的提问来源于stack exchange,提问作者Morozov
相关产品推荐
相关产品推荐

