Android MediasessionCompat callback function for physical media player button keeps crashing

1k Views Asked by At

I used the code from this link MediaSession onMediaButtonEvent works for a few seconds then quits - Android to capture the keyevents of the remote button and send it to the audio() function where the selection will be played by another mediaplayer.

I run into the same problems where the code will crash after a few seconds. I so far tried to do a loop and also made the audio track not to do at.stop() or do at.release but eventually it still crashes. This keeps the service alive for a bit but then will still crash. I have the code and logcat

public class PlayerService extends Service {
    private MediaSessionCompat mediaSession;
    AudioTrack at;
    @Override
    public void onCreate() {
        super.onCreate();
        MediaSession ms = new MediaSession(getApplicationContext(), getPackageName());

        ms.setActive(true);

        ms.setCallback(new MediaSession.Callback() {
            @Override
            public boolean onMediaButtonEvent(Intent mediaButtonIntent) {
                KeyEvent keyEvent = (KeyEvent)     mediaButtonIntent.getExtras().get(Intent.EXTRA_KEY_EVENT);
                if (keyEvent.getAction() == KeyEvent.ACTION_DOWN) {
                    switch (keyEvent.getKeyCode()) {
                      
                        case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:

                            audio("button0");
                            break;
                        case KeyEvent.KEYCODE_MEDIA_REWIND:

                            audio("button1");
                            break;
                        case KeyEvent.KEYCODE_MEDIA_NEXT:

                            audio("button2");
                            break;
                        case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
                            audio("button3");
                            break;
                     
                    }
                }
                return super.onMediaButtonEvent(mediaButtonIntent);
            }


        });
        Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
        PendingIntent mediaButtonReceiverPendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, mediaButtonIntent, 0);

        ms.setMediaButtonReceiver(mediaButtonReceiverPendingIntent);

        at = new AudioTrack(AudioManager.STREAM_MUSIC, 48000, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT,
                AudioTrack.getMinBufferSize(48000, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT), AudioTrack.MODE_STREAM);

       
       **//at.setLoopPoints(3, 10,10000000);
        at.play();
        at.stop();
        at.release();**
        


    }


    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mediaSession.release();

    }



    public void audio(String command) {

        MediaPlayer player = new MediaPlayer();


        try {

            switch (command) {
                case "button0":
                    player = MediaPlayer.create(this, R.raw.button0);
                    break;
                case "button1":
                    player = MediaPlayer.create(this, R.raw.button1);
                    break;
                case "button2":
                    player = MediaPlayer.create(this, R.raw.button2);
                    break;
                case "button3":
                    player = MediaPlayer.create(this, R.raw.button3);
                     
                    break;
            }


            player.start();
            Thread.sleep(1000);

        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

My logcat log


2022-02-13 19:08:01.568 19045-19060/com.example.medialistenercopy W/MediaPlayer-JNI: MediaPlayer finalized without being released
2022-02-13 19:08:01.568 19045-19060/com.example.medialistenercopy I/MediaPlayerNative: setListener
2022-02-13 19:08:01.569 19045-19060/com.example.medialistenercopy I/MediaPlayerNative: disconnect
2022-02-13 19:08:01.580 19045-19060/com.example.medialistenercopy I/MediaPlayerNative: destructor
2022-02-13 19:08:01.581 19045-19060/com.example.medialistenercopy I/MediaPlayerNative: disconnect
2022-02-13 19:08:56.467 19045-19045/com.example.medialistenercopy D/AndroidRuntime: Shutting down VM

    --------- beginning of crash
2022-02-13 18:57:56.595 17903-17903/com.example.medialistenercopy E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.medialistenercopy, PID: 17903
    java.lang.RuntimeException: Unable to stop service com.example.medialistenercopy.PlayerService@e1c144e: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v4.media.session.MediaSessionCompat.release()' on a null object reference
        at android.app.ActivityThread.handleStopService(ActivityThread.java:3880)
        at android.app.ActivityThread.access$1700(ActivityThread.java:208)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1733)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:205)
        at android.app.ActivityThread.main(ActivityThread.java:6991)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:884)
     Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v4.media.session.MediaSessionCompat.release()' on a null object reference
        at com.example.medialistenercopy.PlayerService.onDestroy(PlayerService.java:114)
        at android.app.ActivityThread.handleStopService(ActivityThread.java:3860)
        at android.app.ActivityThread.access$1700(ActivityThread.java:208) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1733) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:205) 
        at android.app.ActivityThread.main(ActivityThread.java:6991) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:884) 
2022-02-13 18:57:56.668 17903-17903/com.example.medialistenercopy I/Process: Sending signal. PID: 17903 SIG: 9

 

Is the problem because the fake audio track ended too soon or because I have another mediaplayer playing sounds too. I am tweeking everything I can.

I tried to tweek the audio track and I got

2022-02-13 20:58:55.609 27560-27560/com.example.medialistenercopy V/AudioTrack: getMinFrameCount=3844: afFrameCount=1920, afSampleRate=48000, afLatency=80
2022-02-13 20:58:55.610 27560-27560/com.example.medialistenercopy V/AudioTrack: set(): streamType -1, sampleRate 48000, format 0x1, channelMask 0x3, frameCount 3844, flags #0, notificationFrames 0, sessionId 0, transferType 3, uid -1, pid -1
2022-02-13 20:58:55.610 27560-27560/com.example.medialistenercopy V/AudioTrack: Building AudioTrack with attributes: usage=1 content=2 flags=0x0 tags=[]
2022-02-13 20:58:55.619 27560-27560/com.example.medialistenercopy W/AudioTrack: Use of stream types is deprecated for operations other than volume control
2022-02-13 20:58:55.619 27560-27560/com.example.medialistenercopy W/AudioTrack: See the documentation of AudioTrack() for what to use instead with android.media.AudioAttributes to qualify your playback use case
2022-02-13 20:58:55.625 27560-27560/com.example.medialistenercopy V/AudioTrack: ~AudioTrack, releasing session id 8857 from 27560 on behalf of 27560
2022-02-13 20:58:55.626 27560-27560/com.example.medialistenercopy W/MediaAnalyticsItem: Unable to record: [1:audiotrack:0:-1::0:-1:1:0:5:android.media.audiotrack.underrunframes=1922:android.media.audiotrack.type=AUDIO_CONTENT_TYPE_MUSIC:android.media.audiotrack.usage=AUDIO_USAGE_MEDIA:android.media.audiotrack.samplerate=48000:android.media.audiotrack.channelmask=3:] [forcenew=0]
1

There are 1 best solutions below

3
Paul Lammertsma On

The specific reason for your crash is likely because you do not assign the field mediaSession; you've instead assigned an instance of MediaSession to a variable in a function scope inside onCreate().

I would like to call out that we recommend handling the onPlay(), onPause(), onFastForward(), etc. callbacks from MediaSession.Callback, as opposed to implementing onMediaButtonEvent(). The reason for this, is that not all actions are provided as a media button, such as seek commands, ratings or custom actions.

For more information about media sessions, see also my contextual video on this topic and the dedicated codelab.