Flutter audio_service iOS后台切歌卡顿缓冲问题求助
iOS后台使用audio_service切歌失败,播放器持续卡在缓冲状态
我基于Flutter的audio_service包开发音频流应用,前台切歌功能正常,但在iOS后台状态下无法切换歌曲,音频播放器始终卡在缓冲状态。该问题仅出现于iOS平台,Android端运行完全正常。
已完成的配置与操作
- 在Info.plist和Xcode中配置了音频后台模式
- 实现了音频播放所需的后台任务
SongHandler代码
import 'dart:developer'; import 'package:audio_service/audio_service.dart'; import 'package:just_audio/just_audio.dart'; import 'package:rxdart/rxdart.dart' as rx; class SongHandler extends BaseAudioHandler with SeekHandler { final AudioPlayer audioPlayer = AudioPlayer(); MediaItem? currentMediaItem; bool hasPrevious = false; bool hasNext = false; void _broadcastState() { mediaItem.add(currentMediaItem); playbackState.add(playbackState.value.copyWith( controls: [ if (hasPrevious) MediaControl.skipToPrevious, if (audioPlayer.playing) MediaControl.pause else MediaControl.play, if (hasNext) MediaControl.skipToNext, ], systemActions: { MediaAction.seek, MediaAction.seekForward, MediaAction.seekBackward, }, processingState: { ProcessingState.idle: AudioProcessingState.idle, ProcessingState.loading: AudioProcessingState.loading, ProcessingState.buffering: AudioProcessingState.buffering, ProcessingState.ready: AudioProcessingState.ready, ProcessingState.completed: AudioProcessingState.completed, }[audioPlayer.processingState]!, playing: audioPlayer.playing, updatePosition: audioPlayer.position, bufferedPosition: audioPlayer.bufferedPosition, speed: audioPlayer.speed, queueIndex: 0, )); } Future<void> initSong( AudioSource audioSource, MediaItem song, ) async { currentMediaItem = song; // Set current media item audioPlayer.playbackEventStream.listen((_) => _broadcastState()); await audioPlayer.setAudioSource(audioSource); play(); } Future<void> updateAudioSource(AudioSource audioSource, MediaItem song, {bool? isShowButton = false}) async { await audioPlayer.setAudioSource(audioSource); currentMediaItem = song; hasPrevious = isShowButton ?? false; hasNext = isShowButton ?? false; } @override Future<void> play() async { if (currentMediaItem != null) { await audioPlayer.play(); } } @override Future<void> pause() => audioPlayer.pause(); @override Future<void> seek(Duration position) => audioPlayer.seek(position); @override Future<void> skipToNext() async { final musicPlayerViewModel = Get.find<MusicPlayerViewModel>(); musicPlayerViewModel.moveNextSong(); // Logic to skip to the next song log('message'); } @override Future<void> skipToPrevious() async { final musicPlayerViewModel = Get.find<MusicPlayerViewModel>(); musicPlayerViewModel.movePreviousSong(); // Logic to skip to the previous song log('message'); } Stream<PositionData> get positionDataStream => rx.CombineLatestStream.combine3( audioPlayer.positionStream, audioPlayer.bufferedPositionStream, audioPlayer.durationStream, (position, bufferedPosition, duration) => PositionData( position: position, bufferedPosition: bufferedPosition, duration: duration ?? Duration.zero, ), ); }
监听器与切歌函数代码
void musicSetupListeners() { playerStateSubscription?.cancel(); playerStateSubscription = songHandler.audioPlayer.playerStateStream.listen((state) async { log('Player state: ${state.processingState}'); switch (state.processingState) { case ProcessingState.idle: // Handle idle state if needed break; case ProcessingState.loading: // Handle loading state if needed break; case ProcessingState.buffering: // Handle buffering state if needed break; case ProcessingState.ready: // Handle ready state if needed break; case ProcessingState.completed: await handleCompletion(); break; } }, onError: (error) { log('Stream error: $error'); }); } Future<void> handleCompletion() async { await songHandler.pause(); await songHandler.seek(Duration.zero); await Future.delayed(const Duration(milliseconds: 500), () async { try { if (!isProcessingCompletion.value) { isNewSongLoading.value = true; isNewSongLoading.refresh(); isProcessingCompletion.value = true; isProcessingCompletion.refresh(); await songHandler.stop(); await Future.delayed(const Duration(milliseconds: 500), () async { await _playNextSong(this); isProcessingCompletion.value = false; }); } } catch (e) { log('Error during completion handling: $e'); } }); } Future _playNextSong(MusicPlayerViewModel musicPlayerViewModel) async { if (isChangeList.value == false) { if (britanyPlyController.isShuffle.value) { await britanyPlyController.selectRandomSongs(musicPlayerViewModel); } else { await britanyPlyController.selectSequenceSongs(musicPlayerViewModel); } } else { await selectSequenceSongs(); } Future.delayed( const Duration(milliseconds: 300), () { isNewSongLoading.value = false; isNewSongLoading.refresh(); }, ); await songHandler.play(); }
希望有人能帮忙解决这个问题。
内容的提问来源于stack exchange,提问作者Hassaan Ahmed
相关产品推荐
相关产品推荐

