Community Member
ย ยทย Building with Flutterflow

audio player that can play a playlist on background?

Hi, I have been trying to create a custom widget to take a List of records, which contains an attribute of the audioUrl I want to play. Once started, it should play in the background and play each audioUrl sequentially (start the next one once the current one is finished).

This has not been easy, and am wondering if someone has succeeded to do this?

I started with the just_audio package, but it's not coming together easily.

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

class PlaylistPlayer extends StatefulWidget {
  const PlaylistPlayer({
    Key? key,
    this.width,
    this.height,
    this.compactionsList,
  }) : super(key: key);

  final double? width;
  final double? height;
  final List<CompactionsRecord>? compactionsList;

  @override
  _PlaylistPlayerState createState() => _PlaylistPlayerState();
}

class _PlaylistPlayerState extends State<PlaylistPlayer> {
  late AudioPlayer _player;
  late ConcatenatingAudioSource _playlist;
  int? _currentIndex;

  @override
  void initState() {
    super.initState();
    _player = AudioPlayer();
    _currentIndex = 0;

    _playlist = ConcatenatingAudioSource(
      children: widget.compactionsList
              ?.map((compaction) =>
                  AudioSource.uri(Uri.parse(compaction.audioUrl)))
              .toList() ??
          [],
    );

    _player
        .setAudioSource(_playlist,
            initialIndex: 0, initialPosition: Duration.zero)
        .then((_) {
      _player.play();
    });

    // Listen to changes in the currently playing item
    _player.currentIndexStream.listen((index) {
      if (index != null) {
        setState(() {
          _currentIndex = index;
        });
      }
    });
  }

  @override
  void dispose() {
    _player.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      width: widget.width,
      height: widget.height,
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          // Player controls
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              IconButton(
                icon: Icon(Icons.skip_previous),
                onPressed: () =>
                    _player.hasPrevious ? _player.seekToPrevious() : null,
              ),
              IconButton(
                icon: Icon(_player.playing ? Icons.pause : Icons.play_arrow),
                onPressed: () =>
                    _player.playing ? _player.pause() : _player.play(),
              ),
              IconButton(
                icon: Icon(Icons.skip_next),
                onPressed: () => _player.hasNext ? _player.seekToNext() : null,
              ),
            ],
          ),
          // Playlist display
          Expanded(
            child: ListView.builder(
              itemCount: widget.compactionsList?.length ?? 0,
              itemBuilder: (context, index) {
                final compaction = widget.compactionsList![index];
                return ListTile(
                  title: Text(compaction.itemTitle),
                  onTap: () {
                    _player.seek(Duration.zero, index: index);
                  },
                  selected: index == _currentIndex,
                  selectedTileColor: Colors.grey[300],
                );
              },
            ),
          ),
        ],
      ),
    );
  }
}
1
7 replies