我已经构建了一个音频播放器,该音频播放器已部署在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;
}
});
}
可能是什么问题以及如何解决?
我的想法-可能是因为用户在我的应用仍在播放时打开了其他具有此功能的音乐应用。
答案 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>