某些应用程序如何 block/replace 提醒通知?

How do some apps block/replace heads-up notifications?

背景

自从 Android 上出现提示通知后,有人喜欢它的快速处理,但也有人讨厌它显示在应用程序(尤其是游戏)顶部。

为了显示提醒通知,开发人员可以使用类似的东西:

    final NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
            .setContentTitle("aa").setContentText("bb").setTicker("cc")
            .setColor(0xffff0000).setSmallIcon(R.mipmap.ic_launcher)
            .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
            .setPriority(Notification.PRIORITY_HIGH);
    if (Build.VERSION.SDK_INT >= 21)
        builder.setVibrate(new long[0]);
    NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    notificationManager.notify(1, builder.build());

正因为如此,一些应用程序想出了显示代码文本通知的想法,以某种方式取代它们,就像在单挑通知之前一样:

https://play.google.com/store/apps/details?id=com.jamworks.noheadsup&hl=en

在各种情况下这可能会有用。例如,它可能在使用全屏的游戏中很有用。那是因为如果用户正要按下顶部区域,并且显示抬头通知,我们希望避免意外点击此通知。

问题

不仅我找不到人们是如何做到的,而且它似乎在 Android 的新版本上不再起作用(在 Android 7 上测试过)。

我发现唯一阻止通知的应用程序是: https://play.google.com/store/apps/details?id=com.aboutmycode.NotificationsOff&hl=en

但它不会将单挑通知转换为 "normal" 通知。相反,它只是阻止了它们。另外它需要 root,并且似乎只是将通知设置更改为 "blocked" 。

问题

是否可以暂时阻止单挑通知(并将它们转换为没有单挑通知的通知)?如果是这样,如何?

它有哪些限制?它可以在没有root的情况下工作吗?如果可以用 root,怎么办? "NotificationsOff" 是如何工作的?

也许这个能力以前是可以的,现在不行了?

在 Android 18+ 上有一个 NotificationListenerService。当显示新通知时,此服务会收到通知。然后,我明白了三种操作方式:

  • 拦截通知以使其不显示(不完全确定这是否可以完成) 已检查:如果 NotificationListenerService 不调用 super.xxx 收到通知时,也会显示通知。所以这个方法好像不行。
  • 在发布通知时清除通知。为此,您可以使用 NotificationManager 来清除给定的通知或 clearAllNotifications 选中:它部分地用于清除通知,但您仍然看到通知显示,然后它不在通知区域(这是奇怪的效果)。
  • 在API 21+ Lollipop 中似乎可以覆盖NotificationListenerService#getCurrentInterruptionFilter()。此方法可以 return NotificationListenerService#INTERRUPTION_FILTER_NONE (或任何其他常量),(尚未测试,应验证)。 已检查: NotificationListenerService#getCurrentInterruptionFilter() 是最终的,因此它无法覆盖。
  • 在 API 23+ 中,对于那些 API,您可以同时使用 NotificationManager#setNotificationPolicy() and NotificationManager#setInterruptionFilter() (in that specific order) to control which notifications are shown to the user. Permissions are required请注意,此方法似乎可以方便地访问功能,但请跳过实现完整的 NotificationListenerService这是唯一可以令人满意的选择

关于NotificationListenerService,您可以在GitHub kpbird/NotificationListenerService-Example and in this post.

中看到以下示例

关于 NotificationManager,请参阅 this post in Whosebug (specially interesting the highlighted comment) and in this post 中的其他信息。

示例、测试和附加说明

我上传了以下 repository to GitHub 以及基于 kpbird 的示例,以测试所有假设并提供最终结论。

请注意,必须遵循 following steps to enable the permission 才能使应用程序能够访问通知,以便应用程序正常运行。此答案还提供了一种在正确部分打开系统设置的方法。

此外,为了完整起见,following answer 提供了一种检查权限是否已被授予的方法。

补充说明:显然第一个版本的 Marshmallow 有一个错误 NotificationManager#setInterruptionFilter() 不起作用。参见 here and