Sending different parameters to pendingIntent through notification - android

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

Related

Send Notification ID through to activity for each notfication

I am seriously confused now, I have been reading several SE examples and they all seem to be doing slightly different things.
What i want to do: Is have a single Activity called NotificationActivity, when I click on a notification it must open that activity and provide the activity with a DeviceId. I don't want to override or update any pending activities. Each activity should be its own intent.
There should only be once instance of NotificationActivity.
here is the code I have so far:
MyGcmListenerService:
Intent intent = new Intent(this, NotificationActivity.class);
intent.setAction(Intent.ACTION_VIEW);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
//ADD My Extras
intent.putExtra(CommonBundleAttributes.CONNECTING_ACTIVITY_DEVICE_ID, content.DeviceId);
intent.putExtra(CommonBundleAttributes.CONNECTING_ACTIVITY_DEVICE_TYPE_ID, content.DeviceTypeId);
intent.putExtra(CommonBundleAttributes.CONNECTING_ACTIVITY_DEVICE_NAME, content.DeviceName);
//
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle(content.DeviceName)
.setContentText("Notification")
.setAutoCancel(true)
.setSound(ingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setGroup("Mi:" + content.DeviceId)
.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(NotificationID++, notificationBuilder.build());
and my NotificationActivity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_notification);
deviceId = getIntent().getExtras().getLong(CommonBundleAttributes.CONNECTING_ACTIVITY_DEVICE_ID, -1);
deviceName = getIntent().getExtras().getString(CommonBundleAttributes.CONNECTING_ACTIVITY_DEVICE_NAME, "");
deviceTypeId = getIntent().getExtras().getInt(CommonBundleAttributes.CONNECTING_ACTIVITY_DEVICE_TYPE_ID, 0);
What am I missing here/ I think I am getting mixed up with all the different flags and launcher types.
If there is already an NotificationActivty in memory, I want to close it and open a new one with the latest intent. If there are 3 notifications on the users phones, and they click on all three. it must open the NotificationActivty for the last clicked Notification.
There must be an issue with my pending intent?
In NotificationActivity, you collect int or long value using following code i.e.
notificationID = getIntent().getExtras().getInt(CommonBundleAttributes.CONNECTING_ACTIVITY_NOTIFICATIONID, 0);
then please pass a proper value with putExtra() i.e. if collect int then pass Integer.parseInt(content.DeviceId) or collect long then pass Long.parseLong(content.DeviceId)
hope it's helpful to you
In Notification class add this line
intent.putExtra(CommonBundleAttributes.CONNECTING_ACTIVITY_NOTIFICATIONID, NotificationID);
In NotificationActivity
notificationID = getIntent().getExtras().getInt(CommonBundleAttributes.CONNECTING_ACTIVITY_NOTIFICATIONID, 0);

Android GCM multiple push notifications with one icon in status bar

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);

How to use Intent correctly

I'm using Intents to save data and recover them in others places of my application. I have used them in others places, but now, it's not working as I hope.
public class GCMIntentService extends GCMBaseIntentService {
public GCMIntentService() {
super(ConstantsGCM.GCM_SENDER_ID);
}
#Override
protected void onMessage(Context context, Intent intent) {
...
String ns = Context.NOTIFICATION_SERVICE;
NotificationManager notManager = (NotificationManager) context.getSystemService(ns);
String room = intent.getExtras().getString(ConstantsGCM.GCM_ROOM);
Intent notIntent;
PendingIntent contIntent;
Notification notif;
notif = new Notification(icon, textStatus, time);
notIntent = new Intent(contexto,RoomsActivity2.class);
Bundle b2 = new Bundle();
b2.putString(ConstantsRooms.ROOM, room);
notIntent.putExtras(b2);
contIntent = PendingIntent.getActivity(contexto, 0, notIntent, 0);
notif.setLatestEventInfo(contexto, tittle, description, contIntent);
notif.flags |= Notification.FLAG_AUTO_CANCEL;
notManager.notify((int)(Math.random()*1000), notif);
This code is executed when a notification is coming. When I click this notification, it's executed the Activity RoomsActivities2.class. Here, I just call this code:
public String getMessageString(String cod){
String result = "";
bundle = getIntent().getExtras();
if (bundle != null){
result = bundle.getString(cod);
}
return result;
}
But, I didn't get the last data saved in the Intent. What's it wrong? I guess that I'm not using it correctly. Why can't I get the data from the activity?
What I think that it's happening it's:
The application gets a lot of notifications, the first one works right. But, if I keep getting more notifications, the data isn't override and I always get the first one although when I debug the code, I'm setting the another data.
OK, it's been a while since I've worked with pending intents, but I remember two things:
replace:
contIntent = PendingIntent.getActivity(contexto, 0, notIntent, 0);
with:
contIntent = PendingIntent.getActivity(contexto, 0, notIntent, PendingIntent.FLAG_UPDATE_CURRENT);
That will keep the bundle around.
BUT that flag will override any existing pending intents with the newest one, you might not want that.
If you have multiple pending intents from the same context with the same intent (but different bundles!), you can use the 2nd parameter.
contIntent = PendingIntent.getActivity(contexto, requestCode, notIntent, PendingIntent.FLAG_UPDATE_CURRENT);
as long as every pending intent has a unique requestCode, and even though the google dev's docs say the parameter isn't used, it actually does serve a purpose for identifying pending intent and allows duplicates with different bundles.

Opening an Activity from a notification -Android

I am using GCMBaseIntentService in my service class which extends GCMBaseIntentService I override the method onMessage(Context,Intent).
The code goes here :
protected void onMessage(Context context, Intent intent) {
Log.i(TAG, "Received message");
//String message = getString(R.string.gcm_message);
String id=intent.getExtras().getString("event_id");
String message=intent.getExtras().getString("title");
String eventname=intent.getExtras().getString("event_name");
generateNotification(getApplicationContext(), id, message, eventname);
}
private static void generateNotification(Context context, String id, String message, String eventname)
{
int icon = R.drawable.ic_stat_gcm;
long when = System.currentTimeMillis();
NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(icon, message, when);
//new intent
Intent notificationIntent = new Intent(context, EventDescription.class);
notificationIntent.putExtra("event_id", id);//need this id in the eventdescription activity
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent intent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
notification.setLatestEventInfo(context, eventname, message, intent);
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notificationManager.notify(0, notification);
}
The problem is that, while I click this notification and in the Eventdescription activity and extract the extras from intent and print the ID. It shows the correct value only the first time, after that for every notification it just shows the 1st value all the time. Please help!
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.notificationsfinal);
start=1;
end=15;
next=(Button)findViewById(R.id.nextbtn);
prev=(Button)findViewById(R.id.prevbtn);
statusview=(TextView)findViewById(R.id.status);
notification_list_view=(ListView)findViewById(R.id.not_listview);
updatestatus();
getNotifications();
}
private void getNotifications()
{
eventnotifierapp app=(eventnotifierapp)getApplication();
id=getIntent().getExtras().getString("event_id");
db=new MyDB(this);
}
This is my EventDescription activity where i am retreiving this event_id
Try this
PendingIntent intent = PendingIntent.getActivity(context, **uniqueKey**, notificationIntent, 0);
Please note requestCode of the getActivity of Pending intent should be unique.So just pass
unique value for every notification.You can put time stamp or even the id which you receive
from the server. I have tried this and this works.Do share your feedback
Your subsequent Intents aren't different enough, so they're being recycled. Specifically, changing the extras doesn't make a distinct Intent from the perspective of the system.
The docs for Intent.filterEquals explain that you will need to change one or more of: action, data, type, class, and categories. One approach, therefore, is to stick some distinguishing information (in your case the event_id) into the data URI; you don't have to use this URI for anything but it ensures that your intents will be distinct.
There's more info in this related question.

