flutter audio_service: AudioProcessingState не обновляется после полного воспроизведения медиа-элемента

Я разрабатываю приложение для музыкального плеера на флаттере.

Сценарий: когда пользователь выбирает одну песню из списка, после того, как выбранная песня полностью воспроизведена, автоматически необходимо запустить следующую песню в списке.

Сейчас слушаю , потоки, чтобы обновить информацию о песне и информацию о слайдере в пользовательском интерфейсе. Но я не могу понять, когда закончится воспроизведение выбранной песни. Идея здесь в том, что после воспроизведения выбранной песни должна быть воспроизведена следующая песня в списке. Первоначально AudioProcessingState переходит из состояния подключения в состояние готовности. Первый мультимедийный элемент воспроизводится успешно. Но,

Проблема 1. Даже после полного воспроизведения первого элемента мультимедиа состояние AudioProcessingState все еще (не заменено на завершенное). Даже игра всегда. Ниже приведена логика воспроизведения и приостановки пользовательского интерфейса.

            StreamBuilder<PlaybackState>(
                      stream: AudioService.playbackStateStream,
                      builder: (context, snapshot) {
                        final processingState = snapshot.data?.processingState;
                        print('Current Processingstate: $processingState');
                        final playing = snapshot.data?.playing ?? false;

                        if (playing)
                          return IconButton(
                              iconSize: 40,
                              onPressed: () {
                                AudioService.pause();
                              },
                              icon: Icon(FontAwesomeIcons.pause,
                                  color: Colors.white));
                        else
                          return IconButton(
                              iconSize: 40,
                              onPressed: () {
                                if (AudioService.running) {
                                  AudioService.play();
                                } else {
                                  List<dynamic> list = [];

                                  for (int i = 0;
                                      i < this.widget.mediaList.length;
                                      i++) {
                                    var m = this.widget.mediaList[i].toJson();
                                    list.add(m);
                                  }
                                  var params = {
                                    "data": list,
                                    'index': this.widget.currentIndex
                                  };

                                  AudioService.connect();
                                  AudioService.start(
                                      backgroundTaskEntrypoint:
                                          _backgroundTaskEntrypoint,
                                      params: params);
                                }
                              },
                              icon: Icon(FontAwesomeIcons.play,
                                  color: Colors.white));
                      },
                    ),

Проблема 2: Кроме того, поток Position получает непрерывный поток даже после завершения выбранной песни. Из-за этого я не могу перестать обновлять метку продолжительности.

                      StreamBuilder<Duration>(
                      stream: AudioService.positionStream,
                      builder: (context, snapshot) {
                        final mediaState = snapshot.data;
                        return SeekBar(
                          duration: this.widget.mediaList[current].duration ??
                              Duration.zero,
                          position: aPosition,
                          onChangeEnd: (newPosition) {
                            AudioService.seekTo(newPosition);
                          },
                        );
                      },
                    ),

Вкратце,

  1. Как я могу узнать, что воспроизведение выбранной песни завершено?
  2. Как обновить ползунок после завершения воспроизведения песни?

1 ответ

Существует нереализованный запрос функции на добавление нового типа подписки на события, которая может проинформировать вас, когда игрок автоматически переходит к следующему элементу в последовательности здесь. Вы можете проголосовать за эту функцию, нажав кнопку «Нравится».

Однако в этом комментарии также есть обходной путь . Что вы можете сделать, так это послушать player.currentIndexStreamкоторый сообщает вам, когда изменяется текущий элемент. Когда игрок автоматически переходит к следующему элементу, этот индекс изменится, но вы не можете предположить, что каждый раз, когда текущий индекс изменяется, это было из-за автоматического продвижения, потому что это также могло быть из-за ручного поиска. . По этой причине обходной путь состоит в том, чтобы просто сохранить логическую переменную, которая указывает, использовался ли ручной поиск, чтобы вы знали, в каком случае. Каждый раз при поиске вы устанавливаете для этой логической переменной значение true и снова устанавливаете значение false после завершения поиска.

Чтобы упростить задачу, вы можете создать для этого свою собственную версию метода поиска, например mySeek и даже добавить это как метод расширения на AudioPlayer:

      bool _seeking = false;
extension AudioPlayerExtension on AudioPlayer {
  Future<void> mySeek(Duration position, {int? index}) async {
    _seeking = true;
    await seek(position);
    _seeking = false;
  }
}

Тогда другая часть решения - послушать currentIndexStream:

      _player.currentIndexStream.listen((index) {
  if (index == null) return;
  if (_seeking) {
    // the index changed due to a manual seek
  } else {
    // the index changed due to an auto-advance
    onAutoAdvance();
  }
  skipped = false;
});

Итак, теперь, каждый раз, когда вы хотите вручную перейти к другому элементу, вы используете:

      player.mySeek(pos, index: i);

А затем, чтобы обработать, когда элемент изменился из-за автоматического продвижения, напишите свой код для его обработки здесь:

      void onAutoAdvance() {
}
Другие вопросы по тегам