我有一个Media服务,它使用startForeground()在播放开始时显示通知。播放时有暂停/停止按钮,暂停时有播放/停止按钮。
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
// setup...
Notification n = mBuilder.build();
if (state == State.Playing) {
startForeground(mId, n);
}
else {
stopForeground(false);
mNotificationManager.notify(mId, n);
}
这里的问题是当我显示/更新处于暂停状态的通知时,应该允许您将其删除。 mBuilder.setOngoing(false)
似乎没有效果,因为之前的startForeground
会覆盖它。
使用相同的代码调用stopForeground(true);
按预期工作,但通知会在销毁并重新创建时闪烁。有没有办法“更新”从startForeground创建的通知,以便在调用stop后将其删除?
编辑:根据要求,这是创建通知的完整代码。只要播放或暂停服务,就会调用createNotification。
private void createNotification() {
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("No Agenda")
.setContentText("Live stream");
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
{
if (state == State.Playing) {
Intent pauseIntent = new Intent(this, MusicService.class);
pauseIntent.setAction(ACTION_PAUSE);
PendingIntent pausePendingIntent = PendingIntent.getService(MusicService.this, 0, pauseIntent, 0);
mBuilder.addAction(R.drawable.pause, "Pause", pausePendingIntent);
//mBuilder.setOngoing(true);
}
else if (state == State.Paused) {
Intent pauseIntent = new Intent(this, MusicService.class);
pauseIntent.setAction(ACTION_PAUSE);
PendingIntent pausePendingIntent = PendingIntent.getService(MusicService.this, 0, pauseIntent, 0);
mBuilder.addAction(R.drawable.play, "Play", pausePendingIntent);
mBuilder.setOngoing(false);
}
Intent stopIntent = new Intent(this, MusicService.class);
stopIntent.setAction(ACTION_STOP);
PendingIntent stopPendingIntent = PendingIntent.getService(MusicService.this, 0, stopIntent, 0);
setNotificationPendingIntent(mBuilder);
mBuilder.addAction(R.drawable.stop, "Stop", stopPendingIntent);
}
else
{
Intent resultIntent = new Intent(this, MainActivity.class);
PendingIntent intent = PendingIntent.getActivity(this, 0, resultIntent, 0);
mBuilder.setContentIntent(intent);
}
Notification n = mBuilder.build();
if (state == State.Playing) {
startForeground(mId, n);
}
else {
stopForeground(true);
mNotificationManager.notify(mId, n);
}
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
private void setNotificationPendingIntent(NotificationCompat.Builder mBuilder) {
Intent resultIntent = new Intent(this, MainActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addParentStack(MainActivity.class);
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
mBuilder.setContentIntent(resultPendingIntent);
}
后续编辑:
下面的评论之一提到答案可能是“脆弱的”,并且自Android 4.3发布以来,startForeground
背后的行为已经改变。 startForeground将强制您的应用程序在前台显示通知,并且应该通过显示通知来调用该方法。我没有测试过,但接受的答案可能不再符合预期。
在调用stopForeground
时停止闪烁方面,我认为不值得对抗框架。
有一些additional information on the Android 4.3 notification change here。
答案 0 :(得分:5)
您可以考虑使用其他方法
既然你应该使用前台服务来完成这样的任务(媒体播放)我建议你继续做start foreground()
,但是不要向它发送通知,只需设置id 0和通知null就像这样startForeground(0, null);
。
这样前台服务不会显示任何通知。
现在,出于您的目的,您可以使用常规通知并更新其状态(正在进行的,布局,文本等等),这样您就不依赖于前台服务的通知行为。
希望这有帮助。
答案 1 :(得分:4)
而不是stopService(true)
,调用stopService(false)
将保留通知(没有正在进行的状态),除非用户解散/以编程方式删除或服务停止。因此,只需调用stopService(false)并更新通知以显示暂停状态,现在可以由用户解除通知。这也可以防止闪烁,因为我们没有重新创建通知。
答案 2 :(得分:3)
根据docs,此行为是在棒棒糖之前设计的
针对此版本或更高版本的应用程序将在行为中获得以下新变化:
...
- 使用removeNotification false调用Service.stopForeground将修改仍然发布的通知,以便不再强制它继续进行。
答案 3 :(得分:1)
在N之前,必须在序列中调用stopForeground和startForeground时重新显示通知。您需要再次显示该通知,并且在暂停后不要将其设为前台通知。我建议您不要添加变通办法或修改此漏洞。(有变通办法,但可能会引入其他错误)。
在N +上,添加了一个标志,即ServiceCompat.STOP_FOREGROUND_DETACH。这将传递给stopForeground,并让您将当前通知保存在通知托盘中。
也不要忘记杀死服务(stopSelf()或其他任何东西)。由于如果用户滑动应用程序,则您的应用程序主过程可能会保留。