一旦服务不再处于前台,就可以取消来自前台服务的通知

Make a notification from a foreground service cancelable once the service is not in foreground anymore

我有一个允许用户 start/stop 音乐的音乐控制通知。我想要与 Google Play Music 应用程序通知完全相同的行为:当音乐正在播放时,服务在前台并且通知不可取消,当音乐不播放时服务不再在前台并且可以删除通知。它工作正常,但是当我取消我的服务的前台时,通知很快就被删除了,然后又重新出现了。

这是我的代码,首先是我如何构建通知:

NotificationCompat.Builder notifBuilder =
            new android.support.v7.app.NotificationCompat.Builder(getApplicationContext())
                    .setStyle(new android.support.v7.app.NotificationCompat.MediaStyle()
                            .setShowActionsInCompactView(1, 2, 3)
                            .setShowCancelButton(true)
                            .setCancelButtonIntent(deletePendingIntent)))
                    .setSmallIcon(R.drawable.notif_logo)
                    .setColor(ResourcesCompat.getColor(getResources(), R.color.blue, getTheme()))
                    .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
                    .setShowWhen(false);

    notifBuilder.setContentIntent(pendingIntent);
    notifBuilder.setDeleteIntent(deletePendingIntent);

这是我开始和更新通知的方式:

private void showNotification(NotificationCompat.Builder notifBuilder, boolean foreground) {
    if (foreground) {
        startForeground(NOTIFICATION_ID, notifBuilder.build());
    } else {
        stopForeground(false);

        NotificationManager notificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.notify(NOTIFICATION_ID, notifBuilder.build());
    }
}

如果我使用 stopForeground(false),通知在 运行 之后仍然不可取消。如果我使用 stopForeground(true),通知会被快速删除然后再次添加,这会产生奇怪的闪烁。

如何在服务退出前台后获得可取消的通知,而无需删除然后再次添加通知?

根据 Using MediaStyle notifications with a foreground service documentation:

In Android 5.0 (API level 21) and later you can swipe away a notification to stop the player once the service is no longer running in the foreground. You can't do this in earlier versions. To allow users to remove the notification and stop playback before Android 5.0 (API level 21), you can add a cancel button in the upper-right corner of the notification by calling setShowCancelButton(true) and setCancelButtonIntent().

您永远不需要调用 setOngoing(false)/setOngoing(true),因为这由您的服务当前是否在前台控制。

根据 Media Session Callbacks docs,当您的音乐暂停时,您应该被呼叫 stopForeground(false) - 这会删除前台优先级并允许用户在 API 上滑动通知 21+设备。