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

Flutter中相机被其他应用占用时的崩溃问题及错误处理求助

解决Flutter Camera包被其他应用占用导致崩溃的问题

1. 先接住初始化阶段的异常

相机被其他应用占用时,调用cameraController.initialize()大概率会直接抛出异常,你之前的监听只关注初始化后的状态变化,根本抓不到这个阶段的错误。必须用try-catch包裹初始化代码:

try {
  await cameraController.initialize();
  // 初始化成功后再添加监听
  cameraController.addListener(_cameraListener);
} on CameraException catch (e) {
  // 直接提示用户相机被占用
  showInSnackBar('相机打不开:${e.description}');
  // 及时释放controller资源
  await cameraController.dispose();
}

2. 优化监听逻辑,紧盯相机状态变化

除了错误状态,还要监听isInitialized——相机被抢占后这个值会变为false,得及时处理:

void _cameraListener() {
  if (!mounted) return;
  
  setState(() {});
  
  final cameraValue = cameraController.value;
  if (cameraValue.hasError) {
    showInSnackBar('相机出错:${cameraValue.errorDescription}');
    _disposeCamera();
  }
  
  // 处理相机突然被销毁的情况
  if (!cameraValue.isInitialized) {
    showInSnackBar('相机被其他应用占用了');
    _disposeCamera();
  }
}

// 封装释放相机资源的方法,方便复用
Future<void> _disposeCamera() async {
  if (cameraController.value.isInitialized) {
    await cameraController.dispose();
  }
}

3. 跟着App生命周期走,后台主动释放相机

App切到后台时,其他应用很容易抢占相机资源,所以要在生命周期变化时主动释放:

@override
void didChangeAppLifecycleState(AppLifecycleState state) {
  super.didChangeAppLifecycleState(state);
  
  if (cameraController == null || !cameraController.value.isInitialized) {
    return;
  }
  
  switch (state) {
    case AppLifecycleState.paused:
      // 切后台立即释放相机
      cameraController.dispose();
      break;
    case AppLifecycleState.resumed:
      // 切回前台重新初始化相机
      _initCamera();
      break;
    default:
      break;
  }
}

// 封装相机初始化逻辑
Future<void> _initCamera() async {
  final cameras = await availableCameras();
  final targetCamera = cameras.first;
  
  cameraController = CameraController(
    targetCamera,
    ResolutionPreset.medium,
  );
  
  try {
    await cameraController.initialize();
    if (mounted) {
      setState(() {});
      cameraController.addListener(_cameraListener);
    }
  } on CameraException catch (e) {
    showInSnackBar('相机启动失败:${e.description}');
  }
}

4. 加全局异常兜底,避免直接崩溃

如果还有漏网的异常,就加个全局处理器,不让App直接崩掉:

void main() {
  FlutterError.onError = (FlutterErrorDetails details) {
    FlutterError.presentError(details);
    // 这里可以记录日志或给用户提示
    if (details.exception is CameraException) {
      print('全局捕获相机错误:${details.exception.toString()}');
    }
  };
  
  runApp(MyApp());
}

最后补个关键细节

页面销毁时一定要彻底清理相机资源:

@override
void dispose() {
  cameraController?.removeListener(_cameraListener);
  cameraController?.dispose();
  super.dispose();
}

测试时可以打开微信视频通话,切回自己的App,验证异常处理逻辑是否正常触发。

内容的提问来源于stack exchange,提问作者Vinh Bui

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 01:10:28