MediaSession & MediaController
– Android TV app hands on Tutorial 9

Video Controls implementation with MediaSession

The sample implementation is done in Google’s latest sample Android TV application. AOSP sample application implementation does not have MediaSession implementation yet (in API 21, 22).

In previous chapter, I explained that following Video controls are needed to be impmented.

  1. Action’s UI update part (done in previous chapter)
  2. Video control part (done in previous chapter) MediaSession implementation, Video control via MediaController’s TransportControls (this chapter)
  3. – MediaSession can handle the action when user presses TV remote controller’s video control button.
    – It allows other activity to inherite video control. Especially LeanbackLauncher, Home display, can play video in background.  
  4. set MediaMetadata to MediaSession (this chapter)
    – “Now playing card” will appear at the top of recommendation row.

In this chapter, we proceed to implement Video controls using MediaSession. We can pass VideoView control to LeanbackLauncher by using MediaSession, which results to achieve playing video background in LeanbackLauncher. 

For 3, we create MediaSession in PlaybackOverlayActivity, and control it from MediaController in PlaybackOverlayFragment.

For 4, MediaSession’s Metadata is updated using MediaMetadata & PlaybackState class to update “Now playing card”.

I recommend you to read Displaying a Now Playing Card, for official explanation.

This chapter’s implementation is almost independent with previous chapter’s implementation. Before implementing MediaSession, I will implement requestVisibleBehind method, so that we can play video in background of LeanbackLauncher app.

Implement requestVisibleBehind

This method is added in API 21 (Lolipop), AOSP explanation explains that

If this call is successful then the activity will remain visible after onPause() is called, and is allowed to continue playing media in the background.

Sample implementation is as follows.

After this implementation, when you play video contents in your application and press “Home” key to go back LeanbackLauncher, the video is remain playing in background. .

Class structure of this chapter

We handle 3 classes in this chapter.

  • PlaybackOverlayActivity    
     – manage lifecycle, pass intent information to PlaybackController
     – MediaSession’s life time is linked with activity
  • PlaybackOverlayFragment
     – handle UI of PlaybackControlsRow
     – MediaController Callback function is used to update UI according to the current playback state
  • PlaybackController              
     – manage video playback
     – video control functions
     – MediaSessionCallback for receiving Video control key from TV remote controller

Create & release MediaSession

So far, we cannot control this video by using video control key in remote controller. Let’s implement MediaSession to define the action for each video control key in remote controller. At first, we create MediaSession in Constractor of PlaybackController, which is invoked by PlaybackOverlayActivity.

We can set callback, MediaSessionCallback, to MediaSession. It defines the precise behavior of each video control button which will be explained later.  

setFlags method with the argument FLAG_HANDLES_MEDIA_BUTTONS & FLAG_HANDLES_TRANSPORT_CONTROLS are necessary to enable remote controller key to control video.

After create, we must release MediaSession when it finishes.

Video control functions

Video control functions are implemented in MediaSessionCallback class. As name suggests, each video control action is implemented in corresponding callback function. This callback is called from 2 ways, which is “remote controller media key” or “UI video control button in PlaybackControlsRow”.


Video control by remote controller key

To enable video control from remote controller, we need to explicitly set available actions to MediaSession. Available actions are defined in PlaybackState class, sample implementation is below.

In this example, available actions are decided in getAvailableActions method, by adding actions using logical disjunction.

Video control from UI – MediaController.getTransportControls

To control MediaSession from PlaybackControlsRow in VideoDetailsFragment, we use MediaController. The MediaController is created in the constructor of PlaybackController and it owns token of MediaSession.

When user clicks video control button, it will invoke MediaSessionCallback method using MediaController.getTransportControls() method.

Video control part is done. However, we need to update UI of PlayControlsRow depending according to the video control.

Updating UI of VideoDetailsFragment 

We need to change the UI when video control action has executed, and video playback status has changed. We can get this event by using MediaController’s callback function. 2 callback methods are introduced in the following. 

  • onPlaybackStateChanged
  • onMetadataChanged

To use these callback methods, you can make subclass which extends MediaController.Callback class, and override these methods. To use this class, we can call MediaController’s registerCallback/unregisterCallback method to get event of MediaController.


Updating video control icons in onPlaybackStateChanged 

Update PlaybackState

PlaybackState is updated in PlaybackController.

For example, it will be called in playPause method. When user start play video state will change from STATE_PLAYING to STATE_PAUSED, or vice versa. PlaybackState update is set (notified) to MediaSession.


When PlaybackState has changed by setPlaybackState above, this event can be received with onPlaybackStateChanged callback. We can update play/pause icon in PlaybackControlsRow.


update Media information in onMetadataChanged

Update MediaMetadata

MediaMetadata class is used to set metadata information of the video. We can set each attribute of metadata by using put method in MediaMetadata.Builder. Again, MediaMetadata update is set (notified) to MediaSession.

By setting correct MediaMetadata to MediaSession, Android TV will show Now Playing Card on LeanbackLauncher, which will be explained again later.


When MediaMetadata has changed by setMetadata above, this event can be received with onMetadataChanged callback. We can update item value of PlaybackControlsRow.


Build and run

Now video playcontrol is possible from both clicking button on PlayControlsRow and pushing media key in remote controller. In the above video, I’m controlling video contents via remote controller and not using UI on the screen 🙂

Now Playing Card

Now Playing Card

Now Playing Card on Leanback Launcher screen.

If the MediaMetadata is correctly set to MediaSession, Now Playing Card will appear to the LeanbackLauncher (Home display). It notifies information of current playing media to user. Also, Now Playing Card enables user to go back to your app to control video (pause/go to next video etc). 



Source code is on github.

Sponsored Links

Leave a Reply

Your email address will not be published.