I implemented Firebase Cloud Messaging in my application and while using the Firebase console my application in Android and iOS receives my notifications. But because I wanted to push notification daily I created a cron job to do that in my server side. I notice that every time i trigger my cron my application crashes
In my iOS client it doesn't receive any notification.
In my android client it displays an error:
java.lang.String com.google.firebase.messaging.RemoteMessage$Notification.getBody()' on a null object reference
Where it is in my FirebaseMessagingService here is my code
public class MyFirebaseMessagingService extends FirebaseMessagingService {
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d(TAG, "From: " + remoteMessage.getFrom());
Log.d(TAG, "Notification Message Body: " + remoteMessage.getNotification().getBody());
sendNotification(remoteMessage.getNotification().getBody());
}
And in my server-side
function sendNotificationFCM($apiKey, $registrationIDs, $messageText,$id) {
$headers = array(
'Content-Type:application/json',
'Authorization:key=' . $apiKey
);
$message = array(
'registration_ids' => $registrationIDs,
'data' => array(
"message" => $messageText,
"id" => $id,
),
);
$ch = curl_init();
curl_setopt_array($ch, array(
CURLOPT_URL => 'https://fcm.googleapis.com/fcm/send',
CURLOPT_HTTPHEADER => $headers,
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POSTFIELDS => json_encode($message)
));
$response = curl_exec($ch);
curl_close($ch);
return $response;
}
I'm wondering why am I having a NPE and how can I solve it?
Try to add a notification object on your $message. The body of your POST request must be something like:
{
"to" : "aUniqueKey",
"notification" : {
"body" : "great match!",
"title" : "Portugal vs. Denmark"
},
"data" : {
"Nick" : "Mario",
"Room" : "PortugalVSDenmark"
}
}
Your remoteMessage.getNotification() returnsnull because the body of your POST request doesn't contain a notification object.
Use notifications when you want FCM to handle displaying a notification on your client app's behalf. Use data messages when you want your app to handle the display or process the messages on your Android client app, or if you want to send messages to iOS devices when there is a direct FCM connection.
Check the Documentation for Advanced Messaging Options for your reference.
if (remoteMessage.getNotification() != null) {
sendNotification(remoteMessage.getNotification().getBody());
}
function sendNotificationFCM($apiKey, $registrationIDs, $messageText,$id) {
$headers = array(
'Content-Type:application/json',
'Authorization:key=' . $apiKey
);
$message = array(
'registration_ids' => $registrationIDs,
'data' => array(
"message" => $messageText,
"id" => $id,
),
'notification' => array(
"body" => "body of notification",
"title" => "title for notification",
)
);
$ch = curl_init();
curl_setopt_array($ch, array(
CURLOPT_URL => 'https://fcm.googleapis.com/fcm/send',
CURLOPT_HTTPHEADER => $headers,
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POSTFIELDS => json_encode($message)
));
$response = curl_exec($ch);
curl_close($ch);
return $response;
}
I faced the same issue and found out the solution through few experiments.
I am using Node backend where my Sample Push (Taken from Google Firebase) looks like:
const message = {
data: {score: '850', time: '2:45'},
tokens: nTokenArray
}
admin.messaging().sendMulticast(message)
.then((response) => {
if (response.failureCount > 0) {
const failedTokens = [];
response.responses.forEach((resp, idx) => {
if (!resp.success) {
console.log('resperrorresperrorresperrorresperror', resp.error);
failedTokens.push(registrationTokens[idx]);
}
});
console.log('List of tokens that caused failures: ' + failedTokens);
}
})
.catch(fcmError => {
console.log({'FCM Errors': fcmError});
})
At Android Side:
Log.d(TAG, "BodyScore: " + remoteMessage.getData().get("score"));
NullPointerException is due to when you use getNotification().getBody() instead of getData().get("score") when you are using Data Payload instead of Notification Payload at server side:
const message = {
data: {score: '850', time: '2:45'},
tokens: nTokenArray
}
Related
I am currently generating a data only FCM to my ionic application which will then create a local notification on the mobile application (android).
It works fine when the app is in foreground/background however when the app is closed the mobile application doesn't receive the notification.
Is there any solution to this issue? Preferably without having to send notification in the payload.
$data = [
"registration_ids" => [$user->device_token],
"data" => [
"targetPage" => "manualTicketPage",
"ticketID" => $ticket_id,
"ticketClassification" => $ticket_classification,
"title" => "New Task",
"body" => "Hi " . $user->name . ",\nYou have a new " . $ticket_description ." task to work on.",
"badge" => 99,
"content-available"=> "1",
"force-start"=>"1"
],
"priority"=>"high"
]
Ionic Code
this.platform.ready().then(() => {
this.rootPageParams = {'notificationReceived' : false };
if(this.device.platform != "browser"){
if(this.device.platform != "Android"){
this.requestNotificationPermission();
}
this.fcm.getToken().then(token => {
console.log("INSIDE GET TOKENNNNNNNN");
this.fcm.getInitialPushPayload().then( data => {
console.log('*********');
console.log("RECEIVE FCM NOTIFICATION");
console.log("DATA = "+ JSON.stringify(data));
if(data) {
if(data.wasTapped) {
if(data['targetPage'] == 'manualTicketPage'){
console.log("SET ROOT PAGE PARAMS");
this.rootPageParams = {'notificationWasTapped' : true,'targetPage' : 'manualTicketPage' };
}
}
}
})
});
this.fcm.onNotification().subscribe(async notificationData => {
console.log("NOTIFICATION RECEIVED ");
console.log("DATA = "+ JSON.stringify(notificationData));
if (notificationData.wasTapped) {
console.log("NOTIFICATION WAS TAPPED");
this.storage.get('url').then((url) => {
this.storage.get('id').then(data => {
let headers = new HttpHeaders();
headers.append('Content-Type', 'application/json');
headers.append('Authorization', 'my-auth-token');
let params = new HttpParams().set("user_id", data);
this.http.get(url + "/api/checkUserStatus", {headers: headers, params: params}).subscribe(data => {
if (data['status'] == "Active") {
if(notificationData['targetPage'] == 'manualTicketPage'){
console.log("SET ROOT PAGE PARAMS");
// this.rootPageParams = {'targetPage' : 'manualTicketPage' };
this.nav.push(TicketListPage);
}
else{
this.nav.push(ShowAuditPage);
}
}
})
})
})
} else {
console.log('Received in foreground');
}
});
}
I make app with cordova and Google FMC notification plugin and everything work great until app is in foreground.
//MY index.php
<div id="load"></div>
<script>
FCMPlugin.onNotification(function(data){
alert( JSON.stringify(data) );
// I DONT UNDERSTAND THIS SECTION ???
// WHAT I SCHOULT DO HERE???
if(data.wasTapped){
//Notification was received on device tray and tapped by the user.
alert( JSON.stringify(data) );
// I RECIVED THE DATA ON "CLOSED" APP! GET VARS AND LOAD FILE INTO div id="load" WITH AJAX BASED ON KEY SENDTH FROM FIREBASE CONSOLE
// EXAMPLE KEY = MESSAGE = 10890
// $AJAX LOAD FILE MESSAGE ?ID=10890
// CLEAR NOTIFICATIONS
//example ajax
var message= 10890; // GET FROM CORDOVA NOTIFICATION
var dataString = '& message=' + message;
$.ajax({
type: "POST",
url: "https://mywebsite.com/LOAD.php",
data: dataString,
success: function(response) {
$('#info').html(response);
}
});
}else{
//Notification was received in foreground. Maybe the user needs to be notified.
alert( JSON.stringify(data) );
// I RECIVED THE DATA ON OPEN APP! GET VARS AND LOAD FILE INTO div id="load" WITH AJAX BASED ON KEY SENDTH FROM FIREBASE CONSOLE
// EXAMPLE KEY = MESSAGE = 10890
// $AJAX LOAD FILE MESSAGE ?ID=10890
// CLEAR NOTIFICATIONS
// HOW TO GET VAR FROM alert( JSON.stringify(data) ); ??
//example ajax
var message= 10890; // GET FROM CORDOVA NOTIFICATION
var dataString = '& message=' + message;
$.ajax({
type: "POST",
url: "https://mywebsite.com/LOAD.php",
data: dataString,
success: function(response) {
$('#info').html(response);
}
});
}
});
</script>
Thnaks if sombody can help to solve this enigma. I hope its can help other people not expert like me.
I Use app as wrapper only and load external .php
App work great with all function that i need this ist only problem that i need to solve.
Thank You ,Sory for errors im newby
The Problem vas in sending notification
<?php
$url = "https://fcm.googleapis.com/fcm/send";
$token = "xxxx";
$serverKey = 'xxx';
$topic = 'mytopic';
$title = "title";
$body = "Message.";
$img = 'https://url.com/images/img.jpg';
$data = array('USR_id' => '1000',
'USR_name' => 'Name',
'MSG_id' => '1004',
'SEN_id' => '1001',
'USR_level' => 'user');
$android = array('senderID' => 'xxxxxxxxxxxx',
'sound' => true,
'vibrate' => true,
'clearNotifications' => true,
'forceShow' => true);
$notification = array('title' =>$title,
'body' => $body,
'image' => $img,
'sound' => 'audio.mp3',
'color' => '#F6C02B',
'click_action' => 'FCM_PLUGIN_ACTIVITY',
'badge' => '1');
$arrayToSend = array('to' => '/topics/' . $topic,
'notification' => $notification,
'data' => $data,
'android' => $android,
'priority' => 'high');
$json = json_encode($arrayToSend);
$headers = array();
$headers[] = 'Content-Type: application/json';
$headers[] = 'Authorization: key='. $serverKey;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST,"POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
curl_setopt($ch, CURLOPT_HTTPHEADER,$headers);
//Send the request
$response = curl_exec($ch);
//Close request
if ($response === FALSE) {
//die('FCM Send Error: ' . curl_error($ch));
}
curl_close($ch);
?>
After i send it with php that work Perfect
I have a problem in my project. I am using edujugon push-notification for push notification of my app, I created push notification to android, ios devices successfully with title, body. But when I integrate the notification in my web devices it does not show the title and body rather it shows the site is upgrated in backend. Also I want to set an url in my web notification. But dont know how.
Here is my code
public static function sendPushNotification($devices, $pushData, $partner = false) {
$android = $devices->where('type', 2)->pluck('token')->all();
if (!empty($android)) {
$push = new PushNotification('fcm');
$push->setMessage(
[
'data' => $pushData,
]
)
->setDevicesToken($android)
->send();
}
$ios = $devices->where('type', 1)->pluck('token')->all();
if (!empty($ios)) {
$push = new PushNotification('apn');
$feedback = $push->setMessage(
[
'aps' => [
'alert' => [
'title' => $pushData['title'],
'body' => $pushData['body'],
],
'sound' => 'default',
'badge' => 1
],
'data' => $pushData
]
)->setDevicesToken($ios)->send()->getFeedback();
}
$web = $devices->where('type', 3)->pluck('token')->all();
if (!empty($web)) {
$push = new PushNotification('fcm');
$push->setMessage($pushData)->setDevicesToken($web)->send();
}
}
and my push data is
$pushData = [
'title' => 'Test',
'body' => 'Test',
];
Please help me solving this
You should write this
if (!empty($web)) {
$push = new PushNotification('fcm');
$push->setMessage(
[
'notification' => $pushData,
]
)->setDevicesToken($web)->send();
}
Hopefully this will solve your problem.
i am trying Edujugon Push Notification laravel; all configuration be correct.
my push notification code is
$push = new PushNotification('fcm');
$push->setMessage([
'notification' => [
'title'=>'This is the title',
'body'=>'This is the message',
'sound' => 'default'
],
'data' => [
'extraPayLoad1' => 'value1',
'extraPayLoad2' => 'value2'
]
])
->setApiKey('AAAAv7w78uY:APA91bF73GY1AcZvBh84K2matRxFwWB0VQysqlDzsLBtrmVRbRN0e6T2Lxasiv-sNfWaNQwqgltTaiaL0rZVC5TKzwfZRgrxb30B4jkl2bzJ9DViZsbGVdQMNOJ78FtOfwcUCgvUj_XC7jLdargjnfKQAD0ecbWMlA')
->setDevicesToken('fj6Sx3zYjhM:APA91bE3cas4LPX-T9jJ-7YgKrMIYOiD5Brjf9AgqvCUsSN7OygZEX3qhQ1F4RxCZfsvSCHNV9gq15NL26k62KBuWqpX4G9nrSQHT3ddabCTRwinqbmpt53gtdCgakaW5LvSxA1t1-iiZS8at8pW7W9o5Gyv2mBSEw');
$push = $push->send();
Please refer https://packagist.org/packages/edujugon/push-notification
$push->setMessage([
'notification' => [
'title'=>'This is the title',
'body'=>'This is the message',
'sound' => 'default'
],
'data' => [
'extraPayLoad1' => 'value1',
'extraPayLoad2' => 'value2'
]
])
->setApiKey('Server-API-Key')
->setDevicesToken(['deviceToken1','deviceToken2','deviceToken3'...]);
used this package LARAVEL-FCM EASY TO USED
I have also integrated push notification in laravel using below code, hope it helps you :
function sendPushNotification($fcm_token, $title, $message, $id="") {
$push_notification_key = Config::get('settings.PUSH_NOTIFICATION_KEY');
$url = "https://fcm.googleapis.com/fcm/send";
$header = array("authorization: key=" . $push_notification_key . "",
"content-type: application/json"
);
$postdata = '{
"to" : "' . $fcm_token . '",
"notification" : {
"title":"' . $title . '",
"text" : "' . $message . '"
},
"data" : {
"id" : "'.$id.'",
"title":"' . $title . '",
"description" : "' . $message . '",
"text" : "' . $message . '",
"is_read": 0
}
}';
$ch = curl_init();
$timeout = 120;
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
// Get URL content
$result = curl_exec($ch);
// close handle to release resources
curl_close($ch);
return $result;
}
I am using ngcordova push plugin for android with ionic framework.
My device is getting registered in GCM. I get the registration id as well. I am able to store the regid in users table. Everything works fine till now. But when I send the notification from my php server I cannot receive the notification in my mobile phone. The response of the gcm to php code I get is:
{"multicast_id":5214502018855543648,"success":1,"failure":0,"canonical_ids":0,"results":[{"message_id":"0:1439022666580761%156ac804f9fd7ecd"}]}
My JavaScript code is.
.run(function($ionicPlatform,ngFB,$state,$cordovaPush,$rootScope) {
$ionicPlatform.ready(function() {
// ------------------------------ GCM NG-CORDOVA PUSH-----------------------------------
var androidConfig = {
"senderID": "XXXXXXXXXX"
};
$cordovaPush.register(androidConfig).then(function(result) {
// Success
alert(result);
}, function(err) {
// Error
alert(err);
});
$rootScope.$on('$cordovaPush:notificationReceived', function(event, notification) {
switch(notification.event) {
case 'registered':
if (notification.regid.length > 0 ) {
alert('registration ID = ' + notification.regid);
$rootScope.reg_id = notification.regid;
}
break;
case 'message':
// this is the actual push notification. its format depends on the data model from the push server
alert('message = ' + notification.message + ' msgCount = ' + notification.msgcnt);
break;
case 'error':
alert('GCM error = ' + notification.msg);
break;
default:
alert('An unknown GCM event has occurred');
break;
}
});
// WARNING: dangerous to unregister (results in loss of tokenID)
// $cordovaPush.unregister(options).then(function(result) {
// Success!
//}, function(err) {
// Error
//})
});
})
My php code is:
<?php
// API access key from Google API's Console
define( 'API_ACCESS_KEY', 'YOUR-API-ACCESS-KEY-GOES-HERE' );
$registrationIds = array( $_GET['id'] );
// prep the bundle
$msg = array
(
'message' => 'here is a message. message',
'title' => 'This is a title. title',
'subtitle' => 'This is a subtitle. subtitle',
'tickerText' => 'Ticker text here...Ticker text here...Ticker text here',
'vibrate' => 1,
'sound' => 1,
'largeIcon' => 'large_icon',
'smallIcon' => 'small_icon'
);
$fields = array
(
'registration_ids' => $registrationIds,
'data' => $msg
);
$headers = array
(
'Authorization: key=' . API_ACCESS_KEY,
'Content-Type: application/json'
);
$ch = curl_init();
curl_setopt( $ch,CURLOPT_URL, 'https://android.googleapis.com/gcm/send' );
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 );
curl_close( $ch );
echo $result;
I don't understand where I am wrong. Please help me.
Thanks
I had the same problem one time back, I recommend making your first application with the link below and let second regid make sure the device is correct, that keep well and that the keys of the application are correct. Try the same browser send notifications, sometimes vary in time.
add android app
Make sure you wrap your $cordovaPush.register() and $rootScope.$on() functions inside document.addEventListener("deviceready", function() {}
like this
document.addEventListener("deviceready", function() {
console.log("insode ");
$cordovaPush.register(androidConfig).then(function(result) {
console.log(result);
// Success
}, function(err) {
console.log(err);
// Error
})
$rootScope.$on('$cordovaPush:notificationReceived', function(event, notification) {
console.log(event);
console.log(notification);
switch (notification.event) {
case 'registered':
if (notification.regid.length > 0) {
//alert('registration ID = ' + notification.regid);
}
$http({
url: "http://192.168.1.101/saveregid.php",
method : "POST",
data : {
id : notification.regid
}
}).success(function(){
alert("Id is saved");
});
break;
case 'message':
// this is the actual push notification. its format depends on the data model from the push server
$scope.notification = notification;
//alert('message = ' + notification + ' msgCount = ' + notification.msgcnt);
break;
case 'error':
alert('GCM error = ' + notification.msg);
break;
default:
alert('An unknown GCM event has occurred');
break;
}
});
}, false);
To get a correct reg id I have made a simple script at http://192.168.1.101/saveregid.php which gets registration id in its post request and stores it on server file which I can access. Get exact reg id from server file and then try sending a notification.