I'm creating an app which tracks the location through FusedLocationProviderApi in a Foreground Service.
When I create LocationRequest with PRIORITY_BALANCED_POWER_ACCURACY and start listening for location updates, to my surprise GPS fires up ( Location in the phone settings is set to High Accuracy). I get the location almost immediately (through wifi/cell sources I guess), but as I'm indoors I can't get a GPS fix and it just keeps on trying without end...
Even though I didn't ask for PRIORITY_HIGH_ACCURACY I get hit with significant battery drain and get blamed for using GPS for several minutes.
Is there a way to set a timeout for GPS search (detect indoors situation)?
Is it possible to get a decent location using FusedLocationProviderApi without automatically triggering GPS or do I have to revert to the old location API?
Do I have to resort to limiting each LocationRequest to couple of minutes (setExpirationDuration) and create a new one to prevent the GPS battery drain?
[EDIT]: I think I might have found an another culprit. On a map tab in the app I have set setMyLocationEnabled(true), and this seems to be causing the GPS to flare up. I will experiment a bit more and post the results. Still I'm interested in how the location manager decides that enough is enough when it comes to GPS fix attempt.
Thanks in advance!
After few hours of testing outside of house, when i came back to my house i found that GPS is enabled but was not getting location fixes inside the building.Hence its onLocationChanged method couldn't get called.
Problem: How to know that GPS is not getting any location fixes as device continue to sense your location in "trying mode".By trying mode i mean the situation where it is not coming to any result even after 20 to 30 minutes still it declared it self as enabled (blinking in status bar).
How one could know that the GPS doesn't get location so switch to another provider like Network_Provider.
In short i want to get my device to conclude something that GPS can find location fix for sure or you have to take location by another means.
I hope at least someone can give me idea about how to deal with that.
The link below has an awesome tutorial, of how to get the location from GPS and/or Network.
It uses a timer task, which analyzes if there is a GPS location in a specific period of time, assume 20 seconds. If not, it will return the location from Network as the current location. If there is a location from GPS, then it will compare which update is new (latest), and return that.
What is the simplest and most robust way to get the user's current location on Android?
I have a Service implementing LocationListener listening for both GPS and Network.
The application is dependant on a constant location-feed, but it seems when GPS has a hard time getting a locationfix network location doesnt step in.
manager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000 * 30,0, LocationReporterService.this);
manager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000 * 60 * 2,0, LocationReporterService.this);
Questions
How do I make sure that I always get a location?
How can I make sure that if I dont get a GPS-location, I get a Network-location?
Is it a known bug?
Should I have 2 services, GPSLocationService and NetworkLocationsService?
Is there a solution to this? :)
I agree with most of comments from AlexBottoni good answer, although in some points I can't suppot him.
Overview
First, just to check that you are doing it right...
You setup the same LocationListener for both providers. To indentify from where you are reciving the location you need to test it like this:
public void onLocationChanged(Location fix) {
if(fix.getProvider().equals(LocationManager.GPS_PROVIDER)){
//here Gps
} else if(fix.getProvider().equals(LocationManager.NETWORK_PROVIDER)){
//here Network
}
Also, you setup a different acquisition frequency. Gps is providing a new location every 30 seconds and Network every 2 minutes.
As you didn't impose a minimum distance, you should receive a new Location from each one of the providers (as long as they can get a fix) with the frequency requested. If you don't receive a fix, is because they weren't able to acquire one.
Also, it may takes a little longer then requested to get the fix (mainly with Gps), because it may take some time to shyncronize with satellites and fix a location.
Fallback
There is no builted-in fallback from one provider to the other. They are independet, as said by Alex. I'm using the following approach to implement fallback:
Register Gps listener and start a timer
On every GPS location, restart timer
If timer reachs end, register Network listener (Gps listener keeps registered)
If new Gps location arrives, unregister Network listener, restart timer
Preferable Provider
Although Gps may not be available everyhere, is far most precise then Network. In my town, I get 6 meters accuracy with GPS and 1 Km with Network :-(
Two services
Doesn't matter where you register the listener, activity or service, separate ot together, as long as you request them and the provider can get a fix, you will get the location (assuming no bugs in application :-))
Final Notes
Ensure you have the permissions need (ACCESS_FINE_LOCATION, INTERNET, etc).
Ensure that phone setup have Network Location enabled (usually default is disable)
Most Gps receivers support updating information about satellite location, which improves fix time. You can use GPS Satus from the market, to do it.
Regards.
This is really weird because, AFAIK, Android does not fall back to the second choice (network location provider) only if and when the first one (GPS) does not work. The two location providers are indipendent and should be sending location updates to you listeners indipendently to each other. Hence, the first one (GPS) should not be able to block the second one (network) in any case.
Regarding your questions:
How do I make sure that I always get a location?
You don't. There is no way to be sure. There are cases in which you cannot get any location fix just because no location reference is available. This is often the case in metro/underground stations. No GPS, no cellular antennas (not everybody lives in NYC or London...), no wi-fi hotspots so no way to determine your current position. Believe it or not, in the new hospital of my town, we have this situation at the moment because GPS constellation is not visible (indoor...), no wi-fi hotspots have been installed yet and the only available CellID antenna is just a few hundred meters away so you get the same signal everywhere, both outside and inside the building.
How can I make sure that if I dont get a GPS-location, I get a Network-location?
You cannot, either. It depends on the available networks. Anyway, you can check what you get from the location providers in your code and switch from one to the next until you get a usable location fix.
Is it a known bug?
No, it is not a bug. It is more a known limit of the existing technology.
Should I have 2 services, GPSLocationService and NetworkLocationsService?
It is something to try. As nick already said, this should not be a problem but a check should not hurt.
Is there a solution to this? :)
If your app is intended to be used mainly in a urban environment (a town), most likely you should use the network location engine as your main location engine. Nowadays, every village and town is covered by a large set on cellular phone antennas and by a large set of wi-fi hotspot so you are more likely to get a good location fix from the network location provider than from the GPS one. This is particularly true in towns with high buildings and narrow roads (that does not just mean NYC. Even here in Venice we have problems with the GPS). The network engine is also faster in getting a first fix and works indoor as well.
Fall back to GPS only if and when the network location engine does not work.
I am trying to find out more information about LocationProvider.TEMPORARILY_UNAVAILABLE location status on Android.
I have a program that has to periodically poll device's GPS location. I use requestLocationUpdates() and addGpsStatusListener() methods in the LocationManager class to register my listener.
Most of the time it works just fine. However, occasionally a device would get into a mode where onStatusChanged() method would be called with status argument set to LocationProvider.TEMPORARILY_UNAVAILABLE and my program would not receive updates anymore.
Do you know what would cause the GPS device to become "Temporary Unavailable"? I've been searching the internet but could not find anything useful.
Thanks.
i'm working on app, which must get latitude and longitude. in my case requestLocationUpdates (String provider, long minTime, float minDistance, LocationListener listener) is not in option. why? because i must get location just when user do something that location is needed (let's say he hits button). and i need location exactly on the time, when button is hit. in requestLocationUpdates, we can set minTime-if i set this let's say on 30000 the location at the "button hit time" won't be as good as i want. of the same reason minDistance is also not as good as i want. if i understant function requestLocationUpdates correct-when minTime and minDistance are set to 0, location is updating all the time. please correct me if i'm wrong. app is for company that i'm working at and that app will be used through the day and night. so if app will check for location updates all the time, battery would be often empty. thst's why i need location just at the time, that button is hit. i found requestSingleUpdate function. but i can't use it in eclipse =( like it doesn't exists.
is there some other way to do this or am i missing something?
The requestSingleLocation method new for API level 9. If you are targeting an earlier API level, this method will not be available to you.
One of the problems with obtaining location information is that it can take time to get a fix. This is more of a problem with the GPS location provider than the network provider. If you are only using the network provider, then there may not much of a delay with getting the location information when the user clicks the button (I say this knowing nothing about what your app does with the data, or what type of user experience you are trying to provide).
Something else you can try is the PASSIVE_PROVIDER. It allows you to get location updates that were requested from other apps. This will mean that you have to request the ACCESS_FINE_LOCATION permission however. You may also need to leave something running to receive the location updates (likely a service or a BroadCastReceiver). The BroadcastReceiver approach should not use that much additional battery life since it only runs when the Intent is received along with the PASSIVE_PROVIDER only getting locations when some other app requested them anyways.
The other sticky point with the PASSIVE_PROVIDER is that you should eventually call removeUpdates. Where and when to call this really depends on how your app is structured and how you handle the user exiting the app.
You can use getLastKnownLocation method, but it can be out-of-date. requestLocationUpdates is asynchronous because gps needs to "warm-up" to find new location.
requestSingleUpdate method is available since api level 9, but you can implements it's using requestLocationUpdates and disabling updates after first callback to LocationListener.