'Firebase Cloud Messaging: Unable to correlate SendResponse to subscriber token

I'm using the Java SDK for Firebase Cloud Messaging and want to send out a batch (or multicast) of messages. In case I send 100 messages I get 100 SendResponse's returned. But I don't see how I can relate those to the tokens/subscribers. There is a messageId in the successful ones but I can't use that to relate it to the tokens.

What am I missing? Or is this a limitation of the API/SDK?



Solution 1:[1]

You will have to manually manage a mapping of device tokens to users. Device tokens just identify a device, not a user. And a user could be using multiple devices, so it is actually a one to many mapping. But there's no avoiding keeping track of this mapping on your own.

Solution 2:[2]

According to the server environments docs on sending messages to multiple devices, the order of the list of SendResponses corresponds to the order of the input tokens:

The return value is a BatchResponse whose responses list corresponds to the order of the input tokens. This is useful when you want to check which tokens resulted in errors.

You can use this fact to determine the token -> SendResponse mapping, as shown by the example code on that page:

// These registration tokens come from the client FCM SDKs.
List<String> registrationTokens = Arrays.asList(
    "YOUR_REGISTRATION_TOKEN_1",
    // ...
    "YOUR_REGISTRATION_TOKEN_n"
);

MulticastMessage message = MulticastMessage.builder()
    .putData("score", "850")
    .putData("time", "2:45")
    .addAllTokens(registrationTokens)
    .build();
BatchResponse response = FirebaseMessaging.getInstance().sendMulticast(message);
if (response.getFailureCount() > 0) {
  List<SendResponse> responses = response.getResponses();
  List<String> failedTokens = new ArrayList<>();
  for (int i = 0; i < responses.size(); i++) {
    if (!responses.get(i).isSuccessful()) {
      // The order of responses corresponds to the order of the registration tokens.
      failedTokens.add(registrationTokens.get(i));
    }
  }

  System.out.println("List of tokens that caused failures: " + failedTokens);
}

As Doug mentioned in his answer, associating the input tokens to users is something you'll need to manage yourself. In a relational database you'd probably have a FCM_Token table that includes a foreign key to a User table.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Doug Stevenson
Solution 2 mgalgs