android pendingintent sending duplicate data - android

My PendingIntent is working on time broadcast receiver. The problem is when I set my time and send first data it work successfully but when I send other data it again displays the first data and not the new one, below is my code.
All my mServiceIntenyt code is perfect but what is the error
mServiceIntent.putExtra("unique",lackmyData);
PendingIntent pintent = PendingIntent.getService(MessageActivity.this, 0, mServiceIntent, 0);
AlarmManager alarm = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarm.set(AlarmManager.RTC_WAKEUP,targetCal.getTimeInMillis(), pintent);

If you do not pass any flag then the PendingIntent ignores changes in extras when comparing Intent, causing the same old Intent to be spent again. You need to ask the PendingIntent to update the Intent as below:
PendingIntent pintent = PendingIntent.getService(MessageActivity.this,
0, mServiceIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Or in order to make sure your intent is unqiue based on extras, you may play with setData as below:
mServiceIntent.setData(Uri.parse(mServiceIntent.toUri(Intent.URI_INTENT_SCHEME)));

Related

Where are stored PendingIntents? Big trap of using

In my project i have tried out some possibilities and limitations of PendingIntent
So i have created some notification, that opens an activity by tapping
Intent intent = new Intent(this, NotificationActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.putExtra(Constants.INTENT_ITEM_NAME, "ItemName");
intent.putExtra(Constants.INTENT_ITEM_ID, itemId);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, CHANNEL_ID)
// properties set
;
notificationManager.notify(new Random().nextInt(10), notificationBuilder.build());
at begin was everithing good, until i have placed other item to show in NotificationActivity by tap on notification.
Here starts problems: in NotificationActivity was still showed previous item.
After some search it could be solved with:
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
BUT: if i have in same time many notifications, then i always see only last item, PendingIntent was created for.
Second parameter of getActivity is requestCode. So when i update solution to
PendingIntent pendingIntent = PendingIntent.getActivity(this, new Random().nextInt(1000), intent, PendingIntent.FLAG_UPDATE_CURRENT);
Then also many items are supported, and if for some reason the random makes me same numbers, the content in NotificationActivity will be the same.
So to 99% the solution is good, yes? NO
Again to first approach
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
If i set new extras for intent -> old extras will be readed.
In other words: by new Random().nextInt(1000) somewhere in the system of android device will be stored till 1000 PendingIntents for one of activities i have forever
So here are the questions:
Where all this PendingIntents stored?
How to clear it?
With How to clear it, i mean a way to remove all currently maked PendingIntents with some Random as requestCode, so that in clear way with only one notification at time i could use
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
with different items
PendingIntents are stored in non-persistent storage. When the device restarts, they are all gone.
Also, if you create a PendingIntent and put it in a Notification, once the Notification is gone (dismissed, opened, etc.) the PendingIntent is no longer in use and will be deleted.
Generally you should not use random numbers for the requestCode as this is no guarantee of uniqueness. You need to find a way to make your PendingIntent unique if you want to have many of them existing in parallel.

Automatically assign requestCodes to PendingIntent.getBroadcast (using AlarmManager)

I am essentially providing an interface to another application inside my android app. The client requested a system where he can either schedule a new local notification to be displayed at a specific time but also the ability to cancel all the local scheduled notifications. Is there a way that automatically assigns (practically unlimited) requestCodes(/ids) to PendingIntent objects while using them with AlarmManager?
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, requestCode, someNotificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
...
AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, futureTimeInMillis, pendingIntent);
I also want to be able to cancel all these pending intents without keeping track of the requestCodes:
for(int requestCode : somehowGetAllUsedRequestCodes){
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, requestCode, someNotificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
pendingIntent.cancel();
alarmManager.cancel(pendingIntent);
}
Is that thing even possible without manually keeping track of request codes?
You would need to keep track of the request codes in a database or whatever to be able to cancel them later. You can ensure the id is unique if you store the values in a database as well.

Cancelling a PendingIntent with unique requestCode

I'm having trouble with cancelling my pendingintent. Right now I create my pending intent like so:
Intent intent = new Intent(_self, NotificationService.class);
PendingIntent pi = PendingIntent.getService(this, task.getID, intent, 0);
task.getID is a unique int here. Later on in my app a user can edit a "task" and can decide to cancel the notifications (pendingintent). I try to cancel the pendingintent like so:
Intent intent = new Intent(_self, NotificationService.class); PendingIntent pIntent = PendingIntent.getBroadcast(_self, task.getID, intent , PendingIntent.FLAG_NO_CREATE);
pIntent.cancel();
But it doens't work! The notifications still shows up. In this case, task.getID refers to the unique id that was created before.
I've tried several different parameters, PendingIntent.FLAG_NO_CREATE returns null, FLAG_UPDATE_CURRENT doens't work and FLAG_CANCEL_CURRENT neither. Can somebody please help me with this and see what it is I am doing wrong?
You are trying to create a service with your PendingIntent and are trying to cancel a Broadcast. It will never work.
You need to getService with the PendingIntent you are trying to cancel.
You need to recreate your pending intent THE EXACT SAME WAY you created the first one when you want to cancel it.
take a look : Cancelling a PendingIntent

