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.
Related
I am running into a weird situation where I previous has created a pending intent for activity recognition updates
PendingIntent pendingIntent = PendingIntent.getService(mContext, getIntentID(), intent,
PendingIntent.FLAG_UPDATE_CURRENT);
my getIntentID code is
private static int getIntentID(){
if(intentID == 0)
return intentID = (int)(System.currentTimeMillis());
return intentID;
}
I did this because I wanted to be sure the id was unique everytime I stop and start my service.
However now when I am in my intentService reading the activities that are being sent I am pretty sure it is not my most recent pendingintent calling making the request. I believe it is from a previous one. However I don't know how to cancel it since I don't know the id from the previous one.
1. Why don't I know the previous id? well when I cancelled the updates via the remove updates I did use my getIntentID which I thought was working correctly however when I stopped my app, started it again but didnt launch the update() code for the activity recognition, I noticed I was still getting activities, when I used the debugger.
Here is my update request
ActivityRecognition.ActivityRecognitionApi.requestActivityUpdates(getActivityRecognitionClient(),
Utility.DETECTION_INTERVAL_TIME, pendingIntent())
Here is my remove code
ActivityRecognition.ActivityRecognitionApi.removeActivityUpdates(getActivityRecognitionClient(),
pendingIntent())
So my question is, is there a way to cancel all calls period to the activity recog. even if I dont know the pendingintent info?
So my question is, is there a way to cancel all calls period to the
activity recog.
If you refer the API of ActivityRecognitionApi it contains only two methods
https://developers.google.com/android/reference/com/google/android/gms/location/ActivityRecognitionApi
one for requesting updates
requestActivityUpdates(GoogleApiClient client, long detectionIntervalMillis, PendingIntent callbackIntent)
and
second one to remove updates
removeActivityUpdates(GoogleApiClient client, PendingIntent callbackIntent)
both methods need PendingIntent.
So obviously answer is NO.
Hope this will helps you.
Okay there seems to be no way to cancel the pending intents to the activity recog. LIke Nag stated however what I ended up doing was changing the name of my intentservice class and using it instead and keeping track of the pending Id info. Now I don't have any request coming in from previous calls
I have a Service that first creates a new Intent, and calls setAction('foo') on it. After this I call putExtra("key","value123"). Then I call PendingIntent.getService(this,999,intent,0) (no flags passed), and pass the pending intent to the AlarmManager.
But then before the alarm fires (or even after, it seems) I create another Intent and again call setAction('foo') on it, but don't set any extras.
Then I again pass it to PendingIntent.getService(this,999,intent,0). However, this time I call send() on the PendingIntent so as to receive the intent immediately.
What I observe is that the original extras are delivered with the new Intent. I appear to be able to do this over and over, and even if my app is killed, when I restart it, the extras are still there.
However, I don't see anything specifically in the documentation which says whether or not this is actually expected behavior. Is this a reliable method by which I can persist a small amount of data in RAM (only!) in case my app gets terminated? Currently I'm using file on a RAMdisk, but some devices apparently don't have such a thing.
This is the way PendingIntent works ;-)
The first call to PendingIntent.getService() creates a new PendingIntent with the requestCode set to 999 and the Intent set to ACTION="foo".
The second call to PendingIntent.getService) doesn't create a new PendingIntent. It just returns a token (reference) to the first PendingIntent. When you call send() on it, the original PendingIntent is sent.
The reason is that when you call PendingIntent.getService(), Android first tries to find a PendingIntent that matches the one you've specified. To determine if the Intent matches, it checks the ACTION, COMPONENT, DATA and it also checks for matching requestCode arguments. In your case, both calls to PendingIntent.getService() have the same requestCode and the Intents have the same ACTION. NOTE: "extras" in the Intent are not considered when determining if the Intents match.
If you always want to (re)use a single PendingIntent and just override the "extras" every time you use it, you can add the flag PendingIntent.FLAG_UPDATE_CURRENT to the call to PendingIntent.getService().
If you need to create several PendingIntents in parallel, with different "extras", you need to make sure to use a unique requestCode every time you call PendingIntent.getService().
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 have to do a task multiple times, and task is to broadcast an intent which will be intercepted by a different app. Lets say from App Sender to Receiver.
Receiving the intent in Receiver app is working fine, I have tested and guaranteed:
How I am doing this is,
I created a broadcast receiver in Sender app, with action SENDER_ACTION.
I create an intent with this action, set an extra with key frequency and value 4.
Get a PendingIntent from this and set an alarm of 10 sec, and fires this intent.
Idea is that sender app, will receive this intent, will fire the required intent to RECEIVER app, and then decreases the frequency value by 1, set it again to the intent, creates a pending intent and alarm and fires again.
So, ideally this counter of frequency should reach to 0 and process should terminate.
I can see that while setting the decreased value of frequency, it is happening (in logs), but when I receive its the same unchanged value.
I suspect that pending intent instance is kept on fired again and again.
Can some body please help me why is this happening?
If I had to guess -- which I do, since you provided no source code -- it is because you have not passed the right flags into getBroadcast() (or whatever factory method that you are using on PendingIntent to obtain the PendingIntent instance). Please bear in mind that Android caches PendingIntent objects and will reuse them, with their internal Intent extras unmodified, by default. Consider passing FLAG_UPDATE_CURRENT as the last parameter to getBroadcast().