How do you send a Firebase Notification to all devices via CURL?

AndroidFirebaseFirebase Cloud-MessagingFirebase Notifications

Android Problem Overview


I'm attempting to send out a notification to all app users (on Android), essentially duplicating what happens when a notification is sent via the Firebase admin console. Here is the CURL command I begin with:

curl --insecure --header "Authorization: key=AIzaSyBidmyauthkeyisfineL-6NcJxj-1JUvEM" --header "Content-Type:application/json" -d "{"notification":{"title":"note-Title","body":"note-Body"}}" https://fcm.googleapis.com/fcm/send

Here's that JSON parsed out to be easier on your eyes:

{
"notification":{
    "title":"note-Title",
    "body":"note-Body"
    }
}

The response that comes back is just two characters:

to

That's it, the word "to". (Headers report a 400) I suspect this has to do with not having a "to" in my JSON. What would one even put for a "to"? I have no topics defined, and the devices have not registered themselves for anything. Yet, they are still able to receive notifications from the Firebase admin panel.

I'm want to attempt a "data only" JSON package due to the amazing limitation of Firebase notification processing whereby if your app is in the foreground, the notification gets processed by YOUR handler, but if your app is in the background, it gets processed INTERNALLY by the Firebase service and never passed to your notification handler. APPARENTLY this can be worked around if you submit your notification request via the API, but ONLY if you do it with data-only. (Which then breaks the ability to handle iOS and Android with the same message.) Replacing "notification" with "data" in any of my JSON has no effect.

Ok, then I attempted the solution here: https://stackoverflow.com/questions/37576705/firebase-java-server-to-send-push-notification-to-all-devices which seems to me to say "Ok, even though notifications to everyone is possible via the Admin console... it's not really possible via the API." The workaround is to have each client subscribe to a topic, and then push out the notification to that topic. So first the code in onCreate:

FirebaseMessaging.getInstance().subscribeToTopic("allDevices");

then the new JSON I send:

{
"notification":{
    "title":"note-Title",
    "body":"note-Body"
    },
"to":"allDevices"
}

So now I'm getting a real response from the server at least. JSON response:

{
"multicast_id":463numbersnumbers42000,
"success":0,
"failure":1,
"canonical_ids":0,
"results":
    [
    {
    "error":"InvalidRegistration"
    }
    ]
}

And that comes with a HTTP code 200. Ok... according to https://firebase.google.com/docs/cloud-messaging/http-server-ref a 200 code with "InvalidRegistration" means a problem with the registration token. Maybe? Because that part of the documentation is for the messaging server. Is the notification server the same? Unclear. I see elsewhere that the topic might take hours before it's active. It seems like that would make it useless for creating new chat rooms, so that seems off as well.

I was pretty excited when I could code up an app from scratch that got notifications in just a few hours when I had never used Firebase before. It seems like it has a long way to go before it reaches the level of, say, the Stripe.com documentation.

Bottom line: does anyone know what JSON to supply to send a message out to all devices running the app to mirror the Admin console functionality?

Android Solutions


Solution 1 - Android

Firebase Notifications doesn't have an API to send messages. Luckily it is built on top of Firebase Cloud Messaging, which has precisely such an API.

With Firebase Notifications and Cloud Messaging, you can send so-called downstream messages to devices in three ways:

  1. to specific devices, if you know their device IDs
  2. to groups of devices, if you know the registration IDs of the groups
  3. to topics, which are just keys that devices can subscribe to

You'll note that there is no way to send to all devices explicitly. You can build such functionality with each of these though, for example: by subscribing the app to a topic when it starts (e.g. /topics/all) or by keeping a list of all device IDs, and then sending the message to all of those.

For sending to a topic you have a syntax error in your command. Topics are identified by starting with /topics/. Since you don't have that in your code, the server interprets allDevices as a device id. Since it is an invalid format for a device registration token, it raises an error.

From the documentation on sending messages to topics:

https://fcm.googleapis.com/fcm/send
Content-Type:application/json
Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA

{
  "to": "/topics/foo-bar",
  "data": {
    "message": "This is a Firebase Cloud Messaging Topic Message!",
   }
}

Solution 2 - Android

The most easiest way I came up with to send the push notification to all the devices is to subscribe them to a topic "all" and then send notification to this topic. Copy this in your main activity

FirebaseMessaging.getInstance().subscribeToTopic("all");

Now send the request as

{
   "to":"/topics/all",
   "data":
   {
      "title":"Your title",
      "message":"Your message"
      "image-url":"your_image_url"
   }
}

This might be inefficient or non-standard way, but as I mentioned above it's the easiest. Please do post if you have any better way to send a push notification to all the devices.

You can follow this tutorial if you're new to sending push notifications using Firebase Cloud Messaging [Tutorial - Push Notifications using FCM][1]


To send a message to a combination of topics, specify a condition, which is a boolean expression that specifies the target topics. For example, the following condition will send messages to devices that are subscribed to TopicA and either TopicB or TopicC:

{
   "data":
   {
      "title": "Your title",
      "message": "Your message"
      "image-url": "your_image_url"
   },
   "condition": "'TopicA' in topics && ('TopicB' in topics || 'TopicC' in topics)"
}

Read more about conditions and topics here on [FCM documentation][2]

