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

Flutter Camera异常:CameraDevice已关闭致应用崩溃问题

Flutter camera插件录制后导航崩溃:CameraDevice was already closed

使用camera: ^0.10.0+4实现视频录制功能,流程为:在VideoRecordPage完成录制后点击继续,释放相机控制器并导航到仅含输入框的FormPage。页面导航成功,但在输入框输入时应用崩溃,报错日志如下:

I/Camera  (25833): startPreview
I/Camera  (25833): close
4
I/flutter (25833): last state body port: false
I/Camera  (25833): close
E/AndroidRuntime(25833): FATAL EXCEPTION: CameraBackground
E/AndroidRuntime(25833): Process: id.test.app.dev, PID: 25833
E/AndroidRuntime(25833): java.lang.IllegalStateException: CameraDevice was already closed
E/AndroidRuntime(25833):    at android.hardware.camera2.impl.CameraDeviceImpl.checkIfCameraClosedOrInError(CameraDeviceImpl.java:2347)
E/AndroidRuntime(25833):    at android.hardware.camera2.impl.CameraDeviceImpl.createCaptureSessionInternal(CameraDeviceImpl.java:684)
E/AndroidRuntime(25833):    at android.hardware.camera2.impl.CameraDeviceImpl.createCaptureSession(CameraDeviceImpl.java:669)
E/AndroidRuntime(25833):    at io.flutter.plugins.camera.Camera$DefaultCameraDeviceWrapper.createCaptureSession(Camera.java:175)
E/AndroidRuntime(25833):    at io.flutter.plugins.camera.Camera.createCaptureSessionWithSessionConfig(Camera.java:479)
E/AndroidRuntime(25833):    at io.flutter.plugins.camera.Camera.createCaptureSession(Camera.java:465)
E/AndroidRuntime(25833):    at io.flutter.plugins.camera.Camera.createCaptureSession(Camera.java:387)
E/AndroidRuntime(25833):    at io.flutter.plugins.camera.Camera.startPreview(Camera.java:1071)
E/AndroidRuntime(25833):    at io.flutter.plugins.camera.Camera$1.onOpened(Camera.java:322)
E/AndroidRuntime(25833):    at android.hardware.camera2.impl.CameraDeviceImpl$1.run(CameraDeviceImpl.java:165)
E/AndroidRuntime(25833):    at android.os.Handler.handleCallback(Handler.java:938)
E/AndroidRuntime(25833):    at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime(25833):    at android.os.Looper.loopOnce(Looper.java:201)
E/AndroidRuntime(25833):    at android.os.Looper.loop(Looper.java:288)
E/AndroidRuntime(25833):    at android.os.HandlerThread.run(HandlerThread.java:67)

问题原因

崩溃源于相机控制器释放不彻底,底层Camera2 API仍有回调尝试操作已关闭的CameraDevice:

  • 导航操作可能在相机控制器dispose()异步操作完成前执行,页面销毁后,相机插件后台线程仍在处理之前的相机打开/预览回调,此时CameraDevice已关闭,触发IllegalStateException。
  • 未正确移除相机控制器的状态监听,导致监听回调在控制器释放后仍被触发,进而调用相机相关方法。

解决方案

1. 完成释放流程后再导航

在点击继续按钮时,依次完成停止录制、移除监听、释放控制器的所有异步操作,再执行导航:

Future<void> _handleContinue() async {
  // 停止正在进行的录制(如果存在)
  if (_controller.value.isRecordingVideo) {
    await _controller.stopVideoRecording();
  }

  // 移除控制器的状态监听
  _controller.removeListener(_updateCameraState);

  // 等待控制器完全释放
  await _controller.dispose();

  // 确保当前页面仍挂载时再导航
  if (mounted) {
    Navigator.push(context, MaterialPageRoute(builder: (_) => FormPage()));
  }
}

2. 在页面销毁时彻底清理资源

重写VideoRecordPage的dispose()方法,确保相机资源被彻底清理:

@override
void dispose() {
  // 优先移除监听,避免回调触发
  _controller?.removeListener(_updateCameraState);
  // 释放控制器
  _controller?.dispose();
  super.dispose();
}

3. 避免释放后的相机操作

检查所有相机相关代码,通过_controller.value.isInitialized判断控制器状态,仅在活跃时执行操作,避免在dispose()后调用startPreview、startVideoRecording等方法。

关键说明

camera插件的Android底层依赖Camera2 API,其回调(如onOpened)运行在后台线程,若控制器释放后这些回调仍被触发,就会操作已关闭的CameraDevice导致崩溃。通过等待dispose完成+移除监听,可以彻底切断后续的相机操作触发路径。

内容的提问来源于stack exchange,提问作者Yusuf Fachroni

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 03:55:31