Android 13 playbackstate callback not called ( from notification buttons)

808 views Asked by At

For mediaplayer, ACTION_SKIP_TO_NEXT and ACTION_SKIP_TO_PREVIOUS both are working fine from notification buttons for android 12 and below. it seems that android 13 has a different behavior according to this.

to be clear, below buttons in the pictures are not working in android 13 only. enter image description here

Android developer mentioned that playbackstate should be used for android 13

"For apps targeting Android 13 (API level 33) and higher, the system derives media controls from PlaybackState actions."

the problem is that in android 13 playstechange is never called, even public int onStartCommand is never called.

tried below code but even no use

        ComponentName receiver = new ComponentName(this, MediaButtonReceiver.class);
    mediaSession = new MediaSessionCompat(getApplicationContext(), "MediaSession", receiver, null);
    mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS |
            MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);

    mediaSession.setPlaybackState(new PlaybackStateCompat.Builder()
            .setState(PlaybackStateCompat.STATE_PAUSED, 0, 0)
            .setActions(PlaybackStateCompat.ACTION_PLAY_PAUSE)
            .setActions(PlaybackStateCompat.ACTION_SKIP_TO_NEXT)                .setActions(PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS)
            .build());

    mediaSession.setActive(true);

 mediaSession.setCallback(new MediaSessionCompat.Callback() {
        // Implement callbacks

        @Override
        public boolean onMediaButtonEvent(Intent mediaButtonEvent) {
            final String intentAction = mediaButtonEvent.getAction();

            if (Intent.ACTION_MEDIA_BUTTON.equals(intentAction)) {
                final KeyEvent event = mediaButtonEvent.getParcelableExtra(
                        Intent.EXTRA_KEY_EVENT);
                if (event == null) {
                    return super.onMediaButtonEvent(mediaButtonEvent);
                }
                final int keycode = event.getKeyCode();
                final int action = event.getAction();
                if (event.getRepeatCount() == 0 && action == KeyEvent.ACTION_DOWN) {
                    switch (keycode) {
                        case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
                            if (mediaPlayer != null) {
                                if (isPlaying()) {
                                    playbackAction(1);                                        
                                    pauseMedia();                                        
                                    updateMetaData();
                                } else { // want to continue playing
                                    playbackAction(0);
                                    playMedia();
                                }
                            }                              
                            break;
                        case KeyEvent.KEYCODE_MEDIA_PAUSE:
                            pauseMedia();
                            break;
                        case KeyEvent.KEYCODE_MEDIA_PLAY:

                            process_play_request();
                            break;
                        case KeyEvent.KEYCODE_MEDIA_NEXT:
                            skipToPrevious();
                            break;
                        case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
                            skipToNext();
                            break;
                    }
                }
            }
            return super.onMediaButtonEvent(mediaButtonEvent);
        }});
    

and tried to add this code, but also no use:

         MediaControllerCompat mController;

    mController = new MediaControllerCompat(this, mediaSession.getSessionToken());


    mController.registerCallback(mCallback);
    mCallback.onPlaybackStateChanged(mController.getPlaybackState());
    mCallback.onMetadataChanged(mController.getMetadata());

private final MediaControllerCompat.Callback mCallback = new MediaControllerCompat.Callback() {
    @Override
    public void onPlaybackStateChanged(PlaybackStateCompat playbackState) {
        onUpdate();
    }

    @Override
    public void onMetadataChanged(MediaMetadataCompat metadata) {
        onUpdate();
    }

    @Override
    public void onSessionDestroyed() {
    }

    private void onUpdate() {
    }
};

This issue has no relation to android.permission.POST_NOTIFICATIONS as runtime permission is requested and granted but still no use.

Noting that after media player perpared, SetState is called as below:

mediaPlayer.start();

            setState(PlaybackStateCompat.STATE_PLAYING);

private void setState(int state) {
    long position = 0;

    PlaybackStateCompat.Builder builder = new PlaybackStateCompat.Builder();
    builder.setState(state, position, 1.0f);
    builder.setActions(
            PlaybackStateCompat.ACTION_PLAY |
                    PlaybackStateCompat.ACTION_STOP |
                    PlaybackStateCompat.ACTION_PAUSE |
                    PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS |
                    PlaybackStateCompat.ACTION_SKIP_TO_NEXT);
    mediaSession.setPlaybackState(builder.build());


}

suggestions please

2

There are 2 answers

0
Chipunpun On BEST ANSWER

Please try to add a few override methods to your MediaSessionCompat.Callback():

mediaSession.setCallback(new MediaSessionCompat.Callback() {
    // Implement callbacks
    @Override
    public boolean onMediaButtonEvent(Intent mediaButtonEvent) {
        // your implements
    }

    @Override
    public void onPlay() {
        super.onPlay();
        // your play() implements
    }

    @Override
    public void onPause() {
        super.onPause();
        // your pause() implements
    }

    @Override
    public void onSkipToNext() {
        super.onSkipToNext();
        // your next() implements
    }

    @Override
    public void onSkipToPrevious() {
        super.onSkipToPrevious();
        // your prev() implements
    }

    @Override
    public void onSeekTo(long pos) {
        // your seek() implements
    }
});

You will receive the action buttons event in these callbacks.

2
Atomyk Gaming On

I was having the same problem and then I realized I was doing one thing wrong I had to set those actions when I was building my notification along with action_seek_to first set the state to playing or paused and then set action using (or) that's it hope it will help