Exoplayer: In MediaSessionConnector, why is Player.STATE_ENDED state (in Exoplayer) mapped to PlaybackStateCompat.STATE_PAUSED instead of PlaybackStateCompat.STATE_STOPPED

Created on 7 Nov 2018  路  4Comments  路  Source: google/ExoPlayer

The relevant code is in MediaSessionConnector.java:

  private int mapPlaybackState(int exoPlayerPlaybackState, boolean playWhenReady) {
    switch (exoPlayerPlaybackState) {
      case Player.STATE_BUFFERING:
        return PlaybackStateCompat.STATE_BUFFERING;
      case Player.STATE_READY:
        return playWhenReady ? PlaybackStateCompat.STATE_PLAYING : PlaybackStateCompat.STATE_PAUSED;
      case Player.STATE_ENDED:
        return PlaybackStateCompat.STATE_PAUSED;
      default:
        return PlaybackStateCompat.STATE_NONE;
    }
  }

It's unclear to me why Player.STATE_ENDED is mapped to PlaybackStateCompat.STATE_PAUSED instead of PlaybackStateCompat.STATE_STOPPED. I'd like to alter that mapping behavior in my own app, but unfortunately, this is a private method and the class itself is final, so I'm doubly prevented from making my own customizations.

bug enhancement

Most helpful comment

We'll make a change to map Player.STATE_ENDED onto PlaybackStateCompat.STATE_STOPPED.

All 4 comments

The reasoning behind this mapping is that with the MediaSession API, MediaControllerCompat.TransportControls.stop() in contrast to MediaControllerCompat.TransportControls.pause() implies that resources like codecs or the player itself can/should be freed. This is not the case for Player.STATE_ENDED. If ExoPlayer is in the Player.STATE_ENDED seeking to a position somewhere before the end of the media makes the player transition to STATE_READY again. So no resources are freed.

Documentation of STATE_PAUSED and STATE_STOPPED is unclear around this though:
https://developer.android.com/reference/android/support/v4/media/session/PlaybackStateCompat.html#STATE_STOPPED

It might be implied here: https://developer.android.com/reference/android/support/v4/media/session/MediaControllerCompat.TransportControls.html#stop()

While the actual mapping of STATE_ENDED is compatible with that, I acknowledge that this hides the Player.STATE_ENDED which is not visible through the media session state with that mapping. So you can't detect when all media is played to the end.

I think we should reconsider this and map Player.STATE_ENDED to PlaybackStateCompat.STOP which then would reflect that the media has been played to the end.

Am I correct you need to detect the STATE_END for your use case?

Ah, thanks for the explanation. You are correct, I need to detect the end of playback from a media controller (through a MediaControllerCompat.Callback listener).

We'll make a change to map Player.STATE_ENDED onto PlaybackStateCompat.STATE_STOPPED.

Hi @ojw28,
I was wondering why this change didn't make it to release yet? I could really use this functionality of knowing when the track has ended. Just like @dougkeen, I need it through the MediaControllerCompat.Callback listener.

Was this page helpful?
0 / 5 - 0 ratings