单击耳机按钮时应用崩溃

时间:2018-07-06 18:58:30

标签: android android-mediaplayer audio-player headset android-mediasession

我已经构建了一个音频播放器,该音频播放器已部署在android Google Playstore中。我正在使用crashlytics监视崩溃和ANR。最近,我在MediaButtonReceiver中崩溃了很多。耳机喀哒声在许多设备上都可以正常工作。但是某些设备正在解决此问题。

崩溃报告-

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代码-

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;
            }
        });



    }

可能是什么问题以及如何解决?

我的想法-可能是因为用户在我的应用仍在播放时打开了其他具有此功能的音乐应用。

2 个答案:

答案 0 :(得分:0)

class MyMediaButtonReceiver : MediaButtonReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        if (intent.action == Intent.ACTION_MEDIA_BUTTON) {
            val event = intent.getParcelableExtra<KeyEvent>(Intent.EXTRA_KEY_EVENT)
            if (event.action == KeyEvent.ACTION_UP || event.action == 
KeyEvent.ACTION_DOWN) {
            when (event.keyCode) {
                // handle cancel button
                KeyEvent.KEYCODE_MEDIA_STOP -> context.sendIntent(ACTION_FINISH)
               // handle play button
                KeyEvent.KEYCODE_MEDIA_PLAY, KeyEvent.KEYCODE_MEDIA_PAUSE -> context.sendIntent(ACTION_PLAY_PAUSE)
                }
            }
        }
    }
}

将事件发送到媒体服务的kotlin扩展

fun Context.sendIntent(action: String) {
    Intent(this, MediaPlayerService::class.java).apply {
        this.action = action
        try {
            if (isOreoPlus()) {
                startForegroundService(this)
            } else {
                startService(this)
            }
        } catch (ignored: Exception) {
        }
    }
}

在清单中添加Receiver

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

答案 1 :(得分:-2)

您必须创建自己的媒体按钮接收器类,例如MyMediaButtonReceiver.java,该类扩展了MediaButtonReceiver,除了必须重写的onReceive方法之外,它将为空,调用捕获super.onReceive(...)的try-catch之间的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());
        }
    }
}

然后,您必须在清单中声明该接收者类(或替换先前的MediaButtonReceiver类声明(如果有的话)),例如:

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