ExoPlayer 在播放前获取真实的Uri(ResolvingDataSource )

656 阅读1分钟

问题:

现在很多情况是在播放之前需要额外调用一个http接口来获取真实的播放地址,比如播放列表里面有20首歌,难道要把这些歌曲的真实播放地址全部获取生成一个MediaItem列表,然后再去给到ExoPlayer播放,这明显不行,而且一般情况下这个真实的播放地址会失效的。

解决方案:

使用:ResolvingDataSource.Resolver

官网这里有示例

image.png

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()