I have these two lines of code ready to be used in the section of my app where the user's location is requested:
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 0, locationListener);
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 5000, 0, locationListener);
The problem is that, when testing in real device, I have noticed that, using GPS_provider does not work very well when being in certain places like inside of a building....the app is stuck waiting to acquire GPS coordinates which take a lot of time or just never come unless I have open-sky conditions.
The question would be: how do I do to still use GPS_providerby default but, if gps coordinates take more than XXXX seconds to be acquired, then switch to Network_providerand acquire position from Network.
Small edit: is it maybe any way to check GPS signal strength before using GPS or Network provider?
LocationListener has a function onStatusChanged(). You have to override this function to check GPS_PROVIDER's status and accordingly take necessary action , which in your case is switching to NETWORK_PROVIDER.
Hope this answers your query
Related
I develop app, which in service get location and send it to server.
Service in background get location every 5 min(for example).
Battery quickly dies, when GPS and Wi-Fi uses..
So, how can I save battery life ?
Thanks for help in advance!
Small question:
Am I right to do request location updates every 5min code below?
And is it correctly use requestLocationUpdates with NETWORK_PROVIDER and next with GPS_PROVIDER ? That necessary, when GPS not find signal, but Wi-Fi find signal and give coordinates.
I do this:
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 30000, 0, locationListener);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 30000, 0, locationListener);
First of all, you do have to realize that these functions that you need to use are probably one of the most demanding in terms of power. I've compiled a few things that might help you consume less power:
First of all see if you really need the accuracy GPS_PROVIDER. If not choose NETWORK_PROVIDER.
From what I see you set the requestLocationUpdates callback method to be called 2 times, by setting the NETWORK_PROVIDER and the GPS_PROVIDER. You do not need to use them both. Plus take a look at the parameters that you pass on the requestLocationUpdates method:
`public void requestLocationUpdates (String provider, long minTime, float minDistance, LocationListener listener)`
According to the documentation the minDistance is minimum distance between location updates, in meters and you have set it in 0. That means that the device will constantly acquire the users location.
I am able to set a location proximity alert with addProximityAlert and receive the alerts with a broadcast receiver.
But how will I be able to identify the location proximity alert is fired from a location provided by a GPS_PROVIDER and not a NETWORK_PROVIDER. I just want to make sure that the alerts are fired from an accurate location.
I have exactly the opposite problem - I would not want it to use the GPS provider due to the battery drain. But it seems there is no currently known solution. One thing I might be investigating is setting the location radius higher - hoping that a radius of 1000m would automatically not use GPS for example. In my current testing, it seems a radius of 250m will definitely trigger GPS location. At leas
I read on various sources that ProximityAlerts use BOTH Network and GPS provider, so I think that it really depends on the specified radius.
In my test, if I have GPS enabled but set a 1000m radius, it fires the alert in a way that makes me think it's using the Network provider, because I'm sure I'm over the 1000 radius (thus the position detected by the device could only be approximated)
It is not recommended to use GPS provider as it ideals when phone's screen is off, and battery drain issues, but still if you want to then use following:
LocationListener ll;
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE );
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, ll);
locationManager.addProximityAlert(latitude, longitude, radius, -1, proximityIntent);
//you have to define latitude,longitude,radius etc parameters yourself
you can change "GPS_PROVIDER" to "NETWORK_PROVIDER" in order to use network provided location
In my app the GPS takes too much time to get the location.
How can I use GPS from GPS_SATELLITES and GPS _NETWORK_PROVIDERS simultaneously in the same context and get the value of the recent GPS?
Keep track of a Location object that is your current location. Request location updates from both
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
LOCATION_UPDATE_FREQUENCY, LOCATION_UPDATE_MIN_DISTANCE,
gpsListener);
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, LOCATION_UPDATE_FREQUENCY,
LOCATION_UPDATE_MIN_DISTANCE, networkListener);
then when you get a response in onLocationChanged of either listener, either simply replace the Location variable you stored or replace it only if it is X seconds more recent, X% more accurate, X meters distant from your last reading, etc.
You can also use LocationManager.getAllProviders(), then call LocationManager.getLastKnownLocation(provider) to retrieve the last location each available provider found the last time it was called. This way, if another app used the GPS a minute ago, you can just go ahead and trust that they user hasn't made it that far away without hunting for satellites all over again.
I am trying to get the current location. For that I implement a LocationListener and register it for both the network and the GPS provider:
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
I block then for 30 seconds and use the first location that gets passed into the listener's
onLocationChanged()
method with an accuracy of 100 meters or better.
Most of the time this works fine. If the phone is connected to some Wifi network, it takes just a second to get a correct location with an accuracy of about 50 meters. If there is no Wifi but GPS is enabled, it can of course take a while to get a location.
Sometimes however, when connected to a Wifi and getting the current location, some old (cached?) previous "Wifi" location is provided - it might be 15 minutes old and 15 kilometers away from the current location.
The problem is, that
location.getTime()
returns the current time - so it is impossible to know that the location is old.
I guess I have to implement a more elaborate solution - I would just like to know why these old "Wifi" locations have a current timestamp instead one from the time when it was originally retrieved.
This is a known issue which I have encountered and did some research on why this happens.
Here are my observations:
Usually this happens when the mobile network hand-off is happening after losing network connectivity which may not necessarily be significant enough for the user to realize.
Consider you are taking a tube train and you get in at station A and get down at station B, now when you get down at station B the network cell ID may/maynot still be of station A and of course it will do a hands-off and move to station B.
However if you call for getLocation is active before the hand-off you would get station A location which might be like 10 km and 15 mins back.
First understand how network location works:
Android has the cellId of the tower to which it is currently connected to and this id is then used by google to perform look-up and fetch approximate location information whose accuracy can range from 50 metres (one of the best) to a few thousand metres. If the cellId is incorrect as shown in the above example then you would receive wrong location.
There is not much you can do to avoid this except having a custom algorithm that can weed out this noise. Something like
if (location from network) {
if (speed obtained from the difference between previous and current location is greater than say 30 m/s) {
ignore this location as noise
} else {
location is correct
}
}
This is helpful:
A Deep Dive Into Location
and lastly the source code for that talk:
android-protips-location
I have been facing the same issues until I made some changes to my code.
What happened is that I was attaching the same LocationListener when requesting for both GPS and Network location updates and I was getting "weird" issues including getting old WIFI location updates with current time.
Here's my old code:
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 10000, 0, locationListener);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10000, 0, locationListener);
Apparently that is a rather "unsafe" thing to do (sorry, Android newbie here) and so I changed it to:
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 10000, 0, networkLocationListener);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10000, 0, gpsLocationListener);
Of course I had to define 2 separate onLocationChanged block of codes to handle the 2 listeners.
Well, it did solve my problem. I tested this on Gingerbread (API Level: 8). Not sure if it works for you.
I have implemented a locationlistener in my app which uses the Network Provider.
This all works fine because i want a location quickly and with GPS Provider it takes ages.
But I've come to a point in my app where location has to be accurate (max 5-10meters).
I was wondering if it's possible to use the GPS provider with the Network Provider at the same time and then get the best result of both?
And is it also possible to let me know when the GPS provider provided me with an GPS Location?
So basically:
LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
Will this work with the same overridden onLocationChanged() ?
And how can I see if the GPS has gotten a Location?
Thanks,
You can certainly use the same listener for multiple providers. It may be better to use locationmanager.getProviders with a Criteria object then sort by accuracy or just listen to all of them. Not much practical difference though.
The onLocationChanged callback gives you a Location object, which has a getProvider() method you can use to determine where it came from. It also has a getAccuracy() method, so you could also sort your recent fixes by accuracy.
Ideally, if you are not concerned on the battery usage, then it perfectly fine to use both providers. As Daren explained, you can filters the coordinates by using getProvider() and getAccuracy().
http://blog.shinetech.com/2011/10/14/a-good-look-at-android-location-data/
Ideally, if u are using the same listener for multiple providers there are 2 issues to it.
1.) You are requesting location from multiple providers thus more continuous use Battery. - This can be mitigate depending on your use case. You can unregister the listener once u have received a good location (i.e. - not require a continuous location updates for long).
2.) Making your listener synchronized - And this is important, for code to be more stable - You do not know how these listeners would be called. If internally Android calculate the location from different provider on a different thread than ur listener maybe called on the same main thread from 2 different call points. Same listener object is called.