Delete AlarmManager Alarm ONLY for a Deleted Alarm

My app will have several alarms set simultaneously. Unfortunately, each alarm is being set with the same PendingIntent object. Here's the code I'm using to set the alarm:
//Use AlarmManager to trigger the notification/alarm.
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
//PendingIntent to launch activity when the alarm triggers.
Intent i = new Intent("com.testapp.DisplayNotification");
//Assign the reminder's primary key as the notification ID.
i.putExtra("Reminder_Name", editRemindMeTo.getText().toString());
i.putExtra("Reminder_Primary_Key", reminderPrimaryKey);
PendingIntent displayIntent = PendingIntent.getActivity(
getBaseContext(), 0, i, 0);
//Set the alarm to trigger.
alarmManager.set(AlarmManager.RTC_WAKEUP,
c.getTimeInMillis(), displayIntent);
I know that I can delete an alarm by using the following code:
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, MyPendingIntentService.class);
PendingIntent displayIntent = PendingIntent.getService(context, 0, i, 0);
alarmManager.cancel(displyIntent);
However, using this code will delete ALL my alarms (correct me if I'm wrong here). Is there a way to delete just the alarm that a user has deleted from the database? The alarm should be deleted from my app right after the user deletes an alarm entry in my app's database. I'm guessing that using different PendingIntent names would be the way to go, but I have no idea how to do this for each new alarm that a user creates. Thoughts on how to do this? Thanks!
See the same problem i faced here previously...
So the solution is to pass unique pending intent to the alarm service.. So here i how it can be done
PendingIntent pIntent = PendingIntent.getBroadcast(context, (int) alarm_id, intent, PendingIntent.FLAG_CANCEL_CURRENT);
here in the pending intent i have passed unique request id to the pending intent. Which you have to remember while cancelling the alarm.
So in my case what i have done to generate the unique id is put it in the database i have retrieved the id of the tables row and passed to the pending Intent.
So if you want to cancel the particular alarm you have to remember the same request id of the pending intent with the use of the same table entry...
I am sure it will work..
Use a different requestCode when registering each alarm. This is the second parameter of PendingIntent.getActivity/Service().
From the Android Documentation, cancel() will cancel all alarms with same pendingIntent. So the only way out is to create different pendingIntents. OR you could resort to scheduling repeating alarms as well, in this way you could use the same pendingIntents.

android pending intent notification problem

I have a alarm thing going on in my app and it launches a notification that then when pressed launched an activity.
The problem is that when I create more than one alarm then the activity launched from the notification gets the same extras as the first one. I think the problem is either with the intent i put in the pending intent or in the pending intent itself. I think I might need to put a flag on one of these but I dont know which one.
Intent showIntent =new Intent(context, notificationreceiver.class);
showIntent.putExtra("details", alarmname);
PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
showIntent, 0);
notification.setLatestEventInfo(context, "The event is imminent",
alarmname, contentIntent);
And the receiver of the notification
Bundle b = getIntent().getExtras();
String eventname = b.getString("details");
details.setText(eventname);
The "details" extra is the same to every the next time a notification happens instead of having the different value.
Until I set the intents I am sure that the correct value goes to the "details" so its a problem of getting the first intent everytime i press any notification.
How can I make it to launch the correct intents?
Hope I was as clear as i could
Thanks!
The way I solved that problem was by assigning a unique requestCode when you get the PendingIntent:
PendingIntent.getActivity(context, requestCode, showIntent, 0);
By doing so you are registering with the system different/unique intent instances.
Tip: A good way of making the requestCode unique would be by passing to it the current system time.
int requestID = (int) System.currentTimeMillis();
The problem is that when I create more
than one alarm then the activity
launched from the notification gets
the same extras as the first one.
Correct.
How can I make it to launch the
correct intents?
That depends on whether you have two alarms that will be registered at once, or not.
If not, you can use FLAG_ONE_SHOT or one of the other PendingIntent flags to have your second PendingIntent use the newer extras.
If, however, you will have two alarms registered at once, with different Intent extras, you will need to make the two Intents be more materially different, such that filterEquals() returns false when comparing the two. For example, you could call setData() or setAction() and provide different values for each Intent.
I had this issue in my app and just generated a random number to over come overriding notifications intent:
int random= new Random().nextInt();
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(
random,
PendingIntent.FLAG_UPDATE_CURRENT
);
I followed the solution provided by U-ramos and this worked for me
int requestID = (int) System.currentTimeMillis();
PendingIntent pendingIntent = PendingIntent.getActivity(this, requestID, showIntent, 0);
another solution:
use the PendingIntent.FLAG_UPDATE_CURRENT like this:
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,i, PendingIntent.FLAG_UPDATE_CURRENT);
this worked for me

Categories

Resources