问题:
现在很多情况是在播放之前需要额外调用一个http接口来获取真实的播放地址,比如播放列表里面有20首歌,难道要把这些歌曲的真实播放地址全部获取生成一个MediaItem列表,然后再去给到ExoPlayer播放,这明显不行,而且一般情况下这个真实的播放地址会失效的。
解决方案:
使用:ResolvingDataSource.Resolver
fun play() {
val url = "MyApp://music?id=233333333&title=蛄蛹者&singer=圣火猫猫教"
val mediaItem: MediaItem = MediaItem.fromUri(url)
val dataSourceFactory: ResolvingDataSource.Factory = ResolvingDataSource.Factory(
DefaultHttpDataSource.Factory()
){
it.withUri(resolveUri(it.uri))
}
val mediaSource = DefaultMediaSourceFactory(dataSourceFactory).createMediaSource(mediaItem)
player.setMediaSource(mediaSource)
player.playWhenReady = true;
player.prepare()
}
private fun resolveUri(uri: Uri): Uri {
Log.i("ExoPlayer", "resolveUri uri = $uri")
val realUrl = runBlocking {
//模拟调用接口去获取真实的播放地址
delay(2000)
"https://storage.googleapis.com/exoplayer-test-media-0/play.mp3"
}
return Uri.parse(realUrl)
}
当然这个SourceFactory也可以放在ExoPlayer创建的时候:
val player: ExoPlayer = ExoPlayer.Builder(MyApp.instance.applicationContext)
.apply {
val dataSourceFactory: ResolvingDataSource.Factory = ResolvingDataSource.Factory(
DefaultHttpDataSource.Factory()
){
it.withUri(resolveUri(it.uri))
}
setMediaSourceFactory(DefaultMediaSourceFactory(dataSourceFactory))
}
.build()
.also {
it.addAnalyticsListener(EventLogger())
it.addListener(listener)
}
播放的时候就可以直接用MediaItem去播放了:
val url = "MyApp://music?id=233333333&title=蛄蛹者&singer=圣火猫猫教"
val mediaItem: MediaItem = MediaItem.fromUri(url)
player.playWhenReady = true
player.setMediaItem(mediaItem)
player.prepare()