Search code examples
leanbackamazon-fire-tvandroid-mediasession

The remote media buttons don't work on Amazon Fire TV OS with MediaSession


I'm creating a video App for the Amazon platform. I'm trying to enable the "rewind and fast forward" controls on the remote. But it seems like the app doesn't see this action.

    class VideoActivity : FragmentActivity() {

    private var mediaSession: MediaSessionCompat? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_video)
        initMediaSession()
        supportFragmentManager.beginTransaction()
            .replace(R.id.container, VideoFragment().apply { arguments = intent.extras })
            .commit()
    }

    override fun onDestroy() {
        super.onDestroy()
        mediaSession?.isActive = false
        mediaSession?.release()
    }

    private fun initMediaSession() {
        mediaSession = MediaSessionCompat(applicationContext, "VideoTag")
        mediaSession?.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS or MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS)
        val state = PlaybackStateCompat.Builder()
            .setActions(
                PlaybackStateCompat.ACTION_PLAY or PlaybackStateCompat.ACTION_PAUSE or PlaybackStateCompat.ACTION_PLAY_PAUSE or PlaybackStateCompat.ACTION_REWIND
                or PlaybackStateCompat.ACTION_SKIP_TO_NEXT or PlaybackStateCompat.ACTION_SEEK_TO
//                PlaybackStateCompat.ACTION_PLAY_PAUSE or
//                        PlaybackStateCompat.ACTION_FAST_FORWARD
//                        or PlaybackStateCompat.ACTION_REWIND or
//                        PlaybackStateCompat.ACTION_PLAY or
//                        PlaybackStateCompat.ACTION_PAUSE
            )
            .setState(PlaybackStateCompat.STATE_PLAYING, 0, 1.0f)
            .build()
        mediaSession?.setPlaybackState(state)
        mediaSession?.setCallback(object : MediaSessionCompat.Callback() {
            override fun onCustomAction(action: String?, extras: Bundle?) {
                super.onCustomAction(action, extras)
            }

            override fun onSeekTo(pos: Long) {
                super.onSeekTo(pos)
            }

            override fun onSkipToNext() {
                super.onSkipToNext()
            }

            override fun onFastForward() {
                super.onFastForward()
            }

            override fun onPlay() {
                super.onPlay()
            }

            override fun onPause() {
                super.onPause()
            }

        })
        mediaSession?.isActive = true
        val controll = MediaControllerCompat(this, mediaSession!!)
        MediaControllerCompat.setMediaController(this, controll)
    }

Play/pause works, it switches the player's state, but I cannot intercept this event by media session callback. What did I do wrong?


Solution

  • I found a solution. Actually solutions. The problem with the media session was a playback state.

    mediaSession.setPlaybackState(stateBuilder.setState(PlaybackStateCompat.STATE_PLAYING, PlaybackStateCompat.PLAYBACK_POSITION_UNKNOWN, 1).build());
    

    It requires updating its state every time

    But also I figured out I don't need any media sessions because PlaybackTransportControlGlue handles it but does not dispatch it as an action. So I overrode the onKey callback of the PlaybackTransportControlGlue and handle it by myself

    override fun onKey(v: View?, keyCode: Int, event: KeyEvent?): Boolean {
        return when {
            event?.action == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD -> {
                fastForward()
                true
            }
            event?.action == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_MEDIA_REWIND -> {
                rewind()
                true
            }
            else -> super.onKey(v, keyCode, event)
        }
    }