Flutter audioplayers 3.0.1 Windows端热重启后音频无法播放问题
问题描述
我在Windows和原生Android平台使用版本为3.0.1的audioplayers插件。Android端一切运行正常,但Windows端存在问题:
正常情况
Windows和Android端均可正常播放MP3音频文件。
异常情况
仅在Windows端,执行Hot Restart后再次播放同一音频文件时,触发以下错误:
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: FileSystemException: Cannot open file, path = 'C:\Users\<mypath>.mp3' (OS Error: Der Prozess kann nicht auf die Datei zugreifen, da sie von einem anderen Prozess verwendet wird. , errno = 32) #0 _File.open.<anonymous closure> (dart:io/file_impl.dart:356:9) <asynchronous suspension> #1 AudioCache.fetchToMemory (package:audioplayers/src/audio_cache.dart:80:5) <asynchronous suspension> #2 AudioCache.load (package:audioplayers/src/audio_cache.dart:101:31) <asynchronous suspension> #3 AudioPlayer.setSourceAsset (package:audioplayers/src/audioplayer.dart:249:17) <asynchronous suspension> #4 AudioPlayer.play (package:audioplayers/src/audioplayer.dart:131:5) <asynchronous suspension>
我的播放器调用方式:
_player.play(AssetSource('<file>.mp3'));
已确认在组件销毁时调用了_player的dispose方法。
请问我是否错误使用了播放器?Hot Restart是否存在未知的特殊机制?
问题分析与解决方案
问题原因
你没有错误使用播放器,问题出在Windows平台下Hot Restart的特殊机制:
Hot Restart仅重启Dart虚拟机,Windows原生进程(你的Flutter应用.exe)并未终止。- 虽然你在Dart层调用了
dispose,但Windows原生侧的音频播放实例可能未及时释放MP3文件的句柄,导致文件被占用,再次播放时无法打开。
解决方案
完善资源释放流程
在调用dispose前先调用release方法,确保原生侧主动释放资源和文件句柄:await _player.release(); await _player.dispose();必须使用
await确保异步释放操作完成。全局单例管理AudioPlayer
避免重复创建实例,全局维护一个AudioPlayer实例,减少资源泄漏风险:import 'package:audioplayers/audioplayers.dart'; class AudioManager { static final AudioPlayer _player = AudioPlayer(); static AudioPlayer get player => _player; static Future<void> cleanUp() async { await _player.release(); await _player.dispose(); } }可以通过监听应用生命周期,在应用即将退出或Hot Restart前调用
AudioManager.cleanUp():WidgetsBinding.instance.addObserver(LifecycleObserver()); class LifecycleObserver extends WidgetsBindingObserver { @override void didChangeAppLifecycleState(AppLifecycleState state) { if (state == AppLifecycleState.detached) { AudioManager.cleanUp(); } } }临时文件播放备选方案
将Asset中的MP3复制到临时目录后播放,避免原Asset文件被锁定:import 'dart:io'; import 'package:flutter/services.dart'; import 'package:path_provider/path_provider.dart'; import 'package:audioplayers/audioplayers.dart'; Future<void> playAudioFromTemp(String assetPath) async { // 读取Asset文件 final byteData = await rootBundle.load(assetPath); // 获取临时目录 final tempDir = await getTemporaryDirectory(); final tempFile = File('${tempDir.path}/audio_temp.mp3'); // 写入临时文件 await tempFile.writeAsBytes(byteData.buffer.asUint8List()); // 播放临时文件 await AudioManager.player.play(FileSource(tempFile.path)); }
内容的提问来源于stack exchange,提问作者Andreas
相关产品推荐
相关产品推荐