[1]: https://www.pluralsight.com/guides/push-notifications-with-firebase-cloud-messaging "Tutorial - Push Notifications using FCM" [2]: https://firebase.google.com/docs/cloud-messaging/send-message#send_messages_to_topics_2

Solution 3 - Android

EDIT: It appears that this method is not supported anymore (thx to @FernandoZamperin). Please take a look at the other answers!

Instead of subscribing to a topic you could instead make use of the condition key and send messages to instances, that are not in a group. Your data might look something like this:

{
    "data": {
        "foo": "bar"
    },
    "condition": "!('anytopicyoudontwanttouse' in topics)"
}

See https://firebase.google.com/docs/cloud-messaging/send-message#send_messages_to_topics_2

Solution 4 - Android

One way to do that is to make all your users' devices subscribe to a topic. That way when you target a message to a specific topic, all devices will get it. I think this how the Notifications section in the Firebase console does it.

Solution 5 - Android

I was looking solution for my Ionic Cordova app push notification.

Thanks to Syed Rafay's answer.

in app.component.ts

const options: PushOptions = {
  android: {
    topics: ['all']
  },

in Server file

"to" => "/topics/all",

Solution 6 - Android

Just make all users who log in subscribe to a specific topic, and then send a notification to that topic.

Solution 7 - Android

Check your topic list on firebase console.

  1. Go to firebase console

  2. Click Grow from side menu

  3. Click Cloud Messaging

  4. Click Send your first message

  5. In the notification section, type something for Notification title and Notification text

  6. Click Next

  7. In target section click Topic

  8. Click on Message topic textbox, then you can see your topics (I didn't created topic called android or ios, but I can see those two topics.

  9. When you send push notification add this as your condition.

    "condition"=> "'all' in topics || 'android' in topics || 'ios' in topics",

Full body

array(
    "notification"=>array(
        "title"=>"Test",
        "body"=>"Test Body",
    ),
    "condition"=> "'all' in topics || 'android' in topics || 'ios' in topics",
);

If you have more topics you can add those with || (or) condition, Then all users will get your notification. Tested and worked for me.

Solution 8 - Android

For anyone wondering how to do it in cordova hybrid app:

  • go to index.js -> inside the function onDeviceReady() write :

      subscribe();
    

(It's important to write it at the top of the function!)

  • then, in the same file (index.js) find :

    function subscribe(){

     FirebasePlugin.subscribe("write_here_your_topic", function(){
      
     },function(error){
     
         logError("Failed to subscribe to topic", error);
     });
     }
    

and write your own topic here -> "write_here_your_topic"

Solution 9 - Android

It is a PHP Admin-SDK example to subscribe an user to a Topic and to send messages to a device by device token or to a Topic. Note that the Topic is created automatically when you subscribe an user.

$testTokens = ['device token 1', 'device token 2', ....]

// CREDENTIALS, YOU HAVE TO DOWNLOAD IT FROM FIREBASE CONSOLE.
$factory = (new Factory())->withServiceAccount('credentials.json');

$messaging = $factory->createMessaging();

// Subscribe a token or a group of tokens to a topic (this topic is created automatically if not exists)
// YOU CAN DO THIS IN THE MOBILE APP BUT IS BETTER DO IT IN THE API.
$result = $messaging->subscribeToTopic('all', $testTokens); // 'all' is the topic name

// Send a message to a specific Topic (Channel) 
$message = CloudMessage::withTarget('topic', 'all')
    ->withNotification(Notification::create('Global message Title', 'Global message Body'))
    ->withData(['key' => 'value']); // optional
$messaging->send($message);

// Send a message to a token or a grup of tokens (ONLY!!!)
 foreach($testTokens as $i=>$token){
     $message = CloudMessage::withTarget('token', $token)
         ->withNotification(Notification::create('This is the message Title', 'This is the message Body'))
         ->withData(['custom_index' => $i]); // optional
     $messaging->send($message);

You can check this repo for more details: firebase-php-admin-sdk

Solution 10 - Android

Your can send notification to all devices using "/topics/all"

https://fcm.googleapis.com/fcm/send
Content-Type:application/json
Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA

{
  "to": "/topics/all",
  "notification":{ "title":"Notification title", "body":"Notification body", "sound":"default", "click_action":"FCM_PLUGIN_ACTIVITY", "icon":"fcm_push_icon" },
  "data": {
    "message": "This is a Firebase Cloud Messaging Topic Message!",
   }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAnders8View Question on Stackoverflow
Solution 1 - AndroidFrank van PuffelenView Answer on Stackoverflow
Solution 2 - AndroidSyed RafayView Answer on Stackoverflow
Solution 3 - AndroidWalamanaView Answer on Stackoverflow
Solution 4 - AndroidAbdalrahman ShatouView Answer on Stackoverflow
Solution 5 - AndroidKeval ShahView Answer on Stackoverflow
Solution 6 - AndroidAshwin Gopi KrishnaView Answer on Stackoverflow
Solution 7 - AndroidmintView Answer on Stackoverflow
Solution 8 - AndroidNPLSView Answer on Stackoverflow
Solution 9 - AndroidmanuelpgsView Answer on Stackoverflow
Solution 10 - AndroidSiva KaruppiahView Answer on Stackoverflow