Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android MediaSessionCompat.setPlaybackState doesn't notify on position changes

Tags:

android

I'm curious if anyone has ran into this problem or has any suggestions. I'm writing a media player in which I'm utilizing the MediaSessionCompat API. Every so often I determine the current position of the playing media and raise a change event. I re-set the playback state as seen below. However, since the STATE_PLAYING state does not change, Android does not raise the notification that the position value changed. In particular, when I have a Bluetooth device connected that displays the current position, the Bluetooth device only receives the position when the state changes from STATE_PLAYING to STATE_PAUSED, or vice versa. See code below:

public void setup() {
    mediaSession = new MediaSessionCompat(context, Schema.TAG, component, pendingIntent);
    mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
    mediaSession.setActive(true);
    updatePlaybackState();
}

public void updatePlaybackState() {
    int state = isPlaying() ? PlaybackStateCompat.STATE_PLAYING : PlaybackStateCompat.STATE_PAUSED;
    int ms = getCurrentPosition();
    mediaSession.setPlaybackState(new PlaybackStateCompat.Builder()
            .setState(state, ms, 1f)
            .build());
}

In this example, I call updatePlaybackState when the current position changes. If I change the updatePlaybackState method as follows, then it works as expected; though, I'm not sure if I should be doing it this way.

public void updatePlaybackState() {
    int state = isPlaying() ? PlaybackStateCompat.STATE_PLAYING : PlaybackStateCompat.STATE_PAUSED;
    int ms = getCurrentPosition();
    mediaSession.setPlaybackState(new PlaybackStateCompat.Builder()
            .setState(PlaybackStateCompat.STATE_NONE, ms, 1f)
            .build());
    mediaSession.setPlaybackState(new PlaybackStateCompat.Builder()
            .setState(state, ms, 1f)
            .build());
}

As you can see, I set the state to STATE_NONE and then I re-set the state back to STATE_PLAYING to cause Android to notice that the state changed, which re-publishes the current position to the connected Bluetooth device.

like image 424
Nick Avatar asked Jun 23 '15 05:06

Nick


1 Answers

How does the bluetooth device read the position? I'm assuming some code constantly monitors the playbackstate to get the current position?

To prevent you from constantly having to update the PlaybackState, the playback state contains the necessary values to compute the approximate current position of the stream.

When setting the playbackState, you provide values such as speed, current position and the update time.

PlaybackState.Buider.setState(int state, long position, float playbackSpeed, long updateTime)

Given the assertion that unless the playback state changes and it is currently playing, you can calculate the currentPosition from the lastUpdate time, speed and the previousPosition.

long timeDelta = SystemClock.elapsedRealtime() - lastPlaybackState.getLastPositionUpdateTime();
long currentPosition = (int) timeDelta * lastPlaybackState.getPlaybackSpeed();

You can take a look at how uAmp does this in FullScreenPlayerActivity. The specific method is updateProgress(..)

like image 175
Nagesh Susarla Avatar answered Nov 15 '22 07:11

Nagesh Susarla