Reputation: 3440
Apparently, we can set an HLS media source only to ExoPlayer and not to MediaController in the Activity/Composable. Is there way to pass URL and token to the service so that HLSMediaSource factory can be used? Even then, not sure how to play a different source next time?
class PlaybackService : MediaSessionService() {
private var mediaSession: MediaSession? = null
override fun onCreate() {
super.onCreate()
val dataSourceFactory = DataSource.Factory {
val dataSource = DefaultHttpDataSource.Factory().createDataSource()
dataSource.setRequestProperty("Authorization", token) // <-- HOW TO PASS TOKEN TO SERVICE?
dataSource
}
val mediaSourceFactory = HlsMediaSource.Factory(dataSourceFactory)
.createMediaSource(MediaItem.fromUri(url)) // <-- HOW TO PASS HLS STREAMING URL TO SERVICE?
val player = ExoPlayer.Builder(this)
.setMediaSourceFactory(
DefaultMediaSourceFactory(this)
.setDataSourceFactory(dataSourceFactory),
)
.build()
mediaSession = MediaSession.Builder(this, player)
.build()
}
override fun onBind(intent: Intent?): IBinder? {
return super.onBind(intent)
}
override fun onTaskRemoved(rootIntent: Intent?) {
mediaSession?.player?.let { player ->
if (!player.playWhenReady || player.mediaItemCount == 0) {
stopSelf()
}
}
}
override fun onGetSession(controllerInfo: MediaSession.ControllerInfo): MediaSession? {
return mediaSession
}
}
Corresponding Composable code, how to pass the URL and token from here?
val sessionToken = SessionToken(context, ComponentName(context, PlaybackService::class.java))
val controllerFuture = MediaController.Builder(context, sessionToken).buildAsync()
I also have a related question from the Composable perspective at Android Jetpack Compose Media3 HLS Stream with playback service.
Upvotes: 0
Views: 728
Reputation: 71
You can use service intent like below.
Passing auth key is different from media3 topic. It depends on your security design. For demo, you can load from keychain or local storage.
class PlaybackService: MediaSessionService() {
private var mediaSession: MediaSession? = null
private var player: ExoPlayer? = null
override fun onCreate() {
super.onCreate()
player = ExoPlayer.Builder(applicationContext)
.build()
mediaSession = MediaSession.Builder(applicationContext, player!!)
.build()
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Timber.d("onStartCommand:$intent")
when (intent?.action) {
"playSample" -> {
intent.getStringExtra("url")?.let { url ->
val authorization = "" // load from keystore or app local storage.
player?.let {
it.setMediaSource(createHlsMediaSource(url, authorization))
it.repeatMode = Player.REPEAT_MODE_OFF
it.prepare()
it.play()
}
}
}
"stop" -> player?.stop()
else -> {}
}
return super.onStartCommand(intent, flags, startId)
}
override fun onGetSession(controllerInfo: MediaSession.ControllerInfo): MediaSession? {
return mediaSession
}
private fun createHlsMediaSource(url: String, authorization: String): MediaSource {
val dataSourceFactory = DefaultHttpDataSource.Factory()
.setDefaultRequestProperties(
mapOf(
"Authorization" to authorization
)
)
return HlsMediaSource.Factory(dataSourceFactory)
.createMediaSource(MediaItem.fromUri(url))
}
}```
Upvotes: 0