Notifications are not always received by my Android phones, even though Cloud Functions always sends them. As a useful side node: WhatsApp messages are always received (I tested it).
I noticed that notifications are received immediately when the phone is charging or when you open the app.
Also, the UID of the user is not always sent to the database even though a notification has been displayed (you'll understand what I mean by reading the code).
My question is: what can I change to receive notifications and then push to database all the time like it's supposed to be?
My notifications are of the "heads-up" type.
I've been trying to optimize my code for days with no success. I need help.
Code structure:
When message is received, push UID of user to database to see how many people have been notified later.
Send notification to user.
public class MyFirebaseMessagingService extends FirebaseMessagingService {
// Firebase instance variables
private FirebaseAuth mFirebaseAuth;
private FirebaseUser mFirebaseUser;
DatabaseReference myURL = FirebaseDatabase.getInstance().getReferenceFromUrl("https://newproj-54a87.firebaseio.com/notified");
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// Check if message contains a data payload.
if (remoteMessage.getData() != null) {
mFirebaseAuth = FirebaseAuth.getInstance();
mFirebaseUser = mFirebaseAuth.getCurrentUser();
if(mFirebaseUser != null)
mUID = mFirebaseUser.getUid();
myURL.push().setValue(mUID);
sendNotification(remoteMessage.getData().get("body"), remoteMessage.getData().get("title"), remoteMessage.getData().get("icon"));
}
}
private void sendNotification(String messageBody, String messageTitle, String iconURL) {
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
Bitmap bitmap = getBitmapFromURL(iconURL);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setDefaults(DEFAULT_SOUND | DEFAULT_VIBRATE)
.setPriority(Notification.PRIORITY_MAX)
.setStyle(new NotificationCompat.BigTextStyle())
.setSmallIcon(R.drawable.myIcon)
.setLargeIcon(bitmap)
.setContentTitle(messageTitle)
.setContentText(messageBody)
.setAutoCancel(true)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
public Bitmap getBitmapFromURL(String strURL) { //from https://stackoverflow.com/a/16007659
try {
URL url = new URL(strURL);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
Bitmap myBitmap = BitmapFactory.decodeStream(input);
return myBitmap;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
}
My Cloud Function:
const payLoad = {
data:{
title: name,
body: body,
icon: photoURL
}
};
var options = {
priority: "high",
timeToLive: 1000
};
return admin.messaging().sendToTopic("notify", payLoad, options);
Please tell me if I forgot a piece of information. I'm running on a limited time schedule!
If you are using Android 6.0 or versions above there is a feature called Doze that optimizes battery usage. When your phone is Idle (and it is not charging) it only receives high priority FCM notifications, and probably that's your case.
Android documentation says:
FCM is optimized to work with Doze and App Standby idle modes by means
of high-priority FCM messages. FCM high-priority messages let you
reliably wake your app to access the network, even if the user’s
device is in Doze or the app is in App Standby mode. In Doze or App
Standby mode, the system delivers the message and gives the app
temporary access to network services and partial wakelocks, then
returns the device or app to the idle state.
So if are using FCM data messages your backend should start sending the field "priority" : "high".
Ref: https://firebase.google.com/docs/cloud-messaging/concept-options
Related
I am developing an Android application in which I would like to receive a Push notification when application state is both in Foreground and Background.
It was working fine before the click_action is added but after adding it does not make the push notification received when the application is background or killed. After some research, I could understand that I will not be able to receive the Push in Background if the FCM is "notification" message type but only "data" message type.
As FCM provides click_action attribute by default and also provides the method getClickAction() to get it in onMessageReceived(), Should I really use click_action in data message ?
The bundle in onMessageReceived
Bundle[{
google.sent_time = 1521177008895,
google.ttl = 3600,
gcm.notification.e = 1,
lastName = Test,
profileUrl = ,
roleId = ,
userId = 140128,
gcm.notification.badge = 1,
gcm.notification.sound =
default,
gcm.notification.title = Someone
try to login with your credentials,
roleName = ,
userName = test,
flag = 0,
from = 612005318045,
type = 0,
gcm.notification.sound2 = simpleSound,
firstName = Test,
gcm.notification.notification_id = 1140,
google.message_id = 0: 1521177008900292 % c05b1316c05b1316,
notification = Someone
try to login with your credentials,
gcm.notification.body = Someone
try to login with your credentials,
gcm.notification.icon = myApp,
notificationId = 2047669,
gcm.notification.notification_type = 1,
gcm.notification.click_action = com.my.push.activities.OPEN_NOTIFICATION_LIST,
gcm.notification.notification_message = TEST MESSAGE,
notificationDate = Fri Mar 16 05: 10: 08 GMT 2018,
collapse_key = com.my.push,
gcm.notification.notification_title = APP
}]
The code snippet of the way it is handled in onMessageReceived
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
......
......
showNotification(remoteMessage);
}
public void showNotification(RemoteMessage remoteMessage) {
try {
Map<String, String> response = remoteMessage.getData();
Intent intent = prepareIntent(remoteMessage);
PendingIntent pIntent = PendingIntent.getActivity(this, 0,
intent, PendingIntent.FLAG_ONE_SHOT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "D4E_ANDROID")
.setContentTitle("New Notification")
.setContentText(response.get("notification"))
.setSmallIcon(R.drawable.d4e_logo)
.setContentIntent(pIntent)
.setAutoCancel(true)
.addAction(R.drawable.view_icon, "View", pIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(Integer.parseInt(response.get("notificationId")), builder.build());
} catch (Exception exception) {
Log.e("OnREC", exception.toString());
}
}
public Intent prepareIntent(RemoteMessage remoteMessage) {
Map<String, String> response = remoteMessage.getData();
Intent intent;
boolean isAppInBackground;
if (SessionContext.isLoggedIn()) {
isAppInBackground = SessionHelper.initializeSessionHelper().isAppInBackground(this);
Log.e("LOGGGGG", isAppInBackground + "");
if (isAppInBackground) {
intent = new Intent(this, SplashScreen.class);
} else {
intent = new Intent(remoteMessage.getNotification().getClickAction());
}
}
} else {
intent = new Intent(this, LoginActivity.class);
}
return intent;
}
Please anyone guide me to find the solution.
if you can receive FCM notification sent through console, then potentially something is wrong with build the notification. one suspect is that you are not using "icon" field.
If you can debug android device, set breakpoint here and see if you get error or missed some resource.
https://github.com/evollu/react-native-fcm/blob/master/android/src/main/java/com/evollu/react/fcm/SendNotificationTask.java#L46
hello i have android application and i used Firebase notification and its working good ,, now i need to receive silent push without alert or anything ,,, i tried some idea and its working when app is running but when app in background or terminated its not working ! if anyone have idea to sole this issue please tell me :) this is my code
public class MyFirebaseMessagingService extends FirebaseMessagingService {
Boolean isSilent;
String Silent = "";
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
try {
Bundle bundle = new Bundle();
for (Map.Entry<String, String> entry : remoteMessage.getData().entrySet()) {
bundle.putString(entry.getKey(), entry.getValue());
Log.d(entry.getKey(), entry.getValue());
}
// remoteMessage.getData().get("screen_id")
if (remoteMessage.getData().size() > 0) {
sendNotificationData(bundle.getString("data_title"), bundle.getString("data_body"), bundle.getString("screen_id"));
} else if (remoteMessage.getNotification() != null) {
sendNotification(remoteMessage.getNotification(), bundle.getString("screen_id"));
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
private void sendNotification(RemoteMessage.Notification notificationR, String screenId) {
NotificationManager nManager = (NotificationManager) this.getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
Intent intentNotification = new Intent(this, MainActivity.class);
intentNotification.putExtra("screen_id", screenId);
Log.v("sendNotification ", " >>>>>####>>>>>>>> " + screenId);
// finish previous activity
if (!Silent.equals("yes")) {
intentNotification.addFlags(android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP);
intentNotification.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 50, intentNotification, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this.getApplicationContext())
.setContentTitle(notificationR.getTitle())
.setContentText(notificationR.getBody())
.setSmallIcon(getNotificationIcon())
.setLargeIcon(icon(getApplicationContext()))
.setLights(Color.LTGRAY, 1000, 1000)
.setAutoCancel(true)
.setTicker(notificationR.getTitle())
.setContentIntent(pendingIntent)
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION));
Notification notification = notificationBuilder.build();
// '|' Binary OR Operator copies a bit if it exists in either operand. to ensure no conflict on the flags
notification.flags = notification.flags | Notification.FLAG_SHOW_LIGHTS;
nManager.notify((int) SystemClock.currentThreadTimeMillis(), notification);
}
}
private void sendNotificationData(String dataTitle, String dataBody, String screenId) {
NotificationManager nManager = (NotificationManager) this.getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
Intent intentNotification = new Intent(this, MainActivity.class);
intentNotification.putExtra("screen_id", screenId);
if (!Silent.equals("yes")) {
intentNotification.addFlags(android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP);
intentNotification.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 50, intentNotification, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this.getApplicationContext())
.setContentTitle(dataTitle)
.setContentText(dataBody)
.setSmallIcon(getNotificationIcon())
.setLargeIcon(icon(getApplicationContext()))
.setLights(Color.LTGRAY, 1000, 1000)
.setAutoCancel(true)
.setTicker(dataTitle)
.setContentIntent(pendingIntent)
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION));
Notification notification = notificationBuilder.build();
// '|' Binary OR Operator copies a bit if it exists in either operand. to ensure no conflict on the flags
notification.flags = notification.flags | Notification.FLAG_SHOW_LIGHTS;
nManager.notify((int) SystemClock.currentThreadTimeMillis(), notification);
}
#Override
public boolean zzE(Intent intent) {
isSilent = intent.hasExtra("silent");
if (isSilent) {
Silent = "yes";
}
return super.zzE(intent);
}
when app is running this code is working but at background or terminated its not working !!
When your app is in Background firbase notification message received on 'System tray' that's why FirebaseMessagingService.onMessageReceived not called.
When your app is in the background, Android directs notification messages to the system tray. A user tap on the notification opens the app launcher by default.
Try to sent data payload that will call onMessageReceived. and your code will
work
For data message....
Get firebase token from FirebaseInstanceIdService and sent it to app server.
Google have very good documentation to sent it Here
You can sent it using php also.
Then on onMessageReceived
if (remoteMessage.getData().size() > 0) {
String title = remoteMessage.getData().get("title");
String body = remoteMessage.getData().get("body");
String screen = remoteMessage.getData().get("screen");
sendNotification(title, body, screen );}
For Server side php implementation
<?php
$path_to_fcm = "https://fcm.googleapis.com/fcm/send";
$headers = array(
'Authorization:key='YOUR_SERVER_KEY,
'Content-Type:application/json'
);
$reg_id_array = array
(
'token1',
'token2'
)
$mesg = array
(
'title'=>$_POST['title'],
'body'=> $_POST['message'],
'url'=>$_POST['Screen'],
);
$fields = array("registration_ids"=>$reg_id_array, 'data'=>$mesg);
$payload = json_encode($fields);
$curl_session = curl_init();
curl_setopt($curl_session, CURLOPT_URL, $path_to_fcm);
curl_setopt($curl_session, CURLOPT_POST, true);
curl_setopt($curl_session, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl_session, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl_session, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl_session, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4 );
curl_setopt($curl_session, CURLOPT_POSTFIELDS, $payload);
$Qresult = curl_exec($curl_session);
$httpcode = curl_getinfo($curl_session , CURLINFO_HTTP_CODE);
curl_close($curl_session);
if ($httpcode==200) {
echo "Success";
}
?>
Sorry bad English
A Notification contains 2 thigs:
the notification itself and
extra data.
You seem to have data in your code because of values such as screen_id, data_title``etc. It actually looks you are reading everything from thedata` part, I will leave the docs here just in case. In the first table in that page explains where each notification is handled.
Since you use data, all notifications will be manged in onMessageReceived, so the only think I can think of is you terminated the app from Android Studio (through the Stop button).
Doing so, the App terminates, and also does background Firebase instance. All processes exit. So try closing it from the mobile, and report if it worked.
Good luck.
I am really stuck and want to push notification only to specific user using Firebase. I know the FCM method and have got the token. But this tutorial or other tutorials that I've followed are making me send push notification to both users including the sender. I just want to get notification on Recipient Device. Its been a long day , I've been working on this problem.
Looking for some key or UID of the Recipient now. Is it to be fetched from token that I have : FirebaseInstanceId.getInstance().getToken();
Update : I am not able to store and retrieve token (device token) and other children and also am able to log the message in firebase "Functions" tab , but still not able to push the notification to the device . I am testing it on emulator .Should I test it on real device ?
My Node.js code:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
var rootRef =
functions.database.ref('/notifications/{user_id}/{notification_id}');
exports.sendNotification = rootRef.onWrite(event => {
const user_id = event.params.user_id;
const notification_id = event.params.notification_id;
var request = event.data.val();
var payload = {
data: {
title : "New Message from ",
body: "userName has sent you message",
icon: "default",
}
};
console.log('We have a notification for device token: ', user_id );
console.log('Checking if getting inside the node -- ', request.user );
admin.messaging().sendToDevice(user_id, payload)
.then(function(response){
console.log('This was the notification Feature',response);
})
.catch(function(error){
console.log('Error sending message ',error);
})
})
MyFirebaseMEssagingService.java
public class MyFirebaseMessagingService extends FirebaseMessagingService
{
private static final String TAG = "FCM Service";
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// TODO: Handle FCM messages here.
// If the application is in the foreground handle both data and
notification messages here.
// Also if you intend on generating your own notifications as a result
of a received FCM
// message, here is where that should be initiated.
//remoteMessage.getNotification().getBody());
if(remoteMessage.getNotification()!=null){
Map<String,String> payload = remoteMessage.getData();
// String title =
remoteMessage.getNotification().getTitle();
// String message =
remoteMessage.getNotification().getBody();
// Log.d(TAG, "Message Notification Title : " + title);
// Log.d(TAG, "Message Notification Body: " + message);
System.out.println("Messaging Service : Title - " + payload.get("title")
+ " , body - " + payload.get("body"));
sendNotification(payload);
}
}
#Override
public void onDeletedMessages(){
}
private void sendNotification(Map<String,String> payload){
NotificationCompat.Builder builder = new
NotificationCompat.Builder(this);
builder.setSmallIcon(R.mipmap.ic_launcher);
builder.setContentTitle("Firebase Push
Notification"+payload.get("title"));
builder.setContentText("Notification Text : "+ payload.get("body"));
Intent intent = new Intent(this, ChatWindow.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addNextIntent(intent);
PendingIntent pendingIntent =
stackBuilder.getPendingIntent(0,PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager)
getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, builder.build());
}
}
FirebaseIDService.java:
public class FirebaseIDService extends FirebaseInstanceIdService {
private static final String TAG = "FirebaseIDService";
#Override
public void onTokenRefresh() {
// Get updated InstanceID token.
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
Log.d(TAG, "Refreshed token: " + refreshedToken);
DatabaseReference firebase ;//= new Firebase("https://materialtabs-
b5734.firebaseio.com//messages");
firebase =
FirebaseDatabase.getInstance().getReferenceFromUrl("https://materialtabs-
b5734.firebaseio.com//notifications/");
// TODO: Implement this method to send any registration to your app's
servers.
sendRegistrationToServer(refreshedToken);
}
/**
* Persist token to third-party servers.
*
* Modify this method to associate the user's FCM InstanceID token with any
server-side account
* maintained by your application.
*
* #param token The new token.
*/
private void sendRegistrationToServer(String token) {
// Add custom implementation, as needed.
System.out.println("Reading Token : "+ token);
}
}
And I am starting my 'MyFirebaseMessagingService.java' inside my MainActivity file in "onCreate()"
as "startService(new Intent(this, MyFirebaseMessagingService.class));"
Please help me. I think I am missing some minor details or it could be major, not sure !
For that, you need to store the firebase token of the recipient's device and then whenever you want to send the notification to the recipient you have to retrieve the token of the recipient's from the database and then you can send the notification using that token to the only recipient.
I am dealing with FCM messages and I have the following function:
public void onMessageReceived(final RemoteMessage remoteMessage)
{
final Map<String, String> data = remoteMessage.getData();
//...
}
For testing purposes, I have a Json file containing data- and I want to send that Json file from my test method to onMessagereceived() . Hence I need to initialize a RemoteMessage object with the Json file and pass this RemoteMessage object to the function. How do I initialize this?
My JSON file:
{
"data": {
"id" : "4422",
"type" : "1",
"imageUrl" : "https://image.freepik.com/free-vector/android-boot-logo_634639.jpg",
"smallTitle" : "DoJMA v2",
"smallSubTitle" : "Update now from Google Play Store",
"ticker" : "New update for DoJMA",
"contentInfo" : "",
"link" : "https://photo2.tinhte.vn/data/avatars/l/1885/1885712.jpg?1402763583",
"className" : "HomeActivity",
"page" : "2",
"bigTitle" : "DoJMA Android app version 2 released!",
"bigSubTitle" : "Hi folks! New DoJMA update is here! Major redesigning and improvements! This app was made by the Mobile App Club.They work really hard man...and get good products",
"bigSummaryText" : "Update now"
},
"registration_ids": ["dQYmpLUACXQ:APA91bGl-NoIMJ2_DcctF5-OA8ghyWuyrMfsz3uhlj1BySl6axkAsmv5y_7YGfpQQJ2E0lP_fTcxpHpZdkJzY1tbcWA36e78ooxC_b0a1PAank9gFIAUHVZkHKmZT70MPZosCgvRlVfq","dfLXnRI36qY:APA91bFyjLblijVIjGLCGWVeB1B0z5j_3TYqRytJ-8hvuUESpDlX59gWF3hU-I-kA4VrRCPpEVFWl18ZarnPjqxxtZgFkVxoLr77HRex27VN7Mh3xupWykmKq_nnVIlVzrODKwKI7ktM"]
}
you can test using Postman For Single User.
Send a notification with a JSON payload
URL: https://fcm.googleapis.com/fcm/send
Headers:
Authorization: key=<your-api-key>
Content-Type: application/json
Body (click on the 'raw' tab):
{
"to": "dQYmpLUACXQ:APA91bGl-NoIMJ2_DcctF5-OA8ghyWuyrMfsz3uhlj1BySl6axkAsmv5y_7YGfpQQJ2E0lP_fTcxpHpZdkJzY1tbcWA36e78ooxC_b0a1PAank9gFIAUHVZkHKmZT70MPZosCgvRlVfq",
"data": {
"id": "4422",
"type": "1",
"imageUrl": "https://image.freepik.com/free-vector/android-boot-logo_634639.jpg",
"smallTitle": "DoJMA v2",
"smallSubTitle": "Update now from Google Play Store",
"ticker": "New update for DoJMA",
"contentInfo": "",
"link": "https://photo2.tinhte.vn/data/avatars/l/1885/1885712.jpg?1402763583",
"className": "HomeActivity",
"page": "2",
"bigTitle": "DoJMA Android app version 2 released!",
"bigSubTitle": "Hi folks! New DoJMA update is here! Major redesigning and improvements! This app was made by the Mobile App Club.They work really hard man...and get good products",
"bigSummaryText": "Update now"
}
}
Source : https://firebase.google.com/docs/cloud-messaging/concept-options
TL;DR: Initializing a RemoteMessage object is not possible.
Attempting to access initialize a RemoteMessage from your own class would return an error:
'RemoteMessage(android.os.Bundle)' is not public in 'com.google.firebase.messaging.RemoteMessage'. Cannot be accessed from outside package.
I presume you're attempting to do this for testing purposes (stubbing?). In general (not gonna say best practice, since I'm not that entirely sure that it is best practice), it is advisable to have a separate method that accepts a specific value that you need. Referring to the official example (onMessageReceived) (removed some stuff):
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d(TAG, "From: " + remoteMessage.getFrom());
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
if (/* Check if data needs to be processed by long running job */ true) {
// For long-running tasks (10 seconds or more) use Firebase Job Dispatcher.
scheduleJob();
} else {
// Handle message within 10 seconds
handleNow();
}
}
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
}
// Also if you intend on generating your own notifications as a result of a received FCM
// message, here is where that should be initiated. See sendNotification method below.
}
/**
* Schedule a job using FirebaseJobDispatcher.
*/
private void scheduleJob() {
// [START dispatch_job]
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(this));
Job myJob = dispatcher.newJobBuilder()
.setService(MyJobService.class)
.setTag("my-job-tag")
.build();
dispatcher.schedule(myJob);
// [END dispatch_job]
}
/**
* Handle time allotted to BroadcastReceivers.
*/
private void handleNow() {
Log.d(TAG, "Short lived task is done.");
}
/**
* Create and show a simple notification containing the received FCM message.
*
* #param messageBody FCM message body received.
*/
private void sendNotification(String messageBody) {
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_stat_ic_notification)
.setContentTitle("FCM Message")
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
Focusing on the comment that mentions:
Also if you intend on generating your own notifications as a result of a received FCM message, here is where that should be initiated. See sendNotification method below.
This points out the sendNotification() method that accepts a String parameter. Depending on your case, instead of attempting to pass an initialized RemoteMessage (which sadly isn't possible, or at the very least is not advisable), you could simply pass an object that your method needs.
With that, you pretty much tested the method that handles the message without depending on an object that isn't a class you made in the first place.
PS: Some of my explanations can be confusing, but I hope this made sense.
I get the stacked notifications working if the app is opened but not when the app is closed. If the app is closed the icon is incorrect and the notifications are not stacked?
Here is my code:
notification = new NotificationCompat.Builder(this);
notification.setContentTitle(notifyFromName);
notification.setContentText(notifyMsg);
if (!msgIsProj) {
String followText = notifyMsg + " you!";
notification.setContentText(followText);
notification.setGroup(GROUP_KEY_FOLLOWERS);
Log.d(Constants.DEBUG, "SETTING AS FOLLOWers" + unread_notif);
} else {
notification.setContentText(notifyMsg + " " + notifyItemName);
notification.setGroup(GROUP_KEY_PROJECTS);
}
notification.setTicker(getString(R.string.titlePushNotify));
notification.setSmallIcon(R.drawable.ic_pushnotify);
//notification.setGroupSummary(true);
PendingIntent contentIntent = PendingIntent.getActivity(this, id,
newIntentMsg, PendingIntent.FLAG_CANCEL_CURRENT);
notification.setContentIntent(contentIntent);
notification.setAutoCancel(true);
manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if(notifyMsg != null && !notifyMsg.equals("")) {
manager.notify(id, notification.build());
unread_notif++;
Log.d(Constants.DEBUG, "PRE MORE NOTIF" + unread_notif);
if (unread_notif>1) {
Log.d(Constants.DEBUG, "GETTING MORE NOTIF" + unread_notif);
Notification summaryNotification = new NotificationCompat.Builder(this)
.setContentTitle("Your summary message")
.setSmallIcon(R.drawable.ic_pushnotify)
.setStyle(new NotificationCompat.InboxStyle()
.addLine("Details about your first notification")
.addLine("Details about your second notification")
.setBigContentTitle(Integer.toString(unread_notif)+" new notifications")
.setSummaryText("More details in app"))
.setGroup(GROUP_KEY_FOLLOWERS)
.setGroupSummary(true)
.build();
manager.notify(id++, summaryNotification);
}
}
For Firebase notifications,onMessageReceive is called when the app is in the foreground if you app if is background, the Google Services will take care of displaying your message.
Now notifications are handled using two ways:
- notification payload
- data payload
Notifications are managed when the app in the foreground using DATA Payload and using NOTIFICATION payload they are handled when the app in background or killed.
So, the solution for this is ditch the notification object from your message payload. Removing the notification object at backend will consider data payload object as default as you won't face this problem anymore.