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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 21:50:21