Flutter Camera视频录制后台暂停恢复异常问题求助
问题分析与解决方案
问题描述
开发Flutter视频录制功能,需求为:用户启动录制后切至后台,录制自动暂停;返回应用时恢复录制。当前60秒内返回功能正常,但超过60秒返回时出现以下日志:
open | onError open | onClosed
同时触发空指针异常:
E/MethodChannel#plugins.flutter.io/camera_android( 4852): java.lang.NullPointerException: Attempt to invoke virtual method 'void android.media.MediaRecorder.resume()' on a null object reference E/MethodChannel#plugins.flutter.io/camera_android( 4852): at io.flutter.plugins.camera.Camera.resumeVideoRecording(Camera.java:820) E/MethodChannel#plugins.flutter.io/camera_android( 4852): at io.flutter.plugins.camera.MethodCallHandlerImpl.onMethodCall(MethodCallHandlerImpl.java:136) E/MethodChannel#plugins.flutter.io/camera_android( 4852): at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:262) E/MethodChannel#plugins.flutter.io/camera_android( 4852): at io.flutter.embedding.engine.dart.DartMessenger.invokeHandler(DartMessenger.java:295) E/MethodChannel#plugins.flutter.io/camera_android( 4852): at io.flutter.embedding.engine.dart.DartMessenger.lambda$dispatchMessageToQueue$0$io-flutter-embedding-engine-dart-DartMessenger(DartMessenger.java:319) E/MethodChannel#plugins.flutter.io/camera_android( 4852): at io.flutter.embedding.engine.dart.DartMessenger$$ExternalSyntheticLambda0.run(Unknown Source:12) E/MethodChannel#plugins.flutter.io/camera_android( 4852): at android.os.Handler.handleCallback(Handler.java:938) E/MethodChannel#plugins.flutter.io/camera_android( 4852): at android.os.Handler.dispatchMessage(Handler.java:99) E/MethodChannel#plugins.flutter.io/camera_android( 4852): at android.os.Looper.loopOnce(Looper.java:201) E/MethodChannel#plugins.flutter.io/camera_android( 4852): at android.os.Looper.loop(Looper.java:288) E/MethodChannel#plugins.flutter.io/camera_android( 4852): at android.app.ActivityThread.main(ActivityThread.java:7839) E/MethodChannel#plugins.flutter.io/camera_android( 4852): at java.lang.reflect.Method.invoke(Native Method) E/MethodChannel#plugins.flutter.io/camera_android( 4852): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) E/MethodChannel#plugins.flutter.io/camera_android( 4852): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
原因分析
这是Android系统资源回收机制导致的:当应用后台停留超过系统阈值(此处为60秒),系统会主动回收相机相关资源,包括MediaRecorder实例。此时应用返回前台调用resume()时,MediaRecorder已被销毁为null,因此触发空指针异常。
解决方案
1. 生命周期监听+主动资源管理
通过WidgetsBindingObserver监听应用生命周期,进入后台时启动计时,超过60秒则主动停止录制并释放相机、MediaRecorder资源,同时记录当前录制文件路径和时长;返回前台时根据停留时长处理:
- 停留时长≤60秒:直接恢复录制
- 停留时长>60秒:重新初始化相机和
MediaRecorder,从之前的录制文件末尾续录(需支持追加录制),或提示用户重新开始录制。
示例代码片段:
class _RecordingPageState extends State<RecordingPage> with WidgetsBindingObserver { DateTime? _backgroundEnterTime; bool _isRecorderReleased = false; String? _currentRecordingPath; int _recordedDuration = 0; @override void initState() { super.initState(); WidgetsBinding.instance.addObserver(this); } @override void dispose() { WidgetsBinding.instance.removeObserver(this); super.dispose(); } @override void didChangeAppLifecycleState(AppLifecycleState state) { super.didChangeAppLifecycleState(state); switch (state) { case AppLifecycleState.paused: _backgroundEnterTime = DateTime.now(); _pauseRecording(); // 延迟60秒释放资源 Future.delayed(const Duration(seconds: 60), () { if (mounted && !_isRecorderReleased) { _releaseRecorder(); _isRecorderReleased = true; } }); break; case AppLifecycleState.resumed: if (_backgroundEnterTime != null) { final stayDuration = DateTime.now().difference(_backgroundEnterTime!); if (stayDuration.inSeconds <= 60 && !_isRecorderReleased) { _resumeRecording(); } else { _reinitRecorderAndContinue(); } } break; default: break; } } void _pauseRecording() { // 调用camera插件的暂停录制方法 } void _releaseRecorder() { // 调用camera插件的停止录制并释放资源方法,保存当前录制路径和时长 } void _resumeRecording() { // 调用camera插件的恢复录制方法 } void _reinitRecorderAndContinue() { // 重新初始化相机和MediaRecorder,设置追加录制模式,从已录制时长续录 } }
2. 原生层增加空值检查(可修改插件时使用)
若能修改camera_android插件源码,在resumeVideoRecording方法中增加MediaRecorder空值判断:
public void resumeVideoRecording() { if (mediaRecorder == null) { onError(new CameraException(CameraErrorCode.RECORDER_ERROR, "MediaRecorder已被释放")); return; } mediaRecorder.resume(); }
这样Flutter层可收到错误回调,进而处理重新初始化逻辑。
3. 优化资源释放策略
不要依赖系统被动回收,主动根据后台停留时长决定资源保留逻辑:短时间后台仅暂停录制,长时间后台彻底释放资源,避免系统强制回收引发的异常。
内容的提问来源于stack exchange,提问作者GAURAV KATKAR
相关产品推荐
相关产品推荐

