Google Play Services: how to check if there is currently "active" pending intent callback registered to location updates/activity recognition?
Following are the scenarios when a PendingIntent
is removed:
-
PendingIntent
can be removed explicitly by callingPendingIntent.cancel
, only by application which created it. From the docs:
Only the original application owning a PendingIntent can cancel it.
-
PendingIntent
, if inactive i.e. not being used by other application, is removed by the system when the application terminates. -
PendingIntent
, if active i.e. being used by other application, is removed by the system only when the application package is uninstalled.
Hence calling removeLocationUpdates
indicates the system that Google Location services no more references the PendingIntent
. It does not remove it from the system. So you will have to call cancel
on PendingIntent
to remove it, which is absolutely fine.
mLocationClient.removeLocationUpdates(pendingInent);
pendingIntent.cancel();
//Now check whether PendingIntent exists.
Intent locationUpdatesIntent = new Intent(context, LocationUpdatesIntentService.class);
PendingIntent pendingInent = PendingIntent.getService(context, 0, locationUpdatesIntent, PendingIntent.FLAG_NO_CREATE);
boolean isLocationUpdatesEnabled = (pendingIntent != null);
Additional info from the docs:
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.
Tal Kanel
Programmer with a deep knowledge and understanding when it comes to object oriented programming and object oriented design. got most of the experience from developing .NET framework and Java applications, by using the right architectures and design patterns per each. plans for now to continue make my way as a young developer who becomes every day more and more professional and experienced in the field. Specialties: Android applications development and design for smart-phones and tablets, supporting OS versions: 2.1 (Eclair), 2.2 (Froyo), 2.3.X (Gingerbread), 3.X.X (Honeycomb), 4.0 (Ice cream sandwich) Programming Languages: Java, C#, C++, C IDEs: Eclipse, IntelliJ, Visual Studio.
Updated on June 29, 2022Comments
-
Tal Kanel almost 2 years
my application perform periodic location updates and Activity recognition detection in background.
I'm doing that using the Google Play Services API's:
for example - to register to location updates, I provide pending intent to receive update:
mLocationClient.requestLocationUpdates(mLocationRequest, pendingInent);
to unregister to location update, I'm doing the following:
mLocationClient.removeLocationUpdates(pendingInent);
that's nice, and working great.
but how can I find out if there is currently a pendingIntent holding Intent to my application's component is currently registered in front of Google play services to receive location updates or not?
I notices that there is no API to check this, and the approach to check for pendingIntent existence seems not to work for API's against google play services - the pending intent stays exists even after I call the
removeLocationUpdates()
method.I know I can save state (to shared preferences) indicating if now I'm registered or not, but it's not the right solution, and will be "buggy" because it can happen that google play process went down, lost the pendingIntent, but my process will still think that the location updates are "active"..
same problem exactly exists for the activity recognition updates.
Just to make it clear, all I want to do is provide to the users of my application ability to know if my app is currently collecting data in background or not, and provide them a way to toggle between that. So if there is other way to do that in reliable way - I'll except it as an answer also
reliable way = knowing if currently the pending intent really registered in from of google play services...
- using
LocationListener
is not an option for me, because I must be able to receive updates event when my process is shout down - what's possible only usingPendingIntent
callback..
Thanks in advance.
UPDATE
this is the pendintIntent I provide to register and unregister to location updates:
Intent locationUpdatesIntent = new Intent(context, LocationUpdatesIntentService.class); PendingIntent pendingInent = PendingIntent.getService(context, 0, locationUpdatesIntent, PendingIntent.FLAG_UPDATE_CURRENT);
and this is how I'm trying to check (unsuccessfully) if it registered or not:
Intent locationUpdatesIntent = new Intent(context, LocationUpdatesIntentService.class); PendingIntent pendingInent = PendingIntent.getService(context, 0, locationUpdatesIntent, PendingIntent.FLAG_NO_CREATE); boolean isLocationUpdatesEnabled = (pendingIntent != null);
isLocationUpdatesEnabled
returns true event after I callremoveLocationUpdates()
- using
-
Tal Kanel over 9 yearsas I mentioned, my problem is not to display to the user, but to know if it really registered right now to updates. I don't want to use foreground service with LocationListener , because then if my process went down - google won't be able to wake my application. that's why I must user pendingIntent as a callback, and not a LocationListener callback.
-
danny117 over 9 yearsI thought I had everything covered ability to know if app is collecting data (notification) with a way provided to toggle (notification intent). Not collecting data no notification.
-
Tal Kanel over 9 yearsThank you very much for your answer. Besides the fact that I don't want to show to the user this undissmisable notification, this approach will not work for registration to location updates with pendingIntent callback, because pendingIntent can be still registred if my Service, and even my entire process is stopped
-
danny117 over 9 yearsSorry I couldn't help. Your going for pending intent so your process can be awakened by the location. That's a good reason. I'm just brain storming. You could putextra a sequential number in your pending intent. Store lastnumberreceived and lastnumbersent in static sequential variables and use the difference between the two to determine if intents have been lost.
-
Tal Kanel over 9 yearsThanks for sharing this ideas! I Appreciate it .. I'm hoping that there is more trivial and reliable/official straight forward solution without workaround tricks, and hope this bounty will bring this solution out
-
Tal Kanel over 9 yearsyour solution sounds good and promising, I'll try it as soon as I can, and came back to reward you if really adding pendingIntent.cancel() works as you desribed :->
-
Tal Kanel over 9 yearsjust checked it. looking great! as you said, calling cancel() seems to do the job! thank you very much for your answer!! I was already a bit skeptic there is really solution to that.. great to learn something new!