I am scheduling multiple intents to be send to a BroadcastReceiver.
The difference between every intent is the time when it will be received and extra data it contains.
Now I need to allow user to cancel specific alarms. According to AlarmManager.cancel() javadoc, it compares intents using filterEquals method:
http://developer.android.com/reference/android/content/Intent.html#filterEquals(android.content.Intent)
Now the problem is that according to filterEquals, all my intents are the same. Method checks against "action, data, type, class, and categories".
And unique data is either in intent extra bundle or as a time in AlarmManager.
I tried changing any of these parameters - for example using:
intent.setData(Uri.withAppendedPath(Uri.EMPTY, "some_unique_data"));
That would make every intent unique according to filterEquals method, but after changing Data to something like this, my intent does not reach BroadcastReceiver anymore.
What specific bit of data can I change to make every intent unique according to filterEquals and still receivable to my simple BroadcastReceiver?
Maybe I can modify my receiver in any way?
Ok, so I figured it out. As my every alarm has unique time and object ID, this is how I create my PendingIntent:
return PendingIntent.getBroadcast(context, time*100000+o.getId(), toFire, 0);
Now time is either 24 or 15 (24 hours before or 15 minutes before event I fire my alarm) and alarm data object contains unique ID. So I add both and specify it as a "requestCode" parameter in getBroadcast. That is enough to make unique intents based on same data.
Hope this helps anyone who has the same problem!
I ran across a similar problem for my app.
In my app, I used the SQLite DB to store details about each alarm, along with a unique ROW_ID.
So in my alarm listview, each row had a corresponding ROW_ID associated with it.
If the user clicks on a particular row, I just pass this ROW_ID to the method that performs the delete operation
Now, all my alarms were created with Intents which had their data part set as:
Uri.parse(Constants.INTENT_PRE + ROW_ID);
so in order to delete them, I create an Intent that has same data (as above, along with the unique ROW_ID) that was used while creating it.
Needless to say, from "action, data, type, class, and categories", only the "data" part is different for each of my existing PendingIntents.
Hope this helps!
Related
Is it possible to create two PendingIntents with the same ID ( let's say 889) and the same intent (but different bundle) and then when I cancel PendingIntent with ID 889 will it cancel it both ?
As far as i know, you cant do that.
The System uses the ID to identify the Intents. So if you get a result you never know which of your Intents being processed.
You have to use different IDs if you want to set a repeating alarm for 2 different days. Because if you'll use the same id for each then the notification you set the latest will override the previous one and hence you'll have lose one notification.
I have a fragment with a button that starts a BroadcastReceiver. This BroadcastReciever creates a notification after a time retrieved from the fragment. This part works.
However, when I press the button more than once, the existing broadcast receiver is overwritten. I don't want this as I want multiple notifications to be created.
Any solutions?
Thank you
I found the answer - The pending intent used in the alarm manager was not unique so it was overwritten each time I created another alarm. What I needed to do was create multiple alarms. This is done by adding a unique id to the 2nd parameter (argument?) of the pending intent.
See this answer for more details: https://stackoverflow.com/a/10090378/2442638
I am trying to cancel an alarm that was set last time my app was run. This alarm has a PendingIntent that was set with PendingIntent.getBroadcast and an inner Intent that contains some variables set by intent.putExtra. My question is this, I know that alarms can be canceled by calling alarmManager.cancel(pendingIntent) where pendingIntent is the same as the one used to set the alarm. But, if the variables placed into the intent are changed will the alarm still be canceled? For example, I set an alarm with intent.putExtra("Joe") where Joe is a contact name. Later my app is closed and when it is re-run I try and cancel the alarm for "Joe" but the user has changed the name of the contact to "Jones". Can I cancel the alarm without knowing the variables I put into the intent?
Thanks!
I think it should cancel the alaram anyway, even though some data is different. The cancel method says:
Any alarm, of any type, whose Intent matches this one (as defined by filterEquals(Intent)), will be canceled.
And filterEquals says:
Determine if two intents are the same for the purposes of intent resolution (filtering). That is, if their action, data, type, class, and categories are the same. This does not compare any extra data included in the intents.
Anyhow, I'd still test it myself.
According to this question (which references the documentation), anything you add using putExtra is not taken into account when checking if an intent is equal to another one.
It shouldn't matter if the extra data is changed.
I register a broadcastreceiver in AndroidMainfest.xml
And in my app, a function is that User can set a time and at this time the app will send a notification. I get the arguments User set ,and use alarmManager to set a task which will happened at the time user set.
But I find that GOOGLE API said that:
If there is already an alarm for this Intent scheduled (with the equality of two intents being defined by filterEquals(Intent)), then it will be removed and replaced by this one.
So if I want set two or more task,the Intent will be replaced , and at end I can only get one notification,it's not the result I want.
And then I found the intent was identified by action, data, type, class, and categories,
but I can't change action(the intent's action is the intent-filter's action was registred in the AndroidMainfest.xml ),but at the time that I change the other arguments I can't even receive a broadcast.
I thought there are four ways to solve this problem,but I only made one..
create lots of broadcastreceiver and register these in
AndroidMainfest.xml,and in this way I could change the intent's
action
register the broadcastreceiver in the program ,but I didn't
make it
use service + Timer class ..
To make two intent different without change action.
Any help will be appreciated!!
Intent intent = new Intent("aaa"); //there was a broadcastreceiver's intent-filter "aaa"
intent.putExtra("title", title);
intent.putExtra("table", "计划");
PendingIntent pi = PendingIntent.getBroadcast(Alarm.this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am = (AlarmManager)getSystemService(Alarm.ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+time, pi);
The code is in onClickListener{onClick(){}}
Instead of Broadcasting which is not letting you to set repeat alarm you can use the calendar Object and set the alarm at whatever desired time. Once the alarm gets ON, your code will run automatically and as many times you have set the alarm.
You can also take a help of the following tutorial. I am sure it will help you out somehow.
http://blog.mikesir87.io/2013/04/android-creating-an-alarm-with-alarmmanager/
I have a service that does database calls. The service receives a request with an intent, and when the database call is complete, it broadcasts an "update complete" intent indicating the completion of the call.
Sometimes the database is already populated with cached data, in which case I would like to immediately broadcast an "update complete" intent, indicating the activity should display the cached data, and then once the database has been updated fire another "update complete" intent indicating the activity should load the updated data.
The problem is that the second broadcast is never received by the activity. Is this because I'm re-using the same intent object that has already been fired?
Here's the code:
if (scheduleDatabase.populated()) {
intent.putExtra("fromCache", true);
getApplicationContext().sendBroadcast(intent);
}
scheduleDatabase.update();
intent.putExtra("fromCache", false);
getApplicationContext().sendBroadcast(intent);
An update:
If I comment out one of the intent broadcasts, the other one always fires and is received.
Also, if I create two intent objects with the same action string and fire them separately, only the first one is ever received by the activity. I'm not clear yet on whether the other gets fired but not received, or if it never fires at all.
It turns out that the problems I had with the intents were a symptom of a larger problem in a different area of my code. After fixing that problem, the intents began firing and receiving as I expected. So, to answer my own original question, yes it is possible to fire a single intent multiple times.
I ran into a similar problem. Yes the second intent is overwriting the first one. My workaround was to create a new Intent in my BroadcastReceiver. You have access to the same context, and can pass data in the extras.