我已经构建了一个部署在android google playstore中的audioplayer。我正在使用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)
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;
}
});
}
可能是什么问题以及如何解决这个问题?
我的想法 - 也许这是因为用户在我的应用仍然在播放时打开具有此功能的其他音乐应用。
你必须创建你自己的媒体按钮接收器类,比如扩展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());
}
}
}
然后你必须在你的Manifest中声明接收器类(或者替换你以前的MediaButtonReceiver
类声明,如果你有的话),例如:
<receiver android:name=".MyMediaButtonReceiver" >
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>