16

I'm sending notifications to users Android devices though the Firebase Notification console and I notice that even if I send 10 different notifications while the user device is offline, once the user goes online she/he will receive all 10.

However in Firebase documentation it is stated that:

FCM allows a maximum of four different collapse keys per device to be used by the app server at any given time. In other words, the FCM connection server can simultaneously store four different collapsible send-to-sync messages per device, each with a different collapse key. If you exceed this number, FCM only keeps four collapse keys, with no guarantees about which ones are kept.

So shouldn't the user receive only 4 notifications? Am I missing something? (I am not extending the FirebaseMessagingService, I leave the notification handling to the SDK)

UPDATE: If you don't specify a collapse key in the Firebase notifications console, it seems that an implicit collapse key is assigned to the notification and that is the package name of the app. I've tested that by checking all key/value pairs of the getIntent().getExtras() key set, once I launch the app by tapping on the notification. And indeed, I am getting a collapse_key key with the value of the package name, even if I haven't specified one.

UPDATE 2: I tried to handle the notifications by extending the FirebaseMessagingService, so that I receive the messages from the notifications console, when the app is in the foreground. I receive the notification message and I manually display a notification to the user. And guess what. Collapse keys work great! I receive a single notification even if I send multiple notifications with the same collapse key. BUT this happens obviously only when the app is in the foreground, because the Firebase SDK doesn't call the onMessageReceived() when the app is in the background, but instead it handles the notification itself. Does that mean that this is a bug of the Firebase SDK? (since the issue happens only when the notification is shown by the SDK)

So question remains, why do I receive all 10 notifications since each notification has the same collapse key? Maybe an FCM bug?

