我有一个带有MusicPlayingService(扩展MediaBrowserServiceCompat
)和一个小部件来控制服务的音乐播放器应用程序。MusicPlayingService还引用了一个MusicStateManager
(在MusicServices onCreate中创建),它实现"MediaSessionCompat.Callback
"并处理来自当前MediaSession的所有回调:mSession.setCallback(MusicStateManager);
public class MusicPlayingService extends MediaBrowserServiceCompat implements
AudioManager.OnAudioFocusChangeListener {
@RequiresPermission(Manifest.permission.READ_PHONE_STATE)
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "MusicPlayingService started");
.....
mPlayerStateManager = new MusicStateManager(this);
.....
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand");
MediaButtonReceiver.handleIntent(mPlayerStateManager.getSession(), intent);
return START_STICKY;
}
然后,我的小部件有一堆待处理的意图,这些意图被发送到MusicPlayingService
并由MusicStateManager
处理。一切都很好。
public class MusicStateManager extends MediaSessionCompat.Callback {
....
public MusicStateManager(@NonNull MusicStateManager argService) {
Log.d(TAG, "setting service");
mPlayerService = argService;
ComponentName mediaButtonReceiver = new ComponentName(mPlayerService, HeadsetReceiver.class);
mSession = new MediaSessionCompat(mPlayerService, SESSION_TAG, mediaButtonReceiver, null);
mSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS |
MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
PendingIntent pendingMediaButtonIntent = PendingIntent.getBroadcast(mPlayerService, 0, mediaButtonIntent, 0);
mSession.setMediaButtonReceiver(pendingMediaButtonIntent);
Intent toggleIntent = new Intent(NotificationPlayer.toggleAction);
PendingIntent pendingToggleIntent = PendingIntent.getBroadcast(mPlayerService, 0, toggleIntent, 0);
mSession.setMediaButtonReceiver(pendingToggleIntent);
mSession.setCallback(this);
mSession.setActive(true);
}
/**
* Callback method called from MusicStateManager whenever the music is about to play.
*/
public void onPlay() {
Log.d(TAG, "onPlay");
.......
}
@Override
public void onCustomAction(String action, Bundle extras) {
Log.d(TAG, "received action: " + action); // NoI18N
if (ACTION_TOGGLE.equals(action)) {
mPlayerService.toggle();
}
}
问题是。如果我强制停止应用程序,音乐服务将关闭(显然)。如果我按下小部件上的按钮,它会再次启动我的服务(我可以从 LogCat 中的各种 Log.d(...) 中看到它。但是,小组件中的待处理意图将丢失,并且从未处理过。
这对用户有奇怪的影响。大多数情况下,小部件上的按钮将起作用(当服务运行时)。但是,有时(当服务未运行时)按钮在第一次按下时不会执行任何操作,但是如果您再次按下它们,它们将起作用(因为第一次按下启动了服务,但无法处理意图。
知道如何调试此问题并查看我的挂起意图会发生什么吗?
为媒体播放创建PendingIntent
的最佳方法是使用 MediaButtonReceiver.buildMediaButtonPendingIntent()。这允许您传入一个将触发正确回调的PlaybackStateCompat.ACTION_
常量。
PendingIntent playPendingIntent = MediaButtonReceiver
.buildMediaButtonPendingIntent(context, PlaybackStateCompat.ACTION_PLAY);
似乎您已经在onStartCommand()
中调用了正确的MediaButtonReceiver.handleIntent()
,但您还应该确保在创建MediaSessionCompat
时通过调用setPlaybackState()
来启用正确的操作:
// Ideally, you should keep a reference to this Builder to update it,
// rather than create it from scratch each time
PlaybackStateCompat.Builder playbackStateBuilder = new PlaybackStateCompat.Builder()
.setActions(PlaybackStateCompat.ACTION_PLAY |
PlaybackStateCompat.ACTION_PLAY_PAUSE);
mSession.setPlaybackState(playbackStateBuilder.build());
MediaSessionCompat
默认情况下不允许任何媒体按钮。通过确保直接从实例化支持ACTION_PLAY
,可以确保第一个MediaButtonReceiver.handleIntent()
正确调用您的MediaSessionCompat.Callback
。