rysv
rysv

Reputation: 3440

In Android Media3 MediaSessionService how to specify HLS streaming source

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

Answers (1)

usr153.K
usr153.K

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.

PlaybackService.kt

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

Related Questions