我希望使用 Media3 和后台播放服务来实现 HLS 流式传输。我在网上看到有关如何在活动/可组合项中使用 MediaController
setMediaItem
的参考资料,但是,不确定如何使用也使用自定义 HTTP 标头的媒体源。这是我的可组合函数。
@Composable
fun PlayerTest(
token: String,
url: String,
) {
val context = LocalContext.current
val dataSourceFactory = DataSource.Factory {
val dataSource = DefaultHttpDataSource.Factory().createDataSource()
dataSource.setRequestProperty("Authorization", token)
dataSource
}
val hlsMediaSource = HlsMediaSource.Factory(dataSourceFactory)
.createMediaSource(MediaItem.fromUri(url))
val sessionToken = SessionToken(context, ComponentName(context, PlaybackService::class.java))
val controllerFuture = MediaController.Builder(context, sessionToken).buildAsync()
DisposableEffect(
Box {
AndroidView(
factory = {
PlayerView(context).apply {
resizeMode = AspectRatioFrameLayout.RESIZE_MODE_FILL
useController = false
layoutParams = FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
}
},
update = { playerView ->
controllerFuture.addListener({
val controller = controllerFuture.get()
controller.setMediaSource(hlsMediaSource) // <--- NOT FOUND
playerView.setPlayer(controller)
}, MoreExecutors.directExecutor())
}
)
AudioPlayer(...)
},
) {
onDispose {
MediaController.releaseFuture(controllerFuture)
}
}
}
此外,我在 MediaItem.Builder() 中没有看到采用媒体源的选项。我正在使用 Media3 版本
1.3.0
。有什么建议吗?
方法
setMediaSource
在服务中创建的 ExoPlayer 实现中可用。或者我应该让服务构建 URL 并传递 setMediaSource 而不是在可组合项中执行它?
不需要考虑UI层如何操作媒体,因为
MediaSessionService
可以应付。
UI层只是通过MediaSessionService
连接SessionToken
,构建MediaController
,你可以将其设置为PlayerView
。
@Composable
fun SampleVideoScreen(viewModel: SampleVideoViewModel) {
val context = LocalContext.current
DisposableEffect(viewModel) {
viewModel.prepare(context)
onDispose { viewModel.dispose() }
}
val controller by viewModel.mediaController.observeAsState()
AndroidView(
factory = {
PlayerView(context)
},
update = { playerView ->
playerView.player = controller
}
)
}
class SampleVideoViewModel: ViewModel() {
private var sessionToken: SessionToken? = null
val mediaController = MutableLiveData<MediaController>()
fun prepare(context: Context) {
viewModelScope.launch(Dispatchers.IO) {
val playIntent = Intent(context, PlaybackService::class.java)
.setAction("playSample")
.putExtra("url", "http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8")
context.startService(playIntent)
val component = ComponentName(context, PlaybackService::class.java)
sessionToken = SessionToken(context, component).also { session ->
MediaController.Builder(context, session)
.buildAsync().get().also { controller ->
mediaController.postValue(controller)
}
}
}
}
fun dispose() {
mediaController.value?.clearMediaItems()
mediaController.postValue(null)
}
}