Android Jetpack Compose Media3 HLS Stream 与播放服务

问题描述 投票:0回答:1

我希望使用 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 而不是在可组合项中执行它?

android-mediaplayer exoplayer android-mediasession android-media3 exoplayer-media-item
1个回答
0
投票

不需要考虑UI层如何操作媒体,因为

MediaSessionService
可以应付。 UI层只是通过
MediaSessionService
连接
SessionToken
,构建
MediaController
,你可以将其设置为
PlayerView

示例视频屏幕.kt

@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
        }
    )

}

示例VideoViewModel.kt

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)
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.