0

我想在后台使用audio_servicejust_audio播放音频。但问题是我必须在所有元数据开始时设置队列,以确保即使应用程序处于后台,它们也会自动运行。但我没有播放歌曲的歌曲网址。相反,我有一个函数可以用来获取歌曲播放 URL。现在我想每次都调用该函数来获取歌曲播放 URL 并使用该 URL 播放歌曲。我想在 AudioBackgroundService 的代码中调用该函数,而不是在我的颤振 UI 的代码中。因为如果我的用户界面不存在,即在后台,那么该函数将不会被调用。因此,要确保每次必须在 AudioServiceBackground 代码中调用该函数。有没有办法这样做?我正在使用audio_service 文档中提供的相同代码. 我想我必须在onStartAudioService 的功能中使用该功能,但我仍然无法找到出路。此外,如果它可以在播放当前歌曲的同时为下一首歌曲调用该函数会更好。

4

1 回答 1

1

设置队列时不需要 URL。您可以将每个MediaItem的 ID 设置为您唯一的歌曲 ID,并在以后通过将 URL 存储在extras字段中来修改此数据。

首先,我建议这个启动顺序:

await AudioService.start(backgroundTaskEntrypoint: _entrypoint);
await AudioService.updateQueue(songs);
AudioService.play();

(对于 v0.18 及更高版本,您不再调用start,而是替换AudioService.audioHandler.

在您的后台音频任务 (v0.17) 或音频处理程序 (v0.18) 中,您可能希望字段存储您的播放器和队列:

AudioPlayer _player = AudioPlayer();
List<MediaItem> _queue = [];

onStart(v0.17) 或您的音频处理程序构造函数 (v0.18) 不需要做任何事情,除了您想要在播放器上进行的任何初始化,例如为事件注册监听器(例如,监听当前播放的音频何时完成,所以你可以打电话skipToNext())。updateQueue您应该按如下方式实现回调:

// 0.17 solution:
Future<void> onUpdateQueue(List<MediaItem> queue) =>
  await AudioServiceBackground.setQueue(_queue = queue);
// 0.18 solution:
Future<void> updateQueue(List<MediaItem> newQueue) async {
  queue.add(_queue = newQueue);
  await super.updateQueue(newQueue);
}

对于play回调:

// 0.17 solution:
Future<void> onPlay() => _player.play();
// 0.18 solution:
Future<void> play() => _player.play();

您还需要实现skipToQueueItem回调:

// 0.17 solution:
Future<void> onSkipToQueueItem(String mediaId) async {
  final index = _queue.indexWhere((item) => item.id == mediaId);
  if (_queue[index].extras['url'] == null) {
    // fetch from your API and update queue
    _queue[index] = _queue[index].copyWith(
      extras: {'url': await fetchUrl(_queue[index].id),
    );
    await AudioServiceBackground.setQueue(_queue);
  }
  await AudioServiceBackground.setMediaItem(_queue[index]);
  // load URL into player
  await _player.setUrl(_queue[index].extras['url']);
}
// 0.18 solution
Future<void> skipToQueueItem(index) async {
  if (_queue[index].extras['url'] == null) {
    // fetch from your API and update queue
    _queue[index] = _queue[index].copyWith(
      extras: {'url': await fetchUrl(_queue[index].id),
    );
    queue.add(_queue);
  }
  await mediaItem.add(_queue[index]);
  // load URL into player
  await _player.setUrl(_queue[index].extras['url']);
}

skipToNext/skipToPrevious回调的默认实现是根据 this 定义的。

由于您的 API 调用会根据需要分别加载每个 URL,因此这将在每首歌曲之间产生间隙。如果您可以提前将多个 URL 堆叠在一起,just_audio 可以支持无缝播放。

于 2021-02-12T15:39:20.520 回答