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.
Related
Here is my code, When my app is running in foreground it opens targeted activity but when app is closed or in background, it doesn't opens targeted activity, please help me to solve this problem
I want that by clicking on notification will open targeted activity even app is running / closed.
public void onMessageReceived(RemoteMessage remoteMessage) {
session = new Session(this);
// if (session.getBscloggedin() || session.getAdploggedin()) {
// Log.d(TAG, "FROM:" + remoteMessage.getFrom());
//Check if the message contains data
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data: " + remoteMessage.getData());
}
//Check if the message contains notification
if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Mesage body:" + remoteMessage.getNotification().getBody());
sendNotification(remoteMessage.getNotification().getBody());
}
}
/**
* Dispay the notification
* #param body
*/
private void sendNotification(String body) {
//for CS101 announcement notification
if (body.contains("CS101")) {
Intent intent = new Intent(this, CS101noti.class);
intent.putExtra("body", body);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0/*Request code*/, intent, 0);
//Set sound of notifica tion
Uri notificationSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notifiBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("mine")
.setContentText(body)
.setAutoCancel(true)
.setSound(notificationSound)
.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0 /*ID of notification*/, notifiBuilder.build());
}
Request code should be unique.
Generally people share with us example like giving request code 0(zero). I am the one of copy/paste developer sometimes. But recently I faced with error using this line.
PendingIntent.getActivity(myContext, 0, myIntent, 0);
Whenever app receives notification, intent activity receives old data because of requestCode. Here is the documentation about that method.
Returns an existing or new PendingIntent matching the given
parameters.
So second parameter(requestCode) should be unique to intent. If you use same request code for every notification, activity will be receive old data. So your requestCode should be unique.
There is also another solution.Use PendingIntent.FLAG_UPDATE_CURRENT as flag. The doc says that;
If the described PendingIntent already exists, then keep it but
replace its extra data with what is in this new Intent.
onMessageReceived callback is not called when you receive notification messages in background. If you receive this type of message in background, you can only handle that in a launcher activity.
The solution would be to either change the backend so that it sends only data messages and you handle them internally, or write some routing code inside your launcher activity.
use "click_action" attribute from your backend from which you are sending push notifications. in that attribute value, you have to pass the fully qualified class path of activity, which should be opened when you click on that notification.for more reference refer handling firebase push
Intent intent = new Intent(this, CS101noti.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
....
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 guess it is hard to explain just by reading the title of this question. I am coding an app that gets ambient factors alerts (temperature, etc) sent by a known server to GCM, and then GCM sends it back to the phone. The whole GCM works well. The problem is when notifications arrive. It is thought to send notifications to the phone when an alert happens (a trigger). Then clicking on the alert launches the activity to display the alert. That is OK, but if there is 2 or more alerts on waiting to be clicked, it will only process one, ignoring the rest ("mensaje"). This is how my notification inside a class that extends extends GcmListenerService looks like.
public static void showAlerts(Context context, String mensaje)
{
Intent notificationIntent = new Intent(context.getApplicationContext(), MainActivity.class);
notificationIntent.putExtra("mensaje", mensaje);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_SINGLE_TOP);
Random r = new Random();
PendingIntent pendingIntent = PendingIntent.getActivity(context, r.nextInt(),
notificationIntent, 0);
NotificationManager notificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new NotificationCompat.Builder(context)
.setContentTitle(context.getString(R.string.app_name))
.setContentText("Nueva alerta recibida")
.setSmallIcon(R.drawable.termometrorojo)
.setNumber(UtilidadesGCM.num_notificaciones++)
.setOnlyAlertOnce(true)
.setContentIntent(pendingIntent)
.setWhen(System.currentTimeMillis())
.setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE)
.setDefaults(Notification.DEFAULT_LIGHTS)
.setAutoCancel(true).build();
notificationManager.notify(0, notification);
}
Then in MainActivity, I have the code to process this, and open the activity to display the alert
private final BroadcastReceiver mHandleMessageReceiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
String nuevaAlerta = intent.getExtras().getString("mensaje");
procesaAlerta(nuevaAlerta);
//mDisplay.append(nuevaAlerta + "\n");
}
};
public void procesaAlerta (String alerta)
{
Intent intent = new Intent(this, Alertas.class);
intent.putExtra("mensaje" , alerta);
startActivity(intent);
}
The Alertas class will parse the message fine and display it in its activity, but will only do that once. If there are more than 2 alerts stacked to be read, it only process one. If there is one, it works ok. Sorry if I odn't explain better, but it hard not showing all the code.
Thanks!
Try with writing this line
notificationManager.notify( new Random().nextInt(), notification);
instead of
notificationManager.notify(0, notification);
Your notification id is every time same so your last notification only work. Every new notification id is replaced by id 0. So i use random id instead of fixed id 0. I think above code will work for you
I have a service that shows a notification PendingIntent each time it receives a new GCM message. The problem is that the GCM messages can be of different kinds. And if many notifications leave unread, I want not to show them separately but in groups like:
you have 3 unread messages of type A
you have 2 unread messages of type B
you have 4 unread messages of type C
As far as I understand, to get this effect I need to have an access to unread/unseen notifications. Each time when I new notification comes I can check, if there is another unread message of this type, and then decide, whether I create a new notification or update an old one.
My question is: is there a way to see, which notifications are unseen and get access to them?
For any case this is my method to create a message; if an argument notificationId is 0 a new notification should be created. Else - updated.
private int sendNotification(String msg, Integer notificationId) {
Log.d(TAG, "sending message with text: "+msg);
mNotificationManager = (NotificationManager)
this.getSystemService(Context.NOTIFICATION_SERVICE);
Random random = new Random();
int notification_id = notificationId==0?random.nextInt(9999 - 1000) + 1000:notificationId;
RemoteViews remoteViews = new RemoteViews(getPackageName(),
R.layout.notification);
Intent intent = new Intent(this, MainActivity.class);
// Send data to NotificationView Class
intent.putExtra("text", msg);
PendingIntent pending= PendingIntent.getActivity(getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("escos")
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(msg))
.setContentText(msg);
mBuilder.setContentIntent(pending);
mBuilder.setContent(remoteViews);
remoteViews.setTextViewText(R.id.notiftext, msg);
remoteViews.setImageViewResource(R.id.notifim, R.drawable.ic_launcher);
Notification notification = mBuilder.build();
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notification.sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
mNotificationManager.notify(notification_id, notification);
return notification_id;
}
For different Notification strip (A, B, C etc.) in your status bar, use different NOTIFICATION_ID for building the Notification on basis of your defined type or collapse_key received from GCM.
For determining unread and read messages, use a local variable (counter) in Shared Preferences and increment it each time a specific type of Notification comes (on basis of defined type or collapse_key).
Then generate the Notification with that particular NOTIFICATION_ID as Notification with particular NOTIFICATION_ID can override each other. So You can override the previous Notification with Iterative Numbered text in New Notification.
As soon as user click on any Notification or particular Notification, clear the notification and reset the value of (counter) in Shared Preferences.
Edit1 : When you click on Notification with particular Pending Intent, then in that Activity use this code for removing all the Notifications generated from your app :
NotificationManager nMgr = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
try {
nMgr.cancelAll();
} catch (Exception e) {
e.printStackTrace();
}
Note : Do remember to add Try-Catch before you call cancelAll() as cancelAll() may not be supported by the device model and will generate
java.lang.SecurityException: Permission Denial
error.
Edit 2:
You can also use nMgr.cancel(NOTIFICATION_ID); to clear a specific notification, pass NOTIFICATION_ID to particular intent via extras and get the extras in that activity to cancel a particular notification.
And as you click on any notification it will be cleared from status bar unless you have not set .setAutoCancel(false) in your Notification Builder.
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);