Android Firebase Push notification using php - php

I implemented FCM for my app. I'm using php to send the notification for the registered ids in my DB . I want to send a specific message for each user. Now when I push the notification, I'm getting the same message for all the users.
Example:
I have two registered users in the DB:
1- User called John and his custom message is "Welcome"
2- User called Marco and his custom message is "Happy birth day"
Now when I push the notification all the two users are getting the same message "Welcome".
This is my code:
<?php
function send_notification ($tokens, $message)
{
$url = 'https://fcm.googleapis.com/fcm/send';
$fields = array(
'registration_ids' => $tokens,
'data' => $message,
'priority' => "high",
);
$headers = array(
'Authorization:key = FCM Server Key',
'Content-Type: application/json'
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
$result = curl_exec($ch);
if ($result === FALSE) {
die('Curl failed: ' . curl_error($ch));
}
curl_close($ch);
return $result;
}
include("conn.php");
mysql_select_db($db, $conn);
$query_users = sprintf("Select token, message From users");
$users = mysql_query($query_users, $conn) or die(mysql_error());
$row_users = mysql_fetch_assoc($users);
$totalRows_users = mysql_num_rows($users);
if($totalRows_users > 0 ) {
do {
$tokens[] = $row_users["token"];
$message = $row_users["message"];
} while ($row_users = mysql_fetch_assoc($users));
}
$message_status = send_notification($tokens, $message);
echo $message_status;
?>

you can send fcm with multiple token at once (1000 token limit if i'm not mistake), but, you cannot send with multiple messages
the message that you send is the message from your last record in your queries
$message = $row_users["message"];
if you want to send with different message, then you need to call
send_notification($tokens, $message);
multiple times.

Related

InvalidRegistration on sending push to muliple devices

I'm trying to send push notifications to multiple device using Google Firebase and I always received the error : "InvalidRegistration".
This is the tokens that I sent in the "to"
:json_encode($tokensPerEvent):
["eV9g4oTwjZs:APA91bF3YLGtDkCDekvR6eahbVAn-jIY0sVGjxMWyBEyR-
3AB9q6RBhw4fyeqE4ZkZxQs0TsYhUee9Txy_exAGxtrBPV_-
sjKlWcV3z3nDYXOcVSVwlpPyGzUJKxGMU16drMR41bLI4t"]
and this is the response :
{
"multicast_id":***,
"success":0,
"failure":1,
"canonical_ids":0,
"results":[
{
"error":"InvalidRegistration"
}
]
}
another questions: if the one of the tokens not exist anymore, this is effect on all the other tokens , or just the only old one will effected ?
This is my code:
<?php
require_once '../CommonFunctions.php';
ignore_user_abort();
ob_start();
$url = 'https://fcm.googleapis.com/fcm/send';
//GET TOKENS FROM DB
$db = new Database();
$db->query("SELECT push_token FROM User");
$db1 = new Database();
$db1->query("SELECT phone FROM invite_list where event_id = 137");
$response = $db->resultset();
$response1 = $db1->resultset();
$arr2 = array_column($response1, 'phone');
$phones = join("','",$arr2);
$db2 = new Database();
$db2->query("SELECT push_token FROM User WHERE phone IN ('$phones')");
$tokensPerEvent = array();
$tokensrr = $db2->resultset();
$tokensPerEvent = array_column($tokensrr, 'push_token');
echo json_encode($tokensPerEvent);
$fields = array('to' => json_encode($tokensPerEvent),
'notification' => array('body' => 'HI', 'title' => ':)'));
define('GOOGLE_API_KEY', '***********');
$headers = array(
'Authorization:key='.GOOGLE_API_KEY,
'Content-Type: application/json'
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
$result = curl_exec($ch);
if($result === false)
die('Curl failed ' . curl_error());
curl_close($ch);
return $result;
?>
If you want to send push notification to many clients by theirs registration ids, you have to use registration_ids instead of to field. You can find this in docs (second parameter).
You are also encoding tokens two times:
$fields = array('to' => json_encode($tokensPerEvent), ...
and
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
Try by skipping encoding $tokensPerEvent in array:
$fields = array('to' => $tokensPerEvent, ...

Getting Unauthorized Error 401 in Firebase Cloud Messaging in cURL command

I'm going to send Firebase Cloud Messaging and the problem that I'm facing is I get an Unauthorized Error 401.
I got the security key from my Firebase website then set it. The device token is already in database and I read from database with no problem.
This is my code so far:
<?php
function send_notification($tokens, $message)
{
$url = 'https://fcm.googleapis.com/fcm/send';
$fields = array('registration_ids' => $tokens, 'data' => $message);
$headers = array('Authorization: key=' . "My Firebase key", 'Content-Type: application/json');
echo "work well before init curl";
$ch = curl_init();
echo "init well";
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
echo "init finishe well";
$result = curl_exec($ch);
echo "Execute to get result";
if ($result === false) {
die('Curl failed: ' . curl_error($ch));
}
curl_close($ch);
echo "function finished well";
return $result;
}
$conn = mysqli_connect("localhost", "root", "mysql_password", "FCM") or die("Error connecting");
$sql = " Select Token From users";
$result = mysqli_query($conn, $sql);
$tokens = array();
if (mysqli_num_rows($result) > 0) {
while ($row = mysqli_fetch_assoc($result)) {
$tokens[] = $row["Token"];
}
}
mysqli_close($conn);
$message = array("message" => " FCM PUSH NOTIFICATION TEST MESSAGE");
$message_status = send_notification($tokens, $message);
echo $message_status;
?>
When using FCM, you must use the Server Key seen in the Cloud Messaging tab of your Firebase Console as the value for Authorization in your requests.
Using the documentation at https://developers.google.com/instance-id/reference/server, I wanted to use https://iid.googleapis.com/iid/info/IID_TOKEN to get information about app instances.
In the code of my app, I used this to get the IDD_TOKEN:
// Get token using example from https://github.com/firebase/quickstart-android/blob/master/messaging/app/src/main/java/com/google/firebase/quickstart/fcm/java/MainActivity.java.
// [START retrieve_current_token]
FirebaseInstanceId.getInstance().getInstanceId()
.addOnCompleteListener(new OnCompleteListener<InstanceIdResult>() {
#Override
public void onComplete(#NonNull Task<InstanceIdResult> task) {
if (!task.isSuccessful()) {
Log.w(TAG, "getInstanceId failed", task.getException());
return;
}
// Get new Instance ID token
String token = task.getResult().getToken();
System.out.println("task.getResult().getToken() = "+token);
// Log and toast
String msg = getString(R.string.msg_token_fmt, token);
Log.d(TAG, msg);
Toast.makeText(FirstActivity.this, msg, Toast.LENGTH_SHORT).show();
}
});
// [END retrieve_current_token]
Then in the Android Studio logs, I found the token (I am changing the value of the token because I do not want to post the real one here):
I/System.out: task.getResult().getToken() = bepGr4F2b0Q:APB91cEAKsN1bGjMm5xsobxBHxuYZLfioTPMEIN90njdiK5C2MnOYF5NcOy6ot6XFanMTBIoKRGcyev5RJuydGWt1XHwsniNZ6h3Pjvn9Fqth-Mqgj_2-YN9pv_nMAugG8blc5boeDyH
This means that the IDD_TOKEN was bepGr4F2b0Q:APB91cEAKsN1bGjMm5xsobxBHxuYZLfioTPMEIN90njdiK5C2MnOYF5NcOy6ot6XFanMTBIoKRGcyev5RJuydGWt1XHwsniNZ6h3Pjvn9Fqth-Mqgj_2-YN9pv_nMAugG8blc5boeDyH. So in my PHP code I used this:
$curlUrl = "https://iid.googleapis.com/iid/info/bepGr4F2b0Q:APB91cEAKsN1bGjMm5xsobxBHxuYZLfioTPMEIN90njdiK5C2MnOYF5NcOy6ot6XFanMTBIoKRGcyev5RJuydGWt1XHwsniNZ6h3Pjvn9Fqth-Mqgj_2-YN9pv_nMAugG8blc5boeDyH?details=true";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $curlUrl);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
//turning off the server and peer verification(TrustManager Concept).
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Authorization:key=[My server key]'));
//getting response from server
$response = curl_exec($ch);
print_r($response);
Where is the [My server key] found? You can find it at https://console.firebase.google.com/. Go to the Cloud Messaging tab, and in the Project credentials section, you will find the Server key:
The result was this:
{"applicationVersion":"50","connectDate":"2019-05-09","attestStatus":"NOT_ROOTED","application":"[My package name]","scope":"*","authorizedEntity":"[My Firebase Sender ID]","rel":{"topics":{"Toronto":{"addDate":"2019-05-09"}}},"appSigner":"[My appSigner]","platform":"ANDROID"}
That is correct. I can tell that those values correspond to my IID_TOKEN for the device that I connected, I can recognize that and everything is correct. I can confirm that I subscribed my device to that topic and everything works correctly! I was able to use https://iid.googleapis.com/iid/info/IID_TOKEN to get information about my app instances corresponding to an Android device that I connected using Firebase.

Firebase cloud messaging php script returning invalid registration

I researched online and tried various methods to fix this problem however it did not solve the problem. This is the error i get in my php script
{"multicast_id":6412971464416964071,"success":0,"failure":1,"canonical_ids":0,"results":[{"error":"InvalidRegistration"}]}
I am using authorisation key which is the server key.
push_notification.php
<?php
function send_notification ($tokens, $message)
{
$url = 'https://fcm.googleapis.com/fcm/send';
$fields = array(
'registration_ids' => $tokens,
'data' => $message
);
$headers = array(
'Authorization:key = ********',
'Content-Type: application/json'
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
$result = curl_exec($ch);
if ($result === FALSE) {
die('Curl failed: ' . curl_error($ch));
}
curl_close($ch);
return $result;
}
$conn = mysqli_connect("localhost","root","","fcm");
$sql = "Select Token From users";
$result = mysqli_query($conn,$sql);
$tokens = array();
if(mysqli_num_rows($result) > 0 ){
while ($row = mysqli_fetch_assoc($result)) {
$tokens[] = $row["Token"];
}
}
mysqli_close($conn);
$message = array("message" => " FCM PUSH NOTIFICATION TEST MESSAGE");
$message_status = send_notification($tokens, $message);
echo $message_status;
?>
There is a valid token in my database. However it shows invalid registration. How do i fix this?
If it's invalid registration,
check the format of the registration token you pass to the server. Make sure it matches the registration token the client app receives from registering with Firebase Notifications. Do not truncate or add additional characters.
Source: Downstream message error response codes
If that recommended action doesn't work for you, here are additional things that you can do:
Verify ID Tokens. It mentioned about the need to verify the integrity and authenticity of the ID token and retrieve the uid from it.
You may want to also check this suggested solution in this SO post wherein it states that if you retrieve token from db, you make sure the data type for the column is either text or a very long varchar like 200.

Fixing GCM 1000 message limit, help loop script

I am using PHP to send GCM notification to users. Based on their token saved in SQL on server. But I have a limit of 1000 notifications at once to send,
this is my working code , now i need to edit it to loop the process, and send 5000 notification in sections, 1000 than 1000 etc.
Here is my PHP code, and a simple HTML I didn't post here,
<?php
$mysqlHost = "";
$mysqlUser = "";
$mysqlPwd = ";
$mysqlDbname = "";
class GCM {
function __construct(){}
public function send_notification($registatoin_ids,$data) {
// GOOGLE API KEY
define("GOOGLE_API_KEY","************");
$url="https://android.googleapis.com/gcm/send";
$fields=array(
"registration_ids"=>$registatoin_ids,
"data"=>$data,
);
//var_dump($fields);
$headers=array(
"Authorization: key=".GOOGLE_API_KEY,
"Content-Type: application/json"
);
$ch=curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_POST,true);
curl_setopt($ch,CURLOPT_HTTPHEADER,$headers);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);
curl_setopt($ch,CURLOPT_POSTFIELDS,json_encode($fields));
$result_gcm=curl_exec($ch);
if($result_gcm===FALSE){
die("Curl failed: ".curl_error($ch));
}
curl_close($ch);
//echo $result_gcm;
}
}
// Create connection
$conn = mysqli_connect($mysqlHost, $mysqlUser, $mysqlPwd, $mysqlDbname);
// Check connection
if (!$conn) {
die("Connection failed: " . mysqli_connect_error());
}
$result = $conn->query("SELECT * FROM users WHERE users_android_token IS NOT NULL AND users_android_token <> ''");
$android_tokens = array();
$x=0;
if ($result->num_rows > 0) {
// output data of each row
while($row = $result->fetch_assoc()) {
$android_tokens[] = $row["users_android_token"];
$x++;
}
} else {
echo "0 results";
}
$conn->close();
$title = $_POST['title'];
$msg = $_POST['message'];
$link = $_POST['link'];
if ($android_tokens != array()) {
$gcm=new GCM();
$data=array("title"=>$title,"description"=>$msg,"link"=>$link);
$result_android=$gcm->send_notification($android_tokens,$data);
}
?>
Rather than send notification by registrationId, why not using send notification by topic. You only need to make client subscribed to certain topic.
in GCM, you can send notification topic with this code :
function send_notification_topic($topicname, $message){
$url = 'https://android.googleapis.com/gcm/send';
$fields = array(
'to' => '/topics/' . $topicname,
'data' => $message
);
$headers = array(
'Authorization: key=AIzablablablayourServerKey',
'Content-Type: application/json'
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
$result = curl_exec($ch);
if($result === FALSE){
die('Curl failed : ' . curl_error($ch));
}
curl_close($ch);
return $result;
}
Use this code for divided your tokens .
if ($android_tokens != array()) {
$gcm = new GCM();
$data = array("title" => $title,"description" => $msg,"link" => $link);
//Divide array into 1000 tokens
$splitTokens = array_chunk($android_tokens, 1000);
//loop the array
//Obs: for looping notification may push slow
foreach($splitTokens as $tokens) {
$result_android = $gcm -> send_notification($tokens,$data);
}
}
For divide GCM may push the notification slow . it take up to 2 - 10 mins.

how to send google cloud messaging in queing?

Hi i am sending notifications to android mobile from php server. Its working fine with single notifications. But if i send 2 notifications at once. First notification is replacing by second notifications. is there any way i can see 2 notifications in queing (i.e like sms inbox message format).
Below is my php code:
<?php
define("GOOGLE_API_KEY", "API id");
define("GOOGLE_GCM_URL", "https://android.googleapis.com/gcm/send");
function send_gcm_notify($reg_id, $message) {
$fields = array(
'registration_ids' => array( $reg_id ),
'data' => array( "message" => $message ),
);
$headers = array(
'Authorization: key=' . GOOGLE_API_KEY,
'Content-Type: application/json'
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, GOOGLE_GCM_URL);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
$result = curl_exec($ch);
if ($result === FALSE) {
die('Problem occurred: ' . curl_error($ch));
}
curl_close($ch);
echo $result;
}
$reg_id = "device id";
$msg = "Google Cloud Messaging working well";
for($i=0;$i<=3;$i++){
send_gcm_notify($reg_id, $msg);}
since you are sending data to the same notification builder.. second one is placed on top of first one. that is the default way of notification. but if you want to send multiple notifications for two tasks, you should use two notification builders and filter the received messages and call relevant notification builder. but there are limitations, so this depends on your program requirement.
if you are looking for notification as following image
StackYour notifications

Categories