import 'dart:async'; import 'package:audio_service/audio_service.dart'; import 'package:just_audio/just_audio.dart'; /// An [AudioHandler] for playing a single item. class AudioPlayerHandler extends BaseAudioHandler { final _player = AudioPlayer(); FutureOr Function()? onNextRequest; FutureOr Function()? onPreviousRequest; /// Initialise our audio handler. AudioPlayerHandler() { // So that our clients (the Flutter UI and the system notification) know // what state to display, here we set up our audio handler to broadcast all // playback state changes as they happen via playbackState... _player.playbackEventStream.map(_transformEvent).pipe(playbackState); } AudioPlayer get core => _player; void addItem(MediaItem item) { mediaItem.add(item); } // In this simple example, we handle only 4 actions: play, pause, seek and // stop. Any button press from the Flutter UI, notification, lock screen or // headset will be routed through to these 4 methods so that you can handle // your audio playback logic in one place. @override Future play() => _player.play(); @override Future pause() => _player.pause(); @override Future seek(Duration position) => _player.seek(position); @override Future stop() => _player.stop(); @override Future skipToNext() async { await onNextRequest?.call(); await super.skipToNext(); } @override Future skipToPrevious() async { await onPreviousRequest?.call(); await super.skipToPrevious(); } @override Future onTaskRemoved() { _player.stop(); return super.onTaskRemoved(); } /// Transform a just_audio event into an audio_service state. /// /// This method is used from the constructor. Every event received from the /// just_audio player will be transformed into an audio_service state so that /// it can be broadcast to audio_service clients. PlaybackState _transformEvent(PlaybackEvent event) { return PlaybackState( controls: [ MediaControl.skipToPrevious, if (_player.playing) MediaControl.pause else MediaControl.play, MediaControl.skipToNext, MediaControl.stop, ], androidCompactActionIndices: const [0, 1, 2], processingState: const { ProcessingState.idle: AudioProcessingState.idle, ProcessingState.loading: AudioProcessingState.loading, ProcessingState.buffering: AudioProcessingState.buffering, ProcessingState.ready: AudioProcessingState.ready, ProcessingState.completed: AudioProcessingState.completed, }[_player.processingState]!, playing: _player.playing, updatePosition: _player.position, bufferedPosition: _player.bufferedPosition, speed: _player.speed, queueIndex: event.currentIndex, ); } }