iOS端App后台长时间驻留后AudioPlayer无法正常工作
音频播放后台长时间驻留后无法恢复问题
环境
just_audio: ^0.9.42 riverpod: ^2.6.1 flutter_riverpod: ^2.4.10 riverpod_annotation: ^2.3.4 Dev: riverpod_generator: ^2.3.11 Platform: iOS Flutter version: 3.27.2 Device: iPhone 12 Pro Max - 18.1.1
Provider配置
@Riverpod(keepAlive: true) AudioPlayer audioPlayer(AudioPlayerRef ref) { final audioPlayer = AudioPlayer( userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0', ); ref.onDispose(() async => await audioPlayer.dispose()); return audioPlayer; }
复现步骤
- 打开App并成功播放音频
- 按下Home键将App置于后台(不杀死App)
- 使用其他应用、锁屏或让设备闲置
- 等待数小时(如过夜)
- 从后台返回App
- 尝试播放音频
当前行为
- 返回App后音频无法播放
- 无任何错误提示
- 仅能通过完全杀死并重启App解决问题
预期行为
- 从后台返回App后音频应可正常播放
- 由于Provider标记了
keepAlive: true,实例应保持存活状态
假设
存在两种可能场景:
- Riverpod Provider问题:
- 尽管标记了
keepAlive: true,Provider仍可能销毁实例 - 但根据Riverpod文档,keepAlive Provider仅应在App被杀死时销毁,该可能性较低
- 尽管标记了
- just_audio问题:
- AudioPlayer实例可能在后台长时间驻留后自动销毁或释放资源
- Provider保持存活但持有无效的AudioPlayer实例
问题
- just_audio是否会在App后台长时间驻留后自动释放资源?
- keepAlive Provider在类似场景下是否存在已知问题?
- 处理需在长时间后台驻留后仍可正常工作的音频播放,有哪些推荐方案?
额外上下文
- 仅在后台长时间驻留(数小时)后出现问题
- 短时间后台驻留(30分钟)时无异常
问题解答
1. just_audio是否会在App后台长时间驻留后自动释放资源?
是的,iOS系统会对后台App进行资源管控,长时间闲置后可能回收音频相关原生资源,导致just_audio的AudioPlayer实例失去有效性。即便Dart层的实例还存在,其关联的原生层资源已被系统释放,进而无法正常播放。而且just_audio本身没有主动在后台长时间驻留时维持资源的机制,完全依赖系统的后台权限和资源分配策略。
2. keepAlive Provider在类似场景下是否存在已知问题?
Riverpod的keepAlive: true确实会保证Provider实例在Dart层不被销毁,只要App进程未被杀死。目前没有官方记录的此类场景下的已知问题,所以大概率是AudioPlayer的原生层资源被回收,而非Provider实例被销毁。可以在App返回前台时打印Provider实例的哈希值验证:如果哈希值不变,说明实例仍存活,问题出在AudioPlayer本身。
3. 推荐方案
- 实例有效性检查与重建:尝试播放前检查
AudioPlayer状态,若无效则重建实例。可以通过WidgetsBindingObserver监听App从后台返回的事件,在App恢复前台时重新初始化AudioPlayer:// 在使用AudioPlayer的页面或Provider中添加监听 WidgetsBinding.instance.addObserver(this); @override void didChangeAppLifecycleState(AppLifecycleState state) { if (state == AppLifecycleState.resumed) { final player = ref.read(audioPlayerProvider); // 可根据实际情况添加更精准的有效性判断 if (!player.playing) { ref.invalidate(audioPlayerProvider); ref.read(audioPlayerProvider); } } } - 申请后台音频权限:在iOS的
Info.plist中添加后台音频权限,让系统优先保留App的音频资源:<key>UIBackgroundModes</key> <array> <string>audio</string> </array> - 使用专业音频后台插件:如果需要长期后台播放,推荐使用
audio_service插件,它专门处理后台音频播放的生命周期管理,能更好地适配系统权限和资源管控逻辑。
内容的提问来源于stack exchange,提问作者Phú nguyễn
相关产品推荐
相关产品推荐

