I have an application which requires frequent updates to the user's location, and location changes are relevant from a number of Activities within the app. As such, I created a LocationManager class that manages the LocationClient object, listens for updates, and broadcasts the location changes so that any Activity can handle updates as they need to.
However, I'm running into a problem where the updates seem to stop when I change Activities. I noticed the following message(s) appearing when changing Activities:
09-26 11:19:14.854: D/LocationManagerService(735): Location requesting stopped by an application
09-26 11:19:14.854: I/LocationManagerService(735): remove gps (pid 1332), disabled
After that point, it seems that my LocationClient stops getting any further updates. I can call removeLocationUpdates() and then requestLocationUpdates() to restart the request, but my original request no longer functions.
My only idea is that because the main Activity uses a MapFragment (SupportMapFragment, to be precise) which displays the user's location, when I switch Activities that MapFragment likely makes a call to suspend location updates. But that shouldn't affect my requests.
Does anybody have any insight?
Related
Is it possible to get location updates in android app after force stopping the app. In IOS it is possible to get the location update if we force stop the app, in similar manner is there any service which can provide location updates to killed app in android.
No, this isn't possible because the app's process has been killed and the registered locations listener has been removed. The system doesn't know who it should deliver the Location updates too. It the user force stops and app, by all means that means the app should stop what ever it's doing. But if the app is killed because of low memory pressures, then this is where using a STICKY service would come in handy. Simply register for location udpates inside of your Location Service and then inside of onStartCommmand return the START_STICKY constant to indicate to the system that if the service is killed (not force stopped), then the system should restart the service when memory pressure drops.
Yes, app could restart itself if you had some Geofence registered using BroadcastReceiver. Whenever device enter/leaves the Geofence app would receive the callback via BroadcastReceiver and in this callback you can reschedule location update listener.
But without Geofences location updates are not given to forced closed app.
Here you can know the basics about how to monitor geofences.
In a regular activity, it is mandatory to register to LocationManager when we want to receive updates, and remove updates sometime later, e.g. within onPause() for instance.
However, in a non-wakeful service, which can die at any given time, how can I assure that the LocationManager is not keeping the GPS on?
(I have no guarantee that the onDestroy method of the service will actually get called, and even a foreground Service might get killed...)
I am asking this since I couldn't find any warning regarding polling location within a service, but I suspect that it might be a bad habit overall.
You can keep a service that can run with a interval. Service also contains a instance of your LocationManager and your current activity Context.
When your activity is destroyed your Context will be set to null and you can stop locationrequest and service by itself.
Experimenting with forcing stop of Services, it seems that the location manager
is smart enough to turn off the GPS whenever a LocationListener is dead,
so case is closed...
I have registered a location listener, which will receive location updates using NETWORK_PROVIDER. The listener receives location updates if the activity is in foreground. If I leave the app, after some time it stops receiving location updates. Which is a bit weird... isn't it supposed to receive location update even if none of the activity is on the stack? The listener starts receiving location updates again if I go back to my app.
Or am I doing something wrong? What programming model is suggested to receive location updates even if none of my activity is not active (neither on foreground, nor on stack)?
There are some other way to receive location updates (using pending intent), but those do not trigger if I do not turn on GPS.
The activity in the background will be eventually destroyed, you don't have any guarantee that once stopped it will continue receiving location updates. Activities in Android are not supposed to be used like this.
You can use a service with a wake lock as suggested, but keeping the device awake will quickly drain your battery.
I recommend you this talk by Reto Meier (IO 2011), where he talks about different strategies to have a fresh location. Here is the code.
The app is handling location updates and sending the location back to a server. The app does not turn the location updates off. This is for devices permanently plugged into power, so battery is not an issue.
By design, will the location updates continue indefinitely, or will Android stop sending them at some point, for example if the app is pushed out of RAM?
If the location updates do stop, how do I request them in such a way that they will continue indefinitely?
Yes, if phone is not asleep, then user processes will run.
Register a LocationListener in a Service so that it's triggered when location changes. Even if your service is not running, system will start it and execute the registered method.
You should definitelly read the Deep Dive into Location blog for all angles of location handling in Android.
It depends on how you are running the app. As long as the app maintains focus, unless something catastrophic happens, it will continue to send updates. If the app loses focus, then you might run into issues, depending on how you implement the location updating. Either way, be sure to
Create an ASyncTask[docs] to handle the actual sending of updates, otherwise your app will be killed
If the app can lose focus, you can create a Service, and detach it from your application to keep it running in the background.
I have an android application. Based on the current geo location of user, I want to fetch some remote data in background and store it. My implementation is:
At specific interval a alarm fires up my service. Service uses an anonymous class to query current location and registers a locationListener callback. On call of onLocationChanged() I initiate the remote data fetch from server.
However once my service is done registering the location listener using anonymos class, it returns as expected; as it doesn't wait for callback to happen before finishing. Since callback takes some time and makes a call when service has already returned, it throws an error saying:
java.lang.RuntimeException: Handler{43e82510} sending message to a Handler on a dead thread
Which is quite understandable. One quick workaround for me now is that I can use getLastKnownLocation from locationManager as that doesn't respond back by callback; but what if I do want the latest location right now, in a service and not activity? How can I wait for callback to happen and stop my service from returning.
Also, at what point does lastKnownlocation gets updated? Everytime GPS registers a new location; does it update it? What I want to know is that if it's not latest can it still be closed to latest? As I didn't see an option in android emulator to configure the time period between subsequent updates.
Any help is much appreciated.
Cheers
but what if I do want the latest location right now, in a service and not activity?
Sorry, but that is not possible, in either a service or an activity. For example, if the GPS radio is off, and you are requesting location data from GPS, it will take tens of seconds just to get a fix, and that's if you are lucky. It might not get a fix at all.
How can I wait for callback to happen and stop my service from returning.
You don't. You do what you said you would do:
use getLastKnownLocation from locationManager as that doesn't respond back by callback
So, have your Service (which is hopefully an IntentService) check to see if getLastKnownLocation() happens to have a value. If it does, use it. Otherwise, registerLocationUpdates() using a PendingIntent that will pass control back to your IntentService. When you get that Intent, use the location and unregister for updates (assuming the alarm period is nice and long, like, say, once an hour).
Things get tricky if your alarm is a _WAKEUP alarm. You will then need to hold a WakeLock, so the device does not fall back asleep while you are trying to get a GPS fix. However, you need to release that WakeLock sometime, and if we cannot get a GPS fix...ummm...well, that's the tricky part. Trying to figure out a nice clean way of handling this, and implementing it as a reusable component (e.g., LocationAlarmService), is one of 18,000 items on my to-do list.
Also, at what point does lastKnownlocation gets updated? Everytime GPS registers a new location; does it > update it?
AFAIK, yes.