My app wants to bundle multiple push notifications in one icon in the status bar.
When clicking on the icon, the multiple notifications should be received by the app to show them in listview mode.
There are already some entries in stackoverflow which come close to what I want to obtain and it did give me a better insight in handling pending intents and notification flags but they didn´t solve completely my problem.
First step: Creating the notification:
Following some entries in stackoverflow, I made the following assumptions:
One notification ID (notifyID) to obtain only one icon in status bar
A unique requestId parameter in the pending intent to differentiate between the various notifications requests within the same notification ID
FLAG_ACTIVITY_NEW_TASK used in notification intent and FLAG_UPDATE_CURRENT used in pending intent
Notification notification;
int icon = R.drawable.ic_launcher;
int smallIcon = R.drawable.ic_launcher;
int notifyID = 1;
long when = System.currentTimeMillis();
int requestID = (int) System.currentTimeMillis();
NotificationManager notificationManager = (NotificationManager)
context.getSystemService(Context.NOTIFICATION_SERVICE);
Intent notificationIntent = new Intent(context, NewActivity.class);
notificationIntent.putExtra("new_message", message);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent contentIntent = PendingIntent.getActivity(context, requestID,
notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
int numMessages = 1;
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context);
mBuilder.setNumber(numMessages)
.setSmallIcon(smallIcon)
.setAutoCancel(true)
.setContentTitle("You have " +numMessages+ " new messages.")
.setContentText(message)
.setWhen(when)
.setContentIntent(contentIntent)
.setDefaults(Notification.DEFAULT_LIGHTS | Notification.DEFAULT_VIBRATE);
notificationManager.notify(notifyID, mBuilder.build());
The way I see it, each time a notification is sent by GCM, my app generates a notification to send to the notification manager taking into account the previous assumptions.
First problem: if I want to notify the user with the number of pending notifcations left, how can I get track of the previous number of sent notifications? Do I have to store it in storage media?
Second step: Tapping the notification icon in status bar containing multiple notifications:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
showNotifications();
}
public void onResume() {
showNotifications();
super.onResume();
}
public void showNotifications() {
if (getIntent().getExtras() != null) {
if (getIntent().getExtras().getString("new_message") != null) {
String newMessage = getIntent().getExtras().getString("new_message");
if (!newMessage.equals("")) {
handleMessage(newMessage);
getIntent().removeExtra("new_message);
}
}
}
}
public void onNewIntent(Intent intent) {
Bundle extras = intent.getExtras();
if (extras != null) {
if (intent.getExtras().getString("new_message") != null) {
String newMessage = intent.getExtras().getString("new_message");
if (!newMessage.equals("")) {
intent.removeExtra("new_message"); }
}
}
}
}
Second problem: I only receive the last notification sent. It seems to be that differentiating the pending intents with requestId didn´t do the trick. Also I thought that the different pending intents related to one notification icon would be handled by onNewIntent...
A possible solution that I was thinking about is to save incoming notifications from GCM in storage and get them on tapping the status bar icon, but for sure this cannot be the way Google meant it to be…
¿Any help?
for second step try this: PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
Related
I am implementing push notifications on Android. The problem comes when I want to update my notifications. I would like to stack up notifications so that if a notification is visible I simply update it and do this.
mNotifyBuilder.setContentText(currentText)
.setNumber(++numMessages);
But every time I receive a notification ++numMessages is set back to 0 before being summed up. I need it to sum up from where it was left if there is a notification on the screen. Here is the code:
//Class is extending GcmListenerService
public class GCMPushReceiverService extends GcmListenerService {
//variables for message 1,on receiving job applications
String name;
String lastname;
String jobtypename;
String kasualjobdatetimepostedat;
String kasualjobcount;
int numMessages;
//This method will be called on every new message received
#Override
public void onMessageReceived(String from, Bundle data) {
//Getting the message from the bundle
String message = data.getString("message");
String messageid = data.getString("messageid");
if(messageid.compareTo("1")==0){
name=data.getString("firstname");
lastname=data.getString("lastname");
jobtypename=data.getString("jobtype");
kasualjobdatetimepostedat=data.getString("kasualjobdatetimepostedat");
}
else
{
kasualjobcount=data.getString("kasualjobcount");
}
//Displaying a notification with the message
sendNotification(message, messageid);
}
//This method is generating a notification and displaying the notification
private void sendNotification(String message,String messageid) {
Intent intent = new Intent(this, Main_Activity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
int requestCode = 0;
PendingIntent pendingIntent = PendingIntent.getActivity(this, requestCode, intent, PendingIntent.FLAG_ONE_SHOT);
Uri sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Log.d("notificationid", String.valueOf(messageid));
if(messageid.compareTo("2")==0) {//messages to do with jobs around 2
String messageionkasualjobscount="There are "+kasualjobcount+" new jobs around you";
NotificationCompat.Builder noBuilder = new NotificationCompat.Builder(this);
noBuilder.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("KasualJobs2")
.setContentText(messageionkasualjobscount)
.setAutoCancel(true)
.setContentIntent(pendingIntent).setSound(Settings.System.DEFAULT_NOTIFICATION_URI);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(2, noBuilder.build()); //messageid = ID of notification
}else{//messages to with users applying for job 1
String messageionkasualjobapplication=name+ " "+ lastname+" has applied for the "+jobtypename+" you posted on "+kasualjobdatetimepostedat;
NotificationCompat.Builder noBuilder = new NotificationCompat.Builder(this);
noBuilder.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("KasualJobs1")
.setContentText(messageionkasualjobapplication)
.setAutoCancel(true).setNumber(++numMessages)
.setContentIntent(pendingIntent).setSound(Settings.System.DEFAULT_NOTIFICATION_URI);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(1, noBuilder.build()); //messageid = ID of notification
}
}
}
In general, you should not expect your field values to persist across multiple calls to onMessageReceived, since the service might have been killed by the OS to free up memory.
I suggest storing your messages in a database. Whenever you receive a new message, insert it into the database, and delete it when the user reads it. Then you can easily query how many unread messages there are.
I suggest you to use FCM instead of GCM (because GCM will no longer used).
And to update notifications use sqlite database for storing the notifications with date & time. clear the notification when read & also delete it from database.
I'm trying to send notifications with FCM, it works as expected but i'm facing two different behaviours that I want to deal with because I'm using bigtextstyle and an action:
First case: App in foreground,
onReceiveMessage works as expected and notification is shown correctly
Second Case: App killed or in background,
the documentation says that messages are not handled in the onReceiveMessage event, and the layout of the notification is not the bigtextstyle one:
I tried to find a way for showing the desired layout, but nothing is working, they said that data payload is delivered in the extras of the intent of the launcher Activity!
So, what I want, is to show the same notification layout in the two cases, because some time I use the notification to trigger a call or to open a link in a browser not to open the app itself.
I sent my messages from Firebase Console as shown :
and here's the function that notify :
private void notifyMe(RemoteMessage rm){
String title = "";
String body = "";
String phone = "";
String link = "";
long time = System.currentTimeMillis();
Intent iCall;
PendingIntent pintCall = null;
Intent notificationIntent = null;
NotificationManager notificationManager;
notificationManager = (NotificationManager)FirebaseMessagingService.this.getSystemService(Context.NOTIFICATION_SERVICE);
if (rm.getNotification() != null) {
title = rm.getNotification().getTitle();
body = rm.getNotification().getBody();
}
if (rm.getData().size() > 0) {
phone = rm.getData().get("phone");
link = rm.getData().get("link");
if(link.contains("http://")){
notificationIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(link));
}else{
notificationIntent = new Intent(FirebaseMessagingService.this, MainActivity.class);
}
if(phone.equalsIgnoreCase("")){
iCall = new Intent(Intent.ACTION_DIAL, Uri.fromParts("tel", phone, null));
pintCall = PendingIntent.getActivity(FirebaseMessagingService.this, 0, iCall, PendingIntent.FLAG_UPDATE_CURRENT);
}
}
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK );
PendingIntent pint = PendingIntent.getActivity(FirebaseMessagingService.this, 0, notificationIntent, 0);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(title)
.setContentText(body)
.setWhen(time)
.setPriority(Notification.PRIORITY_MAX)
.setDefaults(Notification.DEFAULT_LIGHTS| Notification.DEFAULT_SOUND)
.setContentIntent(pint);
NotificationCompat.BigTextStyle bigtext = new NotificationCompat.BigTextStyle();
bigtext.setBigContentTitle(title);
bigtext.bigText(body);
mBuilder.setStyle(bigtext);
if(!phone.equalsIgnoreCase("")){
mBuilder.addAction(android.R.drawable.ic_menu_call, "Call me!", pintCall);
}
notificationManager.notify(0, mBuilder.build());
}
Someone has a path on how to do this ?
Thanks.
The Firebase Notifications console sends so-called "notification messages". When your app is not in the foreground, these notifications messages are handled by the system itself and automatically displayed in the notification tray in the format you're seeing. When the user clicks this notification, the app is activated.
To ensure the message always gets delivered to your onReceiveMessage method, use "data messages".
For a great explanation, see the documentation on the different message types.
Hi I am working in chat app where if person A sends request and if person B is in idle state i am displaying in notification as you have received a notification from person A and if person B not responded for 60 seconds,I clear the notification and call missed notification. But I need to display total number of missed chats notifcation if in idle state and if user see the missed chat and clears the notification and if next notification comes, it should display count as 1 similar to phone missed call. How to proceed?Here is code which I done. I need to display count in notification.
Here is code which I tried.
notBuilder.setContentIntent(pendingIntent);
notificationManager.notify(notificationID, notBuilder.build());
clearPendingNotification(notificationID);
}
private void clearPendingNotification(final int id) {
try {
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
#Override
public void run() {
NotificationManager mManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mManager.cancel(id);
missedNotification("test");
}
}, Constants.CHAT_REQ_TIME);
} catch (Exception e) {
LogMessage.e(Constants.TAG, e);
}
private void missedNotification(String message) {
Intent notificationIntent = null;
Context context = getApplicationContext();
int notificationID = new Random().nextInt();
NotificationManager notificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder notBuilder = new NotificationCompat.Builder(
context);
notBuilder.setSmallIcon(R.drawable.ic_notification);
notBuilder.setContentTitle("Missed chat request");
notBuilder.setContentText("You have" + " " + message + " "
+ "missed chat request from customers");
notBuilder.setAutoCancel(true);
notBuilder.setDefaults(Notification.DEFAULT_SOUND);
notificationIntent = new Intent(context, ActivityExpertDasboard.class);
notificationIntent.putExtra(Constants.IS_CHAT_REQUEST, true);
notificationIntent
.putExtra(Constants.KEY_NOFICATION_ID, notificationID);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
notificationIntent.putExtra(Constants.CHAT_USER_NAME, msgTo);
PendingIntent pendingIntent = PendingIntent
.getActivity(context, notificationID, notificationIntent,
PendingIntent.FLAG_UPDATE_CURRENT
| PendingIntent.FLAG_ONE_SHOT);
notBuilder.setContentIntent(pendingIntent);
notificationManager.notify(notificationID, notBuilder.build());
}
}
Thanks in advance.
Adding to #Karakuri's answer you also need to check that the Activity is Visible means its in foreground. Since you'll be receiving notification from GCM, you need to open connection to that service and let service know that activity is visible. When activity is Visible do not post notification instead pass data from service to activity or insert silently in db and send some broadcast to activity indicating that new data has been updated in db please query for latest messages.
Store the number of missed notifications somewhere (like SharedPreferences). You can keep incrementing this value until the user clicks on (or swipes away) a notification. Use setDeleteIntent() to call a component that will reset this stored value when the notification is canceled.
I'm using the Phonegap plugin "PushPlugin" (https://github.com/phonegap-build/PushPlugin) together with Phonegap 2.9.0 for iOS and Android. For iOS everything works as expected: A notification arrives, I click on the notification and the app is started.
On Android, we distinguish between two cases: The app is in foreground (active) or in background (closed or just not actively used). When I receive a notification while in foreground, the plugin works. When I receive a notification while in background, the plugin creates a notification in the notification bar, but tapping on the notification does not open my app.
The relevant code that should open my app is:
// Gets called when the notification arrives
protected void onMessage(Context context, Intent intent) {
Log.d(TAG, "onMessage - context: " + context);
// Extract the payload from the message
final Bundle extras = intent.getExtras();
if (extras != null)
{
final boolean foreground = this.isInForeground();
extras.putBoolean("foreground", foreground);
if (foreground)
PushPlugin.sendExtras(extras);
else
createNotification(context, extras);
}
}
// This creates the notification in the notification bar, but a click on the notification does not open my app
public void createNotification(Context context, Bundle extras)
{
final NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
final String appName = getAppName(this);
final Intent notificationIntent = new Intent(this, PushHandlerActivity.class);
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
notificationIntent.putExtra("pushBundle", extras);
final PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
final NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(context)
.setSmallIcon(context.getApplicationInfo().icon)
.setWhen(System.currentTimeMillis())
.setContentTitle(appName)
.setTicker(appName)
.setContentIntent(contentIntent);
final String message = extras.getString("message");
if (message != null) {
mBuilder.setContentText(message);
} else {
mBuilder.setContentText("<missing message content>");
}
final String msgcnt = extras.getString("msgcnt");
if (msgcnt != null) {
mBuilder.setNumber(Integer.parseInt(msgcnt));
}
mNotificationManager.notify(appName, NOTIFICATION_ID, mBuilder.build());
tryPlayRingtone();
}
I thought it was a problem similar to https://github.com/phonegap-build/PushPlugin/issues/35#issuecomment-24722796, but it was simply an issue with the Android Manifest: The PushPlugin activity was entered with a wrong package.
My target: download files in parallel, and when file downloads complete, I get notifications.
Those notifications are suppose to launch an activity when you click on it which gets unique parameters through putExtra.
The problem is that I can't have different values in each launch of that activity.
Each time the activity, which is being launched through the notification bar, launches it destroys the extra of the ones which haven't been launched yet (the ones that still appear on the notification bar).
How do I keep all my notifications with their own parameters?
Here is my code:
if (messagesManager == null)
{
messagesManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
}
notification = new Notification(R.drawable.icon, message, System.currentTimeMillis());
// for launch activity
Intent intent = new Intent(context, DialogActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.putExtra("fileName", fileName); //- this is where i put my extra's!!
intent.putExtra("onSdcard", onSdcard);
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
notification.setLatestEventInfo(context, "DownloadManager", message, contentIntent);
notification.flags = notification.FLAG_AUTO_CANCEL;
int noticeId = generateNotificationId(requestId);
messagesManager.notify(noticeId, notification);
Now this is the dialog activity:
protected void onCreate(Bundle savedInstanceState)
{
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
Intent i = getIntent();
boolean onSdcard = i.getBooleanExtra("onSdcard", true);
String fileName = i.getStringExtra("fileName");
...
}
I tried to use this technique as it was written in another post here, but it didn't work.
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
Please check the linked duplicate,
you need two things
you need to add an action string
the action string must be unique, probably a timestamp added to it would be good