My Android application receives push notification with some text messages.If I tap a push it redirects me to desired activity with latest push message (intent message) but I want to show my desired activity with corresponding push messages.
For example If I receives 10 push notifications and I tap 3rd notification, my code redirects me to the specified activity with 10th push notification's message, but I want to show 3rd intent push notification's message.
I know PendingIntent.FLAG_UPDATE_CURRENT replace the intent message, how can I redirect with corresponding message instead last message?
I have tried the following:
Intent intent = new Intent(this, TestActivity2.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.putExtra("uid", uid);
PendingIntent resultPendingIntent = PendingIntent.getActivity(this, 0,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
getApplicationContext());
Notification notification = mBuilder
.setSmallIcon(R.drawable.ic_launcher)
.setTicker(textMsg)
.setWhen(0)
.setAutoCancel(true)
.setContentTitle(textMsg)
.setStyle(
new NotificationCompat.BigTextStyle().bigText(textMsg))
.setContentIntent(resultPendingIntent).setContentText(textMsg)
.build();
NotificationManager notificationManager = (NotificationManager) getApplicationContext()
.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify((int) System.currentTimeMillis(),
notification);
Use FLAG_ONE_SHOT instead and change the second parameter in getActivity which is set to 0. This answer will make it clear.
You should Change the pendingIntend's content for Different Messages.
Here is the snippet from PendingIntent document.
"A PendingIntent itself is simply a reference to a token maintained by the system describing the original data used to retrieve it. This means that, even if its owning application's process is killed, the PendingIntent itself will remain usable from other processes that have been given it. If the creating application later re-retrieves the same kind of PendingIntent (same operation, same Intent action, data, categories, and components, and same flags), it will receive a PendingIntent representing the same token if that is still valid, and can thus call cancel() to remove it."
In simple words...try passing different id(Something like currentEpochTime) for each pendingIntent.
Related
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(this, channelId)
.setContentIntent(pendingIntent);
Does it mean that I can't jump to the mainActivity multiple times by repeatedly clicking this notification? Is pendingIntent.send() called internally when I clicks the notification? Does this flag become meaningless in the notifications?
PendingIntent.FLAG_ONE_SHOT means that the PendingIntent will be deleted after it is used once. Normally, a PendingIntent can hang around if there are other references to it in the system.
This flag can be used to prevent multiple uses of the PendingIntent, although my personal experience is that this flag generally causes more problems than it solves.
You asked:
Is pendingIntent.send() called internally when I clicks the notification?
Yes, that's basically what happens when you click on the UI element associated with the PendingIntent in the Notification.
When app receives message from GCM, it shows notification.
Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_event_white_24dp)
.setContentTitle("TheBriefPost")
.setContentText(message)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
When I click on notification, app opens activity but not restarting. What is the problem? How to solve it?
The answer should be related to the flags of the Intent/Pending Intent
According to PendingIntent in Official Docs
In the Pending Intent you sent a flag PendingIntent.FLAG_UPDATE_CURRENT
Flag indicating that if the described PendingIntent already exists, then keep it but replace its extra data with what is in this
new Intent.
I guess in your case you need to use PendingIntent.FLAG_CANCEL_CURRENT
Flag indicating that if the described PendingIntent already exists, the current one should be canceled before generating a new one.
Accodring to Activity in Official Docs
In the Activity you set the flag Intent.FLAG_ACTIVITY_SINGLE_TOP
If set, the activity will not be launched if it is already running at the top of the history stack.
I guess here you need to use Intent.FLAG_ACTIVITY_CLEAR_TASK
If set in an Intent passed to Context.startActivity(), this flag will cause any existing task that would be associated with the activity to be cleared before the activity is started.
app opens activity but not restarting
It should not be restarted. FLAG_ACTIVITY_SINGLE_TOP is "If set, the activity will not be launched if it is already running at the top of the history stack."
Why you want it restarted? To handle intent data? If so, implement onNewIntent() in your activity.
Please have a look at my Pending Intent code.
notificationIntent.putExtra("is_from_notification", true);
notificationIntent.putExtra("push_message_id", push_message_id);
notificationIntent.putExtra("open_target", open_target);
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent contentIntent = PendingIntent.getActivity(context,notifyID, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Notification noti = new NotificationCompat.Builder(context)
.setSmallIcon(icon_small)
.setTicker(message)
.setLargeIcon(largeIcon)
.setWhen(System.currentTimeMillis())
.setContentTitle(title)
.setContentText(message)
.setContentIntent(contentIntent)
.setAutoCancel(true).build();
NotificationManager notificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(notifyID, noti);
My Problem is that, where and how should I clear this pending intent. It stays as far as app is in recent tasks.
Just call notificationManager.cancel(notifyId);
Or
call notificationManager.cancelAll();
Hope , it helps.
To clear a pendingIntent use:
Edit:
PendingIntent.getActivity(context,notifyID, contentIntent, PendingIntent.FLAG_UPDATE_CURRENT).cancel();
Place this line somewhere in your code, where u want to cancel the pendingintent.
Note: The intent must have the same name and ID as your pendingIntent, in your case: notifyID and contentIntent
Note: A PendingIntent itself is simply a reference to a token maintained by the system describing the original data used to retrieve it. This means that, even if its owning application's process is killed, the PendingIntent itself will remain usable from other processes that have been given it. If the creating application later re-retrieves the same kind of PendingIntent (same operation, same Intent action, data, categories, and components, and same flags), it will receive a PendingIntent representing the same token if that is still valid, and can thus call cancel() to remove it.
cancel() - Cancel a currently active PendingIntent. Only the original application owning a PendingIntent can cancel it.
Should help u out
I am using the same notification id to show the notification of my app.
I am passing an object with the intent to launch the activity.
The issue is for same notification id, android caches the initial object which is passed along the intent.
So how can I make sure that the latest object is added in the intent.
Or how can I check if a notification with the id is not cleared in the notification panel and if it's there then I can delete the notification and create a new one.
Note :- I want to avoid the scenario to use new notification id as that keeps creating new notification without removing the older ones.
Use PendingIntent.FLAG_UPDATE_CURRENT in your Pending Intent like below
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
NotificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
call notificationManager.cancel(NOTIFICATION_ID); before calling notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build());
My question is a bit complicated so I am going to describe it briefly what I want to achieve. My application receives messages from GCM without any issue. When application is running and is visible to the user I am not displaying notification in Action Bar, I am displaying this message in dialog alert. I use BroadcastReceiver to achieve this.
The main issue is that, when app gets a few notifications in no time. When main activity is visible to the user, the first notification will be shown in dialog alert. And next will be placed in Action Bar as usual Android notifications. And at this moment user disposes the dialog alert and is going to choose a next notification from Action Bar. At this moment I am using in my CloudService (extends IntentService) intent with flag Intent.FLAG_ACTIVITY_CLEAR_TOP and also PendingIntent.FLAG_UPDATE_CURRENT flag for pendingIntent. PendingIntent is just the contentIntent for my NotificationCompat.Builder.
It works in this way that for each user click on the notification from Action Bar, my activity is refreshing (floats to the lower device edge and then floats from the upper edge with dialog alert with message - I am getting the extras from the intent in onResume method). This action is quite OK. Activity has only one instance in that case - I don't have to break through the few instances of the same activity while I have opened few notifications. But the big problem is that when user chooses any of the notifications in each case the last one will open in dialog alert. Activity seems to has the same intent despite of PendingIntent.FLAG_UPDATE_CURRENT.
There are two methods in CloudService which handle cloud messages:
private void showNotification(Bundle extras) {
notificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
String message = extras.getString(CloudMetaData.MESSAGE);
if (App.isMyActivityVisible() && !CloudMessageDialogFragment.isAttached()) {
sendBroadcast(message, NOTIFICATION_ID);
} else {
Intent intent = new Intent(this, MyParentActivity.class);
intent.putExtra(CloudMetaData.MESSAGE, message);
intent.putExtra(CloudMetaData.NOTIFICATION_ID, NOTIFICATION_ID);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setSmallIcon(R.drawable.ic_launcher);
builder.setContentTitle(getString(R.string.app_name));
builder.setStyle(new NotificationCompat.BigTextStyle().bigText(alert));
builder.setContentText(alert);
builder.setAutoCancel(true);
builder.setDefaults(Notification.DEFAULT_SOUND);
builder.setContentIntent(contentIntent);
notificationManager.notify(NOTIFICATION_ID, builder.build());
}
NOTIFICATION_ID++;
}
And method which send broadcast is just like that:
private void sendBroadcast(String message, int notificationId) {
Intent intent = new Intent();
intent.setAction(ACTION_FROM_CLOUD_SERVICE);
intent.putExtra(CloudMetaData.MESSAGE, message);
intent.putExtra(CloudMetaData.NOTIFICATION_ID, notificationId);
sendBroadcast(intent);
}
In which way can I achieve similar solution? But it is important for user of course to open notification from Action Bar and shown him its correct message.
EDIT
I have switched my dialog alert into the dialog activity. This is its definition in AndroidManifest:
<activity
android:name="com.myapp.activity.CloudMessageDialogActivity"
android:theme="#android:style/Theme.Dialog"
android:parentActivityName="com.myapp.activity.MyParentActivity"/>
But the result is still the same - when app receives a few notifications, clicking on one of them will open the dialog with the intent for the last received notification.
But the big problem is that when user chooses any of the notifications in each case the last one will open in dialog alert. Activity seems to has the same intent despite of PendingIntent.FLAG_UPDATE_CURRENT.
That's because you are using the same request code (i.e., 0) for all PendingIntents here:
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
By doing so, you are ultimately receiving the same intent, because the platform is failing to see the difference between the intents and delivering the same object everytime:
... it is important to know when two Intents are considered to be the same for purposes of retrieving a PendingIntent. A common mistake people make is to create multiple PendingIntent objects with Intents that only vary in their "extra" contents, expecting to get a different PendingIntent each time. This does not happen. The parts of the Intent that are used for matching are the same ones defined by Intent.filterEquals. If you use two Intent objects that are equivalent as per Intent.filterEquals, then you will get the same PendingIntent for both of them.
So, instead of a constant value, please use a unique request code. For e.g. change the above line with:
PendingIntent contentIntent = PendingIntent.getActivity(this, NOTIFICATION_ID,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
Hope this helps.