服务停止时,Widget中的PendingIntent丢失

时间:2016-12-10 21:14:01

标签: android android-widget android-service android-pendingintent

我有一个音乐播放器应用,带有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;
}

我的窗口小部件有一堆Pending Intents,它们被发送到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丢失了,从未处理过。

这对用户有奇怪的含义。大多数情况下,窗口小部件上的按钮都可以工作(当服务运行时)。但是,有时(当服务没有运行时)按钮在第一次按下时什么都不做,但是如果你再次按下按钮它们将起作用(因为第一次按下启动服务,但未能处理意图。

我知道如何调试此问题,看看我的PendingIntent会发生什么?

1 个答案:

答案 0 :(得分:1)

为媒体播放创建PendingIntent的最佳方法是使用MediaButtonReceiver.buildMediaButtonPendingIntent()。这允许您传入PlaybackStateCompat.ACTION_常量,以触发正确的回调。

PendingIntent playPendingIntent = MediaButtonReceiver
  .buildMediaButtonPendingIntent(context, PlaybackStateCompat.ACTION_PLAY);

您似乎已在MediaButtonReceiver.handleIntent()中进行了正确的onStartCommand()来电,但您还应确保在创建MediaSessionCompat时通过调用{{1}启用正确的操作}:

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()