当一个安卓应用程序(活动或服务)被杀死时,如何移除所有通知?

14

我有一个应用程序,其中包含一个活动和一个在后台运行的意图服务。

还有一个通知,显示后台进程的进度条(正在从服务器下载大量文件)。

该活动显示下载进度(在这些资源被下载之前,用户无法有意义地使用该应用程序)。当关闭此活动时,将显示带有进度条的通知。

问题是:当通过“任务管理器”(可通过Android 4.0上的右键单击访问,带有两个矩形的那个)杀死应用程序时,通知仍然存在。但实际上它是僵尸,因为用于更新它的服务已经停止了。

换句话说:当我的应用程序被杀死时,如何删除所有通知或一个(或多个)通知?


你可以检查服务中是否调用了 onDestroy - njzk2
2
我尝试过了,但不幸的是当应用程序被杀死时onDestroy方法并没有被调用。 - treesAreEverywhere
我假设通知的意图是主活动? - njzk2
是的,你可以这样假设。当通知被点击时,活动会启动。 - treesAreEverywhere
那么我会说通知仍然相对相关(除了它给出了错误的概念,即下载仍在运行)。 - njzk2
是的,问题在于有一个进度条,但是不再有进展了。而且由于我无法删除或更新此通知,这会给用户留下错误的印象。 - treesAreEverywhere
6个回答

27

@See public void onTaskRemoved(Intent rootIntent)。 如果服务正在运行且用户已删除来自服务应用程序的任务,则会调用此方法。如果您设置了ServiceInfo.FLAG_STOP_WITH_TASK标志,则不会收到此回调;相反,服务将被简单地停止。

您可以使用cancelAll()删除应用程序创建的所有通知:

NotificationManager nManager = ((NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE));
nManager.cancelAll();

根据API文档,这将会:

取消所有之前显示的通知。

以和cancel(int id)相同的方式:

取消先前显示的通知。如果它是短暂的,视图将被隐藏。如果它是持久的,它将从状态栏中删除。


1
问题不在于如何删除通知,而在于如何检测应用程序是否被系统杀死(以便可以删除通知)。 - Angel Koh
由于后台服务的限制,此功能在API级别>=26上将不再起作用 - https://developer.android.com/about/versions/oreo/background#services。这个解决方案已经不再可行,系统会在一段时间后停止此服务(因此可能会错过onTaskRemoved事件)。 - Vadim Kotov
对于一些设备,除非用户启用设置(例如“设置”>“权限”>“自启动”),否则将永远不会调用onTaskRemoved方法。请注意小心处理此方法内的任何用例。有关更多详细信息,请参见https://dev59.com/5lkR5IYBdhLWcg3w6RID。 - Manju

4

看起来当用户通过在“任务管理器”中滑动应用程序关闭应用程序任务时,Service的onTaskRemoved方法确实会被调用。我可以在这里删除通知。


不适用于API级别>= 26,请参见https://dev59.com/CFYN5IYBdhLWcg3wqpmH#47110577 - Vadim Kotov

0

您可以在服务类的回调方法中编写代码以删除通知。如果条件成立,则清除其余内容。

 override fun onTaskRemoved(rootIntent: Intent?) {
    super.onTaskRemoved(rootIntent)
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        stopForeground(true)
    }else{
        val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
        notificationManager .cancelAll() 
    }
}

目前你的回答不够清晰,请编辑并添加更多细节,以帮助其他人理解它如何回答问题。你可以在帮助中心找到有关如何编写好答案的更多信息。 - Community

0

0

在您的通知构建器中使用setTimeoutAfter,然后使用递归调用启动一个协程来刷新通知,在它自己取消之前。

这样,如果您的服务被杀死(不会通过onDestroy或接收任何其他回调来触发通知的取消),通知就会自动超时。而且,只有当应用程序处于空闲状态并被操作系统杀死后,已启动+绑定的服务才会停止。

使用前台服务也意味着您的正常应用程序生命周期不会受到阻碍。这很棘手,但可行。

请参见https://github.com/05nelsonm/TorOnionProxyLibrary-Android/blob/master/topl-service/src/main/java/io/matthewnelson/topl_service/notification/ServiceNotification.kt中的buildNotificationnotifylaunchRefreshNotificationJob方法。


-4

你试过onStop了吗?这对我很有效。我在onStop中调用了cancelAll()。它可以在从任务管理器中移除应用程序时关闭所有通知。

注意:但是,当您的应用程序进入后台时,它也会删除所有通知。在这种情况下,您可以使用后台进程重新调用这些通知。

@Override public void onStop (){
    super.onStop();
    cancelAllNotification(getApplicationContext());
}

public static void cancelAllNotification(Context ctx) {
    String ns = Context.NOTIFICATION_SERVICE;
    NotificationManager nMgr = (NotificationManager) ctx.getSystemService(ns);
    nMgr.cancelAll();
}

不行,因为应用程序实际上已经停止了。通知在应用程序在后台运行时可见。 - treesAreEverywhere

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