1

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 Answers2

0

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

Aldan
  • 674
  • 9
  • 23
  • 1
    I don't get your answer, again every thing is working fine in android 12. problem is only in android 13. – صلي علي محمد - Atef Farouk May 20 '23 at 02:48
  • Well i am sorry for that here is my repository https://github.com/AbhinavSachan/Atomyk_Play/blob/thrid_branch/AtomykPlay/app/src/main/java/com/atomykcoder/atomykplay/services/MediaPlayerService.kt. Go to the method where i am initiating media session and then watch buildNotification function watch it carefully all the stuff for your solution is there – Atomyk Gaming May 21 '23 at 03:49
0

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.

Chipunpun
  • 40
  • 6