5

我已经构建了一个部署在 android google playstore 中的音频播放器。我正在使用 crashlytics 来监控崩溃和 ANR。最近我遇到了很多崩溃 MediaButtonReceiver。耳机咔哒声在许多设备中都能正常工作。但是有些设备会出现这个问题。

Crashlytics 报告 -

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)

媒体会话代码 -

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



    }

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

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

4

2 回答 2

6

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

然后你必须在你的 Manifest 中声明那个接收器类(或者替换你之前的MediaButtonReceiver类声明,如果你有的话),比如:

<receiver android:name=".MyMediaButtonReceiver" >
    <intent-filter>
        <action android:name="android.intent.action.MEDIA_BUTTON" />
    </intent-filter>
</receiver>
于 2018-08-24T13:26:24.613 回答
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 android:name=".player.receivers.MyMediaButtonReceiver" >
        <intent-filter>
            <action android:name="android.intent.action.MEDIA_BUTTON" />
        </intent-filter>
    </receiver>
于 2020-10-27T15:30:39.790 回答