Connecting exoplayer with MediaSessionCompat

喜你入骨 提交于 2019-12-06 11:05:12

In short:

delete all code in your onCreate starting from (inclusive)

// Enable callbacks from MediaButtons and TransportControls

to (exclusive)

// Create a MediaControllerCompat

:)

More lengthy:

I recommend firing media session callbacks by listening to state transitions of the player instead of by click on buttons. This saves you from doing this for each UI element interacting with the player. That's actually what the MediaSessionConnector does for you.

With the MediaSessionConnector you do not need to manipulate the MediaSession yourself. The connector mediates between the player instance and the media session. This means the connector listens to state transitions of the player and maps the player state to the media session state. The connector also listens for media actions sent by transport controls and delegates them to the player or your app. Note: Your app does not need to provide a MediaSessionCompat.Callback, the connector registers its own (and overrides yours as there can be only one per session).

In general: your app does only interact with the SimpleExoPlayer instance while the connector maps the player state to the session.

Let's start with the basic approach which maps the state of the player to the session which triggers appropriate MediaControllerCompat.Callback methods:

// code running in a activity or service where (this instanceof Context)

mediaSession = new MediaSessionCompat(this, getPackageName());
mediaSessionConnector = new MediaSessionConnector(mediaSession)
mediaSessionConnector.setPlayer(player, null, null);
mediaSession.setActive(true);

You can now prepare and use the player like before, like call setPlayWhenReady(true|false), seekTo(t) and the connector maintains the PlaybackStateCompat which is broadcast to controllers of the session.

The connector does receive and implement a couple of media actions at this level (no need for your own MediaSession.Callback):

PlaybackStateCompat.ACTION_PLAY_PAUSE |
PlaybackStateCompat.ACTION_PLAY | 
PlaybackStateCompat.ACTION_PAUSE | 
PlaybackStateCompat.ACTION_STOP |
PlaybackStateCompat.ACTION_SET_SHUFFLE_MODE |
PlaybackStateCompat.ACTION_SET_REPEAT_MODE;

PlayFromXYZ actions

You may want to support additional media actions like ACTION_PLAY_FROM_MEDIA_ID. You can do so by providing your PlaybackPreparer:

playbackPreparer = new YourPlaybackPreparer(); 
mediaSessionConnector.setPlayer(player, playbackPreparer, null);

The connector now delegates actions like ACTION_PLAY_FROM_MEDIA_ID or ACTION_PREPARE_FROM_MEDIA_ID to your playback preparer which creates a MediaSource for the given media ID to prepare the player.

Metadata and Queue management

Also interesting is the ability to map the Timeline of the player directly to queue and metadata of the media session. To do this you can provide a QueueNavigator. There is an abstract TimelineQueueNavigator provided by the extension:

QueueNavigator queueNavigator = new TimelineQueueNavigator(mediaSession) {
  @Override
  public MediaDescriptionCompat getMediaDescription(int windowIndex) {
    // implement this method and read from your backing data:
    getMediaDescriptionAtQueuePosition(windowIndex):
    return mediaDescription;
  }
}
mediaSessionConnector.setQueueNavigator(queueNavigator);

With this media controllers can now read metadata and queue of the session. The queue represents the current Timeline of the player and the metadata of the session describes the window in the Timeline which is currently playing. (more about playlists).

Provided a TimelineQueueNavigator, the connector listens for ACTION_SKIP_TO_NEXT, ACTION_SKIP_TO_PREVIOUS and ACTION_SKIP_TO_QUEUE_ITEM sent by transport controls and navigates along the timeline accordingly.

Lifecycle integration

Please note that you must create the player instance onStart/onResume and release it onPause/onStop. This makes sure codec resources you share with other apps are freed when you are in background. Your code sample does it only once onCreate which is not good citizenship :). See how the ExoPlayer demo app does it.

Please also consider the Medium blog about the MediaSessionConnector.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!