App crash on headset button click

◇◆丶佛笑我妖孽 提交于 2019-12-23 19:42:02

问题


I have build an audioplayer which is deployed in android google playstore. I'm using crashlytics to monitor crashes and ANRs. Recently I have been getting a lot of crashes MediaButtonReceiver. The headset clicks work fine in many devices. But some devices are giving this problem.

Crashlytics report -

Fatal Exception: java.lang.RuntimeException: Unable to start receiver android.support.v4.media.session.MediaButtonReceiver: java.lang.IllegalStateException: Could not find any Service that handles android.intent.action.MEDIA_BUTTON or implements a media browser service.
       at android.app.ActivityThread.handleReceiver(ActivityThread.java:2866)
       at android.app.ActivityThread.access$1700(ActivityThread.java:182)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1551)
       at android.os.Handler.dispatchMessage(Handler.java:111)
       at android.os.Looper.loop(Looper.java:194)
       at android.app.ActivityThread.main(ActivityThread.java:5706)
       at java.lang.reflect.Method.invoke(Method.java)
       at java.lang.reflect.Method.invoke(Method.java:372)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1033)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:828)

MediaSession code -

private void initMediaSession() throws RemoteException {
        if (mediaSessionManager != null) return; //mediaSessionManager exists

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            mediaSessionManager = (MediaSessionManager) getSystemService(Context.MEDIA_SESSION_SERVICE);
        }
        // Create a new MediaSession
        mediaSession = new MediaSessionCompat(this, "AudioPlayer");
        //Get MediaSessions transport controls
        transportControls = mediaSession.getController().getTransportControls();
        //set MediaSession -> ready to receive media commands
        mediaSession.setActive(true);
        //indicate that the MediaSession handles transport control commands
        // through its MediaSessionCompat.Callback.
        mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS|MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS);


        //Set mediaSession's MetaData
        updateMetaData();


        mediaSession.setCallback(new MediaSessionCompat.Callback() {
            @Override
            public void onPlay() {
                super.onPlay();

                resumeMedia();
            }

            @Override
            public void onPause() {
                super.onPause();

                pauseMedia();
            }

            @Override
            public void onSkipToNext() {
                super.onSkipToNext();

            }

            @Override
            public void onSkipToPrevious() {
                super.onSkipToPrevious();

            }

            @Override
            public boolean onMediaButtonEvent(Intent mediaButtonIntent) {

                if (su.getHeadsetEnableSwitch()) {

                    String intentAction = mediaButtonIntent.getAction();
                    if (Intent.ACTION_MEDIA_BUTTON.equals(intentAction)) {
                        KeyEvent event = mediaButtonIntent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);

                        if (event != null) {


                            int action = event.getAction();
                            Log.e("Headset key: ", String.valueOf(action));
                            if (action == KeyEvent.ACTION_DOWN) {

                                Log.e("Headset: ", "Action down");

                                headsetClickCount++;

                                new Handler().postDelayed(new Runnable() {
                                    @Override
                                    public void run() {

                                        if (headsetClickCount == 1) {

                                            if (isPng()) pauseMedia();
                                            else resumeMedia();

                                            headsetClickCount = 0;

                                        } else if (headsetClickCount == 2) {

                                            if (su.getDoubleClickAction() == 0) {
                                            } else if (su.getDoubleClickAction() == 1)
                                                skipToPrevious();
                                            else if (su.getDoubleClickAction() == 2) skipToNext();
                                            headsetClickCount = 0;
                                        } else if (headsetClickCount == 3) {

                                            if (su.getTripleClickAction() == 0) {
                                            } else if (su.getTripleClickAction() == 1)
                                                skipToPrevious();
                                            else if (su.getTripleClickAction() == 2) skipToNext();
                                            headsetClickCount = 0;
                                        }
                                    }
                                }, 750);
                            }

                            if (action == KeyEvent.FLAG_LONG_PRESS) {

                                if (su.getLongClickAction() == 0) {
                                } else if (su.getLongClickAction() == 1) skipToPrevious();
                                else if (su.getLongClickAction() == 2) skipToNext();

                            }


                            if (action == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE) {

                                Log.e("Headset: ", "headset sethook");
                                if (isPng()) pauseMedia();
                                else resumeMedia();
                            }

                            if (action == KeyEvent.KEYCODE_MEDIA_NEXT) {

                                skipToNext();
                            }

                            if (action == KeyEvent.KEYCODE_MEDIA_PREVIOUS) {

                                skipToPrevious();
                            }

                            if (action == KeyEvent.KEYCODE_MEDIA_PAUSE) {

                                pauseMedia();
                            }

                            if (action == KeyEvent.KEYCODE_MEDIA_PLAY) {

                                resumeMedia();
                            }


                        }
                    }

                    return true;

                }

            return true;
            }
        });



    }

What could be the problem and how to solve this?

My thoughts - Maybe this happens because user opens other music apps that has this feature while my app is still playing.


回答1:


You have to create your own media button receiver class, say MyMediaButtonReceiver.java, that extends MediaButtonReceiver, and it will be empty except for the onReceive method that you have to override, calling super.onReceive(...) between a try-catch that captures the IllegalStateException:

public class MyMediaButtonReceiver extends MediaButtonReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        try {
            super.onReceive(context, intent);
        } catch (IllegalStateException e) {
            Log.d(this.getClass().getName(), e.getMessage());
        }
    }
}

Then you have to declare that receiver class in your Manifest (or replace your previous MediaButtonReceiver class declaration, if you had one), like:

<receiver android:name=".MyMediaButtonReceiver" >
    <intent-filter>
        <action android:name="android.intent.action.MEDIA_BUTTON" />
    </intent-filter>
</receiver>


来源:https://stackoverflow.com/questions/51216279/app-crash-on-headset-button-click

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!