android developer android developer - 1 month ago 6
Android Question

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

Background



Ever since heads-up notifications appeared on Android, some people liked it for its quick handling, yet some hated it for showing on top of apps (especially games).

In order to show heads-up notifications, developers can use something like that:

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());


Because of this, some apps came up with the idea to show ticker-text notifications that replace them somehow, just as it used to be before heads-up notifications:

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

There are various scenarios where this could be useful. It could be, for example, useful in case of games, where full screen is used. That's because if the user is about to press the top area, and the heads-up notifications are shown, we would like to avoid accidental click on this notification.

The problem



Not only I can't find a way of how people did it, but it seems it doesn't work anymore on new versions of Android (tested on Android 7).

The only app I've found that blocks notification is this:
https://play.google.com/store/apps/details?id=com.aboutmycode.NotificationsOff&hl=en

yet it doesn't convert the heads-up notifications to "normal" ones. Instead, it just blocks them all. Plus it requires root, and seems to just change the settings of the notifications to "blocked" .

The question



Is it possible to temporarily block the heads up notifications (and yet convert them to ones without heads-up notifications ) ? If so, how?

Which restrictions does it have? Can it work without root? If it's possible with root, how? How does the "NotificationsOff" work?

Maybe this ability was possible before, but now it is not?

Answer

On Android 18+ there is a NotificationListenerService. This service gets notified when new notifications are shown. Then, I understand there are three ways to act:

  • Intercepting the notifications so they don't get displayed (not completely sure this can be done) Checked: if the NotificationListenerService doesn't call super.xxx when receiving a notification, the notification is also showed. So this method seems to not work.
  • Clearing notifications as they get posted. For this, you can use NotificationManager to either clear a given notification or clearAllNotifications Checked: it partially works to clear the notifications, but you still see the notification showing up and then it's not in the notification area (it's weird effect).
  • In API 21+ Lollipop it seems that you can override NotificationListenerService#getCurrentInterruptionFilter(). This method could return NotificationListenerService#INTERRUPTION_FILTER_NONE (or any other of the constants), (haven't tested, should be verified). Checked: NotificationListenerService#getCurrentInterruptionFilter() is final, so it cannot be overridden.
  • In API 23+ you can use either NotificationManager#setInterruptionFilter() or NotificationManager.setNotificationPolicy() to control which notifications are shown to the user. Permissions are required for those APIs. Notice that this methods seem to be a convenience to be able to access the functionality, but skip implementing a complete NotificationListenerService. That's the only option that can work in a satisfying way

About NotificationListenerService, you can see the following samples in GitHub kpbird/NotificationListenerService-Example and in this post.

About NotificationManager, see additional information in this post in StackOverflow (specially interesting the highlighted comment) and in this post.

Comments