Home » Android » How to use the new MediaSession class to receive media button presses on Android 5.x?

How to use the new MediaSession class to receive media button presses on Android 5.x?

Posted by: admin May 14, 2020 Leave a comment

Questions:

I’m attempting to receive media button presses using the new MediaSession class and so far I’ve been unsuccessful. Has anyone managed to receive them using the new class?

I’ve been successful in creating a MediaSession and using it to update song information on a remote display (an in-car entertainment system) but so far I’m unable to receive button presses from it, headphone controls, and controls on Bluetooth headsets.

After I create the media session I’m executing the following in a service that I use to play audio:

    _mediaSession = new MediaSession(getApplicationContext(), Global.PACKAGE_NAME + "." + TAG);

    if (_mediaSession == null) {
        _log.e(TAG, "initMediaSession: _mediaSession = null");
        return;
    }

    _mediaSessionToken = _mediaSession.getSessionToken();

    _mediaSession.setCallback(new Callback() {
        public boolean onMediaButtonEvent(Intent mediaButtonIntent) {
            _log.d(TAG, "onMediaButtonEvent called: " + mediaButtonIntent);             
            return false;
        }

        public void onPause() {
            Log.d(TAG, "onPause called (media button pressed)");                
            super.onPause();
        }

        public void onPlay() {
            Log.d(TAG, "onPlay called (media button pressed)");             
            super.onPlay();
        }

        public void onStop() {
            Log.d(TAG, "onStop called (media button pressed)");             
            super.onStop();
        }
    });             

     _mediaSession.setFlags(MediaSession.FLAG_HANDLES_MEDIA_BUTTONS | MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS);

    PlaybackState state = new PlaybackState.Builder()
    .setActions(PlaybackState.ACTION_PLAY)
    .setState(PlaybackState.STATE_STOPPED, PlaybackState.PLAYBACK_POSITION_UNKNOWN, SystemClock.elapsedRealtime())
    .build();

    _mediaSession.setPlaybackState(state);

    _mediaSession.setActive(true);

but I’m still not receiving any button presses.

Anyone have any ideas?

Thanks

Update After changing

    PlaybackState state = new PlaybackState.Builder()
    .setActions(PlaybackState.ACTION_PLAY)
    .setState(PlaybackState.STATE_STOPPED, PlaybackState.PLAYBACK_POSITION_UNKNOWN, SystemClock.elapsedRealtime())
    .build();

to

    PlaybackState state = new PlaybackState.Builder()
    .setActions(PlaybackState.ACTION_PLAY)
    .setState(PlaybackState.STATE_STOPPED, PlaybackState.PLAYBACK_POSITION_UNKNOWN, 0)
    .build();

I’m now receiving button press notifications via the onMediaButtonEvent() callback (such as being notified that KEYCODE_MEDIA_PAUSE was pressed) but onPlay(), onPause(), and onStop() are never being called, any idea why?

How to&Answers:

onMediaButtonEvent(..) has a default implementation in MediaSession.Callback. In your code if you call super.onMediaButtonEvent(..), then depending on the keycodes the correct callback namely onPlay(), onPause() will be called.

You can take a look at the default implementation in MediaSession.java

Answer:

The default implementation of onMediaButtonEvent is what figures out the specific callback for a given media key event. Since you’re overriding onMediaButtonEvent and not calling the super’s implementation you will only get onPlay/Pause/etc. calls from other apps that are using a MediaController to make those calls directly.

If you add change your implementation to

public boolean onMediaButtonEvent(Intent mediaButtonIntent) {
    _log.d(TAG, "onMediaButtonEvent called: " + mediaButtonIntent);             
    return super.onMediaButtonEvent(mediaButtonIntent);
}

You should start seeing the keys translated to the other callback methods.