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

