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