1

I received an email from Google where starting June 20, 2024 the legacy Firebase Cloud Messaging (FCM) APIs will be discontinued.

I currently have a server where a php Cron send Android push notifications, every minutes, using legacy api including multiple tokens in registration_ids field and I can send message to multiple clients with one curl post request.

There is no chance, at the moment, to use multicasting messages with new Api, so if I need to send in 1 minute a message to 300 or 400 Android clients I need to call 300/400 times google server to post data? Did I get it right?

Whate are the best solution? thanks

Cristian
  • 329
  • 2
  • 6
  • 14
  • Check this: https://stackoverflow.com/questions/76529438/send-push-fcm-to-multiple-devices-with-curl-in-v1-api/76538993#76538993 – labu77 Jun 23 '23 at 09:58

1 Answers1

0

EDITED SOLUTION

I abandoned deprecated multicast messaging, I started using HTTP/2 and CURLPIPE_MULTIPLEX to send multiple requests across a single connection, each request targeting a different token. I tested it with 300 tokens and execution time was 3 seconds. My php code below:

function getAccessToken(){

    require "google-api-php-client/vendor/autoload.php";

    $client= new Google_Client();
    $client->setAuthConfig("firebasekey.json");
    $client->addScope('https://www.googleapis.com/auth/firebase.messaging');
    $client->refreshTokenWithAssertion();
    $token = $client->getAccessToken();
    $result=$token['access_token'];
            
    return $result;

}

function notification($notifications){
    
    $url = 'https://fcm.googleapis.com/v1/projects/your-project/messages:send';
    $headers = array(
        'Authorization: Bearer '.getAccessToken(),
        'Content-Type: application/json'
    );          

    $multiCurl = array();
    $mh = curl_multi_init();
    curl_multi_setopt($mh, CURLMOPT_PIPELINING,CURLPIPE_MULTIPLEX);

    foreach ($notifications as $i => $notification) {
        $multiCurl[$i] = curl_init();
        curl_setopt($multiCurl[$i], CURLOPT_URL,$url);
        curl_setopt($multiCurl[$i], CURLOPT_HTTPHEADER, $headers);
        curl_setopt($multiCurl[$i], CURLOPT_RETURNTRANSFER,true);
        curl_setopt($multiCurl[$i], CURLOPT_POST, true);
        curl_setopt($multiCurl[$i], CURLOPT_SSL_VERIFYHOST, 0);  
        curl_setopt($multiCurl[$i], CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($multiCurl[$i], CURLOPT_HTTP_VERSION,CURL_HTTP_VERSION_2_0);
        curl_setopt($multiCurl[$i], CURLOPT_POSTFIELDS, json_encode($notification,JSON_UNESCAPED_UNICODE));
        curl_multi_add_handle($mh, $multiCurl[$i]);
    }

    $index=null;
    do {
      curl_multi_exec($mh,$index);
      curl_multi_select($mh);
    } while($index > 0);
    
    foreach($multiCurl as $k => $ch) {
      $result[$k] = curl_multi_getcontent($ch);
      curl_multi_remove_handle($mh, $ch);
    }
    curl_multi_close($mh);
    
    print_r($result);
}


$mydata=array("messagefrom" => "server01","type" => "test");

//You need to create one notification for each token, you can put it inside a cycle and populate fields dynamically
$notifications[] = array(
    'message' => array(
        'token' => 'dNSYyeSETfa2LN2L39...',
        'android' => array(
            'priority' => 'high',
            'ttl' => '3600s',
        ),
        'data' => array(
            'mydata' => json_encode($mydata,JSON_UNESCAPED_UNICODE)         
        ),
    )
);

notification($notifications);

Google Api Client library https://github.com/googleapis/google-api-php-client/releases

To get the JSON with the key https://firebase.google.com/docs/admin/setup#initialize_the_sdk_in_non-google_environments

Cristian
  • 329
  • 2
  • 6
  • 14
  • `messaging.send_multicast()` is also deprecated and will be removed in 2024, as it relies on the deprecated Firebase Admin SDK batch send APIs. – Elad Nava Jul 18 '23 at 08:02
  • @EladNava Thanks for your reply... In this page https://firebase.google.com/docs/cloud-messaging/send-message#send-messages-to-specific-devices I see deprecated messages for old api down the page but no other messages for v1 HTTP Protocol. I'm confused – Cristian Jul 18 '23 at 09:07
  • The Firebase Admin SDK's `messaging.send_multicast()` does not use the FCM v1 HTTP API. It uses the deprecated `FCM HTTP Batch Send API`. See deprecation warning in the linked documentation page ("The batch send methods described in this section were deprecated on June 21, 2023") – Elad Nava Jul 18 '23 at 13:16
  • @EladNava I read the faqs https://firebase.google.com/support/faq#fcm-23-deprecation and I see that: Upgrade to the latest Firebase Admin SDK and use the new APIs instead: sendEach()/ sendEachAsync()/send_each()/sendEachForMulticast()/sendEachForMulticastAsync()/ send_each_for_multicast(). So I tested changing send_multicast() to send_each_for_multicast() and it works... send_each_for_multicast should use the new api – Cristian Jul 18 '23 at 15:59
  • Correct, the new method `send_each_for_multicast()` is the non-deprecated way to send notifications to multiple recipients. However, that method will execute an HTTP request per FCM device token, which will take a very long time if you have hundreds or thousands of recipients. Unlike the FCM Batch Send API, which accepted up to 500 device tokens, the FCM v1 API only accepts one per request. – Elad Nava Jul 18 '23 at 19:28
  • 1
    @EladNava I updated my answer only added response = messaging.send_each_for_multicast(message), I tested and it works with no other changes, so as you describe if message containes 100 registration_tokens it will make 100 HTTP request? – Cristian Jul 19 '23 at 06:53
  • Hi @Cristian, That's correct. Check the solution mentioned here for a solution that uses just one socket to send multiple HTTP/1.1 requests, one for each token, to the new FCM v1 API: https://stackoverflow.com/a/76538993/1123355 – Elad Nava Jul 19 '23 at 10:05
  • Hi @EladNava, thanks, I read the labu77 solution about REST batch call, I see in https://firebase.google.com/support/faq#fcm-23-deprecation and Batch Send API fcm.googleapis.com/batch will start failing after 6/21/2024, I'm very confused! Does his method work after that? – Cristian Jul 22 '23 at 07:12
  • Hi @Cristian My bad, that's indeed correct - the solution I linked to uses the deprecated Batch Send API. I assumed it was using HTTP 1.1 keep alive with multiple requests over the same connection to the FCM v1 API endpoint. While I am not aware of any other efficient solution that uses PHP, I developed a package for Node.js to leverage HTTP/2 to send multicast notifications via the FCM v1 API: https://eladnava.com/send-multicast-notifications-using-node-js-http-2-and-the-fcm-http-v1-api/ – Elad Nava Jul 22 '23 at 13:09
  • 1
    Hi @EladNava it's clear now! So there is not alternative, excpets your with nodejs, to send notifications to multiple token in the same time, this discussion https://groups.google.com/g/firebase-talk/c/f-9b1p6i0IM?pli=1 is exhaustive! So I need to create HTTP/2 PHP curl script to send multiple requests, every request is a single token, across a single connection – Cristian Jul 23 '23 at 06:18