如何正确处理 startForeground 两个通知的问题

9
我有一个IntentService用于上传文件。一切工作正常,但是我对如何处理通知有点困惑。当我启动通知时,我使用startForeground(),因为文件可能相当大,除非绝对必要,否则不希望上传被杀死。当我使用startForeground()时,它在通知区域显示两个通知(一个在进行中,另一个在通知下):

Example:

我已经阅读了许多不同的Stack Overflow帖子和网页文章,但是没有一个回答了我所提出的问题... 希望我没有错过谈论这个问题的文章。
据我所知,上图中的持续通知(没有进度条的那个)是因为它在前台运行而被放置在那里(服务文档)。如果你问我,这很好,我也理解为什么。然而,我不需要显示两个通知,我相信大多数人也不想在通知区域里看到两个通知。我想知道如何正确处理通知,以便只显示一个并且不会混乱通知区域。
我唯一能够解决这个问题的方法是将startForeground (int id, Notification notification)中的整数ID(在我的代码中为ONGOING_NOTIFICATION_ID)设置为零。然而,我引用的上面的文档说: 注意:您给startForeground()的整数ID不能为0 将它设置为0将会禁用持续的通知,进度条只会显示在常规通知中。我认为我可以通过将 `setOngoing(true)` 设置为正在上传文件直到上传完成时将 `setOngoing(false)` 设置为可解除,以此来“修复”这个问题。我不确定将整数 ID 设置为0需要多么“小心谨慎”。对我来说,它似乎是解决我的问题的一种懒惰方式,但我不知道将其设置为0是否会有其他后果。而且,这仅适用于处理一个通知的情况。如果我有多个不同的通知,则需要为每个通知使用不同的ID,这样做就不起作用了。更新: 看起来 将ID设置为0在Android 4.3中行不通,所以现在我又回到了原点。

如何更好地避免同时显示这两个通知?

更新/解决方案:嗯,休息一段时间后回来,根据@dsandler的建议仔细检查我所做的事情帮助我找出了我做错了什么。当我进行进度更新时,我没有设置正确的ID,这就是为什么它创建了两个通知而且一个没有得到更新的原因。对于所有通知使用相同的ID(ONGOING_NOTIFICATION_ID)解决了我的问题。请参见以下代码以获取我之前未包括的其他部分和我犯的错误。

来自UploadFile.java的相关代码:

public class UploadFile extends IntentService {

    private static final int ONGOING_NOTIFICATION_ID = 1;

    @Override
    protected void onHandleIntent(Intent intent) {
        mNotifyManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        mBuilder = new NotificationCompat.Builder(this);
        mBuilder.setContentTitle(getText(R.string.upload))
            .setContentText("0% " + getText(R.string.upload_in_progress))
            .setSmallIcon(android.R.drawable.stat_sys_upload);

        startForeground(ONGOING_NOTIFICATION_ID, mBuilder.build());


....

    if (progress > 0){
        percent = (Long.valueOf(progress) * 100) / totalSize;
        mBuilder.setProgress(100, percent.intValue(), false);
        mBuilder.setContentText(percent.intValue() + "% " + getText(R.string.upload_in_progress));
        mNotifyManager.notify(ONGOING_NOTIFICATION_ID, mBuilder.build()); // <-- My problem was that I had set the ID here to 0 and did not make it the same as the ID I set above
    }                       

....

}
2个回答

3

首先,根据您的描述,您可能可以使用普通服务,认识到除非设备上的情况变得严重并且您的服务已经运行了很长时间,否则不会有内存不足杀手来打扰。

话虽如此,如果您必须使服务前台化,则典型策略是使用您将服务置于前台状态时使用的通知来显示进度。使用 NotificationManager.notify 您可以发布任意数量的更新到该通知中,包括通过 Notification.Builder.setProgress 调整进度条等。

通过这种方式,您只向用户显示一个通知,而且它是 startForeground 所需的通知。


谢谢你的回答。我回去仔细检查了一下我的操作(就是按照你的建议做的),发现在发布进度时我没有使用正确的通知 ID。现在它已经完美地运行了! - Jason
我有一个关于通知的问题:如果您希望使用Android的图标(就像您为“setSmallIcon”所做的那样),则应该使用哪个图标来进行“setLargeIcon”? - android developer
为什么需要使用 NotificationManager.notifystartForegroundService()已经显示了通知。 - IgorGanapolsky

0

当您想要更新通过startForeground()设置的通知时,只需构建一个新的通知,然后使用NotificationManager进行通知即可。

关键点是使用相同的通知ID。

我没有测试重复调用startForeground()以更新通知的情况,但我认为使用NotificationManager.notify会更好。

更新通知不会将服务从前台状态中移除(只能通过调用stopForground来完成);

示例:

private static final int notif_id=1;

@Override
public void onCreate (){
    this.startForeground();
}

private void startForeground() {
        startForeground(notif_id, getMyActivityNotification(""));
}

private Notification getMyActivityNotification(String text){
        // The PendingIntent to launch our activity if the user selects
        // this notification
        CharSequence title = getText(R.string.title_activity);
        PendingIntent contentIntent = PendingIntent.getActivity(this,
                0, new Intent(this, MyActivity.class), 0);

        return new Notification.Builder(this)
                .setContentTitle(title)
                .setContentText(text)
                .setSmallIcon(R.drawable.ic_launcher_b3)
                .setContentIntent(contentIntent).getNotification();     
}
/**
this is the method that can be called to update the Notification
*/
private void updateNotification() {

                String text = "Some text that will update the notification";

                Notification notification = getMyActivityNotification(text);

                NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
                mNotificationManager.notify(notif_id, notification);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接