Android getIntent() returns the first intent

I have developed an application to download a video file and store it in the SD card. In the process I also update the progress and status of the download as a status bar notification using the NotificationManager.
My class called the DownloadTask.java extends the AsyncTask. So here I update the progress using the onProgressUpdate() method where in I use the NotificationManager for the purpose. Everything works like a charm except, on completion of download I want to click the notification to open the specific video file. So this is what i have done:
mNotificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
int icon = android.R.drawable.stat_sys_download_done;
long when = System.currentTimeMillis();
mNotification = new Notification(icon, "", when);
mContentTitle_complete = mContext.getString(R.string.download_complete);
notificationIntent = new Intent(mContext,OpenDownloadedVideo.class);
notificationIntent.putExtra("fileName", file);
mContentIntent = PendingIntent.getActivity(mContext, 0, notificationIntent, 0);
mNotification.setLatestEventInfo(mContext, file, mContentTitle_complete, mContentIntent);
mNotification.flags = Notification.FLAG_AUTO_CANCEL;
mNotificationManager.notify(NOTIFICATION_ID, mNotification);
Note that the fileName and NOTIFICATION_ID are unique in my case.
The Activity OpenDownloadedVideo.java opens the file by:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
fileName = getIntent().getExtras().getString("fileName");
Intent i = new Intent(Intent.ACTION_VIEW);
File videoFileToPlay = new File(Environment.getExternalStorageDirectory()+"/MyFolder"+"/"+fileName);
i.setDataAndType(Uri.fromFile(videoFileToPlay), "video/*");
startActivity(i);
finish();
} catch(Exception e) {
//
}
}
So when I download a video for the first time and click on the notification the appropriate video file will be opened. However next time when I download another video, and click on the notification the first file which was downloaded will be opened again.
This is because getIntent inside OpenDownloadedVideo returns the first Intent created and not the latest. How can I correct this?
Also, please note that the problem scenario exists when I download more than one video, e.g. if I download five different video files and there are five notifications in the status bar. The same file will be opened each time a notification is clicked.
/**
* Override super.onNewIntent() so that calls to getIntent() will return the
* latest intent that was used to start this Activity rather than the first
* intent.
*/
#Override
public void onNewIntent(Intent intent){
super.onNewIntent(intent); // Propagate.
setIntent(intent); // Passing the new intent to setIntent() means this new intent will be the one returned whenever getIntent() is called.
}
actually you just need create PendingIntent with PendingIntent.FLAG_UPDATE_CURRENT ,like this:
mContentIntent = PendingIntent.getActivity(mContext, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
From the Android Activity.onNewIntent() documentation
Note that getIntent() still returns the original Intent. You can use setIntent(Intent) to update it to this new Intent.
So when you get the new Intent, you need to explicitly set it as the activity intent.
#Alex and #Codinguser, thank you for your replies. Much appreciated. However I found a different answer that worked for me. When creating a PendingIntent for the Intent pass a unique value to it. In my case I was doing this:
mContentIntent = PendingIntent.getActivity(mContext, 0, notificationIntent, 0);
but now I'm using NOTIFICATION_ID since it was unique. I've changed the above call to:
mContentIntent = PendingIntent.getActivity(mContext, NOTIFICATION_ID,
notificationIntent, 0);
That's all and it works.
I found some information on it in the question
Mulitple Instances of Pending Intent
What if you make your OpenDownloadedVideo activity SINGLE_TOP and override onNewIntent?
in the activity you're intent is launching.
Add (override) the following function:
#Override
protected void onNewIntent(final Intent intent) {
super.onNewIntent(intent);
this.setIntent(intent);
}

Categories

Resources