12

In Android Nougat and above, push notifications for your app are grouped together automatically after the # 4th.

The problem in Android is that clicking on the bundle does not expand the push notification list, it opens the app.

I have a requirement to identify users that opened the app trough a push notification. For individual notifications, this is easy since I can explore intent extras. The problem with the bundle is that extras are null and intent looks exactly the same as if the user clicked on the launcher icon. I have no way to detect that navigation was done from a push notification :(

Just in case it's not clear: I'm not using push notifications groups explicitly, this is done automatically by Android. I have not set any group key to the notifications.

I'm using Firebase. I only build the push notification using NotificationCompat when the app is on the foreground, this logic is not executed when the app is on the background or closed (OnMessageReceived only runs with the app in foreground).

EDIT

I know that I could change the PN payload for the event OnMessageReceived being executed even in the background or closed. I would like to avoid this since I have found a lot of people complaining about problems with PN not arriving in this case.

http://github.com/firebase/quickstart-android/issues/368

http://github.com/firebase/quickstart-android/issues/219

I want to detect a user tapping on a grouped PN even if the app didn't create it.

Moustafa EL-Saghier
  • 1,721
  • 1
  • 13
  • 43
StackOverflower
  • 5,463
  • 13
  • 58
  • 89
  • AFAIK, tapping on the chevron icon of the bundle should expand/collapse the notification list. – Edric Dec 27 '19 at 17:00
  • @Edric: that's correct... but I cannot force the user to do that. Some users will click on the collapsed push notification and I want to handle that situation. – StackOverflower Dec 27 '19 at 17:02
  • By notifications generated server-side and not client-side, you mean you are using FCM, right? Even in that case, you are still using https://developer.android.com/reference/android/app/Notification.Builder, right? Could you share some code snippet? – Arnab Saha Dec 30 '19 at 11:42
  • @ArnabSaha: I can't because the my code to build the notification would not run when the app is on background or closed – Claudio Redi Dec 30 '19 at 12:16
  • Do you know beforehand when notifications are grouped? – Natig Babayev Dec 30 '19 at 12:52
  • Also, what's your min sdk requirenment – Natig Babayev Dec 30 '19 at 12:56
  • @Natig Babayev: I don't know if the PN will be grouped in advance, that's done by the OS automatically when you have more than 4. – StackOverflower Dec 30 '19 at 13:07
  • @NatigBabayev: my requirement is to execute a specific action when the user opened the app trough a push notification. – StackOverflower Dec 30 '19 at 13:08
  • @StackOverflower in your question you're saying "I only build the push notification using NotificationCompat". What's the way you send push notification to users? Do you have some backend or do you send notifications using firebase console? – Natig Babayev Dec 30 '19 at 21:12
  • @NatigBabayev: yes, the PN is generated on the backend. – StackOverflower Dec 30 '19 at 23:24
  • I updated my answer with second solution @StackOverflower – Natig Babayev Dec 31 '19 at 09:37
  • Hi @StackOverflower, I also need to differentiate between click on notification bundle, individual notification and app launcher icon click. I have read all comments and answers on this post as well as other questions on stackoverflow and many other sites. Have you found a solution or alternative? – Teofilo Israel Vizcaino Rodrig May 21 '20 at 11:57
  • @TeofiloIsraelVizcainoRodrig: I'm afraid that I did not. – StackOverflower Jun 09 '20 at 21:41

2 Answers2

9

Solution 1: If you handle creation of the notifications, you can try following steps:

First of all, every time when you create new notification, you can group them by same key using setGroup(...):

val newMessageNotification1 = NotificationCompat.Builder(applicationContext, ...)
    ...
    .setGroup("group_messages")
    .build()

As you grouped notifications by same id ("group_messages"), now you can create summary notification with different intent:

val notifyIntent = Intent(this, ResultActivity::class.java).apply {
val notifyIntent = Intent(this, ResultActivity::class.java).apply {
    flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
val notifyPendingIntent = PendingIntent.getActivity(
    this, 0, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT
)

val summaryNotification = NotificationCompat.Builder(applicationContext, ...)
    .setSmallIcon(android.R.drawable.ic_btn_speak_now)
    .setContentIntent(notifyPendingIntent)
    .setContentTitle("Grouped notification title")
    .setContentText("Grouped notification text")
    .setGroup("group_messages")
    .setGroupSummary(true)
    .build()

As last step, you can have if check to make sure you have more than 1 notifications with same group, and then notify with group notification:

val notificationManager = applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

val notificationManagerCompat = NotificationManagerCompat.from(applicationContext)
notificationManagerCompat.notify(ID, newMessageNotification1)

val amountOfNotificationsInSameGroup = notificationManager.activeNotifications
                    // Here we filter notifications that are under same group
                    .filter { it.notification.group == "group_messages" }
                    .size

if (amountOfNotificationsInSameGroup >= 2) {
    // if we already have minimum of 2 notifications, we'll group them under summary notification
    notificationManagerCompat.notify(SUMMARY_NOTIFICATION_ID, summaryNotification)
}

You can combine the code in your onMessageReceived method. As you can see, now you can have custom intent to handle grouped notifications. You can read more about grouped notifications here.

Solution 2: If you don't want to handle creation of notifications and still want to know if the notifications are grouped, you can try following solution:

NotificationManager has getActiveNotifications() function which will return notifications that have been posted by the calling app and hasn't been dismissed by the user yet. When you click grouped notifications in Android, notifications won't be dismissed. Therefore, you can check size of active notifications in your launcher activity to detect if the app was launched by clicking to grouped/bundle notifications:

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val notificationManager =
            applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

        if (notificationManager.activeNotifications.size >= 4) {
            // Notifications are grouped
            // Put your logic here

            // Do not forget to clear notifications
            NotificationManagerCompat.from(this).cancelAll()
        }
    }
}

Personally, I'd prefer first solution, but according to the issues you have posted, you can use second option as well but note that you won't be able to differentiate if the app was launched from launcher or by clicking grouped notification.

With second solution there might be following questions:

Q1: How can I differentiate normal notification click from group one in same activity?

- Simply you can define click_action and forward normal notification clicks to different activity. Check the docs.

If you want to replace previous notifications, you can also define same tag in your notification JSON on backend side. In this way, notifications won't be bundled because newer notifications will replace the old one with same tag. Check the docs.

I hope my answer helps.

Natig Babayev
  • 3,128
  • 15
  • 23
  • I only creste the PN when the app is in foreground. Method `OnMessageReceived ` is not executed when the app is closed. I've seen documentation stating that even if I manage to make the app handle PN when the app is closed or in background, that doesn't work very well at all. – StackOverflower Dec 30 '19 at 16:42
  • It does work. Probably you don’t use it properly. Could you put your code and reference it docs that states you can’t create notifications manually? – Natig Babayev Dec 30 '19 at 17:07
  • @StackOverflower you can use data messages in firbebase and in that way you can create your notifications even when app is killed on onMessageReceived method – Natig Babayev Dec 30 '19 at 17:17
  • Some examples: https://github.com/firebase/quickstart-android/issues/368, https://github.com/firebase/quickstart-android/issues/219 – StackOverflower Dec 30 '19 at 17:54
  • Links you have shared doesn’t say that it’s not recommended and it seems like the issue is happening on few devices. How have you implemented notifications in your app? – Natig Babayev Dec 30 '19 at 18:06
  • Not saying that it's not recommended, It's just that lot of people report problems with that. Right now my app only handle PN when it is on foreground, when in background and closed it's not processing incoming PNs. I know that changing the payload I could make my app to process the notification even on background or closed, but wanted to see if I can avoid that... I wouldn't like to fix one problem and add another different one. – StackOverflower Dec 30 '19 at 18:09
  • @StackOverflower Got it. The solution I wrote should be working when app is on foreground at least. If you have further questions, you could update your question? – Natig Babayev Dec 30 '19 at 18:18
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/205128/discussion-between-natig-babayev-and-stackoverflower). – Natig Babayev Dec 31 '19 at 07:21
  • I don't get it... if I open the app clicking the launched icon and I have 6 pending notifications, solutiuon 2 will trigger a false positive. Maybe I'm missing something... what in that logic tells you that user tapped on the PN group? I need detect if the user clicked on the PN, not only if the PN exist. – StackOverflower Jan 02 '20 at 22:14
  • For normal notifications, don’t you have any indicator data as extra data? @StackOverflower – Natig Babayev Jan 02 '20 at 22:24
  • To detect normal notification click, you can add click_action to your notification data. According to docs, it should open specified activity. Check table 2b Android section: https://firebase.google.com/docs/cloud-messaging/http-server-ref – Natig Babayev Jan 02 '20 at 22:32
  • Not normal, grouped PN... I think your solution 2 would not work. I do have information to detect individual PN, the problem is with the group since "extras" is null. Intent when you tap on a group or when you tap on app launcher icon is the same! I didn't find a reliable way to differenciate them – StackOverflower Jan 03 '20 at 03:32
  • Yes, unfortunately, you won't be able to differentiate normal launcher click from notification group click @StackOverflower but you can still do something in both cases. When user launches app either by clicking bundle or launcher, you can show them they have 4 notifications or smth. Depends on work you want to put on usability. Basically, option 2 is sort of "hacky" way but it'd work if you can make it usable. – Natig Babayev Jan 03 '20 at 11:38
0

Answer by @Natig Babayev is well explained. However, in the second part he has not explained the way to distinguish whether the app was opened by clicking on launcher icon or by clicking on Push Notification Bundle (consider the case when there are 5 notifications that are grouped automatically, but the user launches the app by clicking on the app launcher and not on the notification bundle.)

One solution could be to disable automatically grouping notifications. However, this is not possible. Refer this question and this one too

I researched many different options and found that the best solution would be to group notification yourself before the android system does it or limit the number of notifications to max ungrouped notifications by removing older notifications or bundling them out in a separate bundle.

You may also refer to following

  1. https://stackoverflow.com/a/47073575/9640177
  2. https://stackoverflow.com/a/34961716/9640177
Mayank Kumar Chaudhari
  • 16,027
  • 10
  • 55
  • 122