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

Flutter:使用just_audio播放音频,杀死应用后仍后台播放如何解决

解决 just_audio 后台杀死应用后音乐继续播放的问题

核心思路

Flutter 的 AppLifecycleState.detached 在应用被主动杀死时触发不可靠,尤其是 Android 任务管理器杀进程场景。需要依赖原生平台的生命周期回调通知 Flutter 安全停止播放并释放资源,避免内存泄漏。


1. Android 端:监听任务移除事件

在 MainActivity 中重写 onTaskRemoved 方法(应用从最近任务列表被移除时触发),通过 MethodChannel 通知 Flutter 停止播放,并终止后台音频服务。

class MainActivity : FlutterActivity() {
    private val CHANNEL = "com.your.package.audio_control"

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
            if (call.method == "stopAudio") {
                result.success(null)
            }
        }
    }

    override fun onTaskRemoved(rootIntent: Intent?) {
        super.onTaskRemoved(rootIntent)
        flutterEngine?.let { engine ->
            val channel = MethodChannel(engine.dartExecutor.binaryMessenger, CHANNEL)
            channel.invokeMethod("stopAudio", null)
            // 终止后台音频服务,确保通知栏移除
            stopService(Intent(this, YourBackgroundAudioService::class.java))
        }
    }
}

2. iOS 端:监听应用终止事件

在 AppDelegate 中重写 applicationWillTerminate 方法(应用即将终止时触发),通过 MethodChannel 通知 Flutter 停止播放。

import UIKit
import Flutter

@UIApplicationMain
class AppDelegate: FlutterAppDelegate {
    let CHANNEL = "com.your.package.audio_control"

    override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        guard let controller = window?.rootViewController as? FlutterViewController else {
            return super.application(application, didFinishLaunchingWithOptions: launchOptions)
        }
        let channel = FlutterMethodChannel(name: CHANNEL, binaryMessenger: controller.binaryMessenger)
        channel.setMethodCallHandler { call, result in
            if call.method == "stopAudio" {
                result(nil)
            }
        }
        GeneratedPluginRegistrant.register(with: self)
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }

    override func applicationWillTerminate(_ application: UIApplication) {
        guard let controller = window?.rootViewController as? FlutterViewController else { return }
        let channel = FlutterMethodChannel(name: CHANNEL, binaryMessenger: controller.binaryMessenger)
        channel.invokeMethod("stopAudio", arguments: nil)
    }
}

3. Flutter 端:安全停止并释放播放器

通过 MethodChannel 接收原生指令,在 UI 未销毁的安全时机停止播放、释放播放器资源,避免内存泄漏。

import 'package:flutter/services.dart';
import 'package:just_audio/just_audio.dart';
import 'package:just_audio_background/just_audio_background.dart';

class AudioPlayerManager {
  static const MethodChannel _audioControlChannel = MethodChannel('com.your.package.audio_control');
  AudioPlayer? _player;

  Future<void> initPlayer() async {
    _player = AudioPlayer();
    // 初始化后台播放配置(示例)
    await _player!.setAudioSource(
      AudioSource.uri(Uri.parse('your_audio_url')),
      metadata: const MediaMetadata(title: "示例音频"),
    );

    // 监听原生传来的停止指令
    _audioControlChannel.setMethodCallHandler((call) async {
      if (call.method == 'stopAudio') {
        await _stopAndDisposePlayer();
      }
    });
  }

  Future<void> _stopAndDisposePlayer() async {
    if (_player != null) {
      await _player!.stop();
      await _player!.dispose();
      _player = null;
      // 确保通知栏移除,just_audio_background 通常会自动处理,若未生效可手动触发
      await AudioService.stop();
    }
  }
}

关键注意事项

  • 不要在 AppLifecycleState.detached 中操作播放器:此时 Flutter UI 已销毁,资源引用失效,易引发内存泄漏。
  • 确保 just_audio_background 配置正确:播放器停止并释放后,通知栏应自动消失,若未消失,可调用 AudioService.stop() 强制终止后台服务。

内容的提问来源于stack exchange,提问作者Md Usama

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 19:15:30