steliosf
  • 3,669
  • 2
  • 31
  • 45
  • 1
    Well... If your notifications don't have collapse keys, then they won't collapse. – Uli Jun 14 '17 at 18:50
  • 1
    Well that's what I thought, but then I read this: https://stackoverflow.com/questions/39655543/does-a-notification-message-count-towards-the-collapse-key-limit which states that the notifications have an implicit collapse key. – steliosf Jun 15 '17 at 00:17
  • Hi MScott. Just curious, how long is the device offline for? – AL. Jun 15 '17 at 09:15
  • 1
    For testing purposes I'm just turning off the Wi-Fi for 1 or 2 minutes. I still haven't figured out, if I don't specify a collapse key, is there an implicit one? Or no collapse key, means all notifications are delivered without collapsing? – steliosf Jun 15 '17 at 14:34
  • Please check the update on my question. – steliosf Jun 15 '17 at 15:38
  • Could you try testing it in different intervals (10mins, 30mins, 1hr) and see if it's the same behavior? If it is, then there is a possibility that something is wrong with the collapse keys, if not, then my guess would be that there is a specific time frame for the collapse key behavior (disgard messages if more than four) to take effect. – AL. Jun 19 '17 at 05:01
  • @MScott can you share the push notification format you are using and are these issues on different android OS - N,M,L ? – Ashutosh Barthwal Jun 20 '17 at 05:07
  • One important consideration here is that if you are using more than 4 collapse keys, then the behavior is non-deterministic. That's the only documented behavior that seems similar to what you've described, and could account for messages not being collapsed. Note also that [only Notification type messages are collapsed](https://firebase.google.com/docs/cloud-messaging/concept-options#which_should_i_use). If you are using a different message type, they will not be collapsed. – Kato Jun 20 '17 at 19:39
  • 1
    Thanks for your comments, @AL I tested an 1 hour interval but still the same. -Ashutosh I'm sending the notifications through the Firebase console (Notifications composer) without adding any other keys other than the default ones. -Kato About a week ago, I did some tests and I had definitely used more than 4 collapse keys, but since then I do not specify one. Could that have broken the notifications? – steliosf Jun 20 '17 at 23:10
  • 1
    Hmm. I might try it on my end and see if I could replicate it. For the meantime, could you also try sending the `notification` messages from your App Server or just use [Postman or cURL](https://stackoverflow.com/documentation/firebase-cloud-messaging/8242/firebase-cloud-messaging#t=201706202315414348406) and see of that makes a difference? – AL. Jun 20 '17 at 23:16
  • I'm actually using a Firebase cloud function as well which sends notifications to users' devices, without specifying any collapse key. It's similar to the Firebase follower notification sample: https://github.com/firebase/functions-samples/blob/master/fcm-notifications/functions/index.js And again, same exact behavior. I'm starting to think that using more than 4 collapse keys in the past might have broken the notifications. – steliosf Jun 20 '17 at 23:23
  • Post your cloud function code that shows the call to `sendToDevice()` along with the payload and options objects. I tried to replicate your results using Firebase Console and couldn't get collapse to occur at all. Had much better results using ARC (Advanced Rest Client). – Bob Snyder Jun 23 '17 at 00:15
  • I'm pretty sure that it's not a problem of the cloud function, because it's the exact same behavior with the Firebase notification composer in Firebase console. So at least the notification composer should work with the collapse keys. By the way, check the 2nd update on my question, I've just tested what happens if I extend the `FirebaseMessagingService` – steliosf Jun 23 '17 at 13:34
  • @Kato if you have a minute, check the 2nd update on my question. TL;DR: When I handle the notification messages in the foreground collapse keys work. When Firebase handles the notification messages in the background collapse keys do not work. – steliosf Jun 23 '17 at 13:44

1 Answers1

10

After reading the post and comments, I'm not completely clear on everything that has been tried, which efforts were successful and which failed. I'll cover a number if items and hope something is helpful.

Your post indicates that for some tests, you specified a collapse key when you composed the message in Firebase console. That is not possible. If you opened Advanced options and entered a key/value pair under Custom data, that will not work. Those values are stored in the message under the data key, not at the top level of the message where collapse_key must appear. Also, Table 1 in the documentation includes a warning that data keys should not be any of the reserved words in the table, specifically citing collapse_key:

The key should not be a reserved word ("from" or any word starting with "google" or "gcm"). Do not use any of the words defined in this table (such as collapse_key).

As noted in the comments to your post, the console automatically assigns a collapse key that is the package name, so user entry of a collapse key is not needed.

That said, my experiences with the console match yours. I create messages by entering only Message text and the device token. I see no collapse processing; each message is received by the device. Based on my experience with the tests described below, this seems to be a problem with the console and not with collapse processing in general. This is odd, because if I send the messages when the app is in the foreground, and onMessageReceived() is invoked, I have debug logging that outputs the collapse key in the message using getCollapseKey(). That output confirms that the key is present and is my app package name.

You indicate that you did some tests sending notifications from a cloud function. I did my own testing with this cloud function and observed the expected message collapse:

exports.test = functions.database.ref('/test').onWrite(event => {
  const token = 'dK1FjGbNr6k:APA91bH7Vz3x...icGO56sJ7rAqOXRI';

  console.log('Sending notification...');

  const payload = {
    notification: {
      title: 'Message',
      body: 'Just one please!'
    }
  };

  const options = {
    collapseKey: 'green'
  };

  return admin.messaging().sendToDevice(token, payload, options).then(response => {
    console.log('Done');
  });
});

I also sent this message using browser app Advanced Rest Client, and also saw correct message collapsing:

{
  "to": "dK1FjGbNr6k:APA91bH7Vz3x...O56sJ7rAqOXRI",
  "collapse_key": "green",
  "notification": {
    "title": "Message",
    "body": "Just one please!"
  }
}

I'll also share that Firebase emits an analytics log message when a notification message is received. This is useful for testing, when you want to get a count of messages received:

D/FA: Logging event (FE): notification_receive(_nr), Bundle[{firebase_event_origin(_o)=fcm, message_device_time(_ndt)=0, message_time(_nmt)=1498227476, message_id(_nmid)=6447126672094369335}]
Bob Snyder
  • 37,759
  • 6
  • 111
  • 158
  • Hi Bob, you are absolutely right. I was specifying the collapse_key in the custom data which now that you're saying it, it doesn't make sense. So like you say, you cannot specify a collapse_key at the notifications console. But since the notifications do not collapse, this is definitely a bug of Firebase. However, my guess is that it's a bug of the Firebase Android SDK (not sure if you're using Android or iOS) and not a problem of the Firebase console. I'll continue in the next comment: – steliosf Jun 23 '17 at 15:26
  • @MScott: All of my tests used an Android device. I don't see how the problem could be in the client-side processing given that collapse works when messages are sent from a cloud function. – Bob Snyder Jun 23 '17 at 15:32
  • 1
    At first I was using the Firebase console as well as a Cloud Function to send notifications. But I wasn't extending the `FirebaseMessagingService`. I let the SDK to handle the notifications. Well, the notifications were not collapsing, regardless if they were coming from the console or the cloud function. But when I implemented `MyFirebaseMessagingService`, collapse keys now work both from the console and my cloud function, but only when the app is in the foreground, because when the app is in the background notification messages do not invoke `onMessageReceived()`. – steliosf Jun 23 '17 at 15:36
  • You can test that, by sending 2 notification messages from the console while your device's Wi-Fi is turned off. Then open your app and turn on the Wi-Fi while the app is in the foreground. The collapse keys should now work and you should receive only 1 notification (assuming that you're handling the notifications in your Firebase service). But that won't happen if the app is in the background. So, when we do the handling by extending the `FirebaseMessagingService`, collapse keys work, but when Firebase does the handling, they don't. – steliosf Jun 23 '17 at 15:38
  • @MScott: I don't see that behavior. Add some log output to `onMessageReceived()` to get a clear indication of the number of messages received. If you are using the same ID when your generate the notifications, your are unintentionally collapsing them. The `NotifcationManager` will treat multiple calls with the same ID as updates to the existing notification instead of creating another one. – Bob Snyder Jun 23 '17 at 17:28
  • Can you please help me with [this](https://stackoverflow.com/questions/49085079/how-to-collapse-multiple-notifications-into-a-single-one-using-firebase/49089811)? – Joan P. Mar 04 '18 at 12:07
  • @BobSnyder This is driving me crazy, i still get collapsing notification even after i changed the Notificationmanager ID! What is wrong! – stefanosn Oct 22 '20 at 15:06