Android - GPS and Network Providers conflict - android

I'm creating app to listen to location changes, in onResume() I call these two methods:
_locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 10,locationListenerGps);
_locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000, 10, locationListenerNetwork);
When I do that, I never get location from GPS_PROVIDER, only from NETWORK_PROVIDER.
What more, when I get location from NETWORK and it gets to method onStatusChanged() (resulting in TEMPORARILY_UNAVAILABLE) app is stucked and nothings going on. There are no location updates at all, until I restart app.
I'll be thankful for any help in discovering why it's not working like I thought it might...

Related

Android: locationManager GPS_provider VS Network_provider

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

Android fused location api not providing consistent updates with screen off

I have some code that runs multiple times per second in my app. I'm trying to get my location in every cycle. I am using the following:
Location myLastPos = LocationServices.FusedLocationApi.getLastLocation(googleApiClient)
My app also runs in the background using a PARTIAL_WAKE_LOCK. With the screen on everything seems OK. When I turn the screen off my app still runs normally but I no longer get location updates consistently.
It appears that I get updates much less frequently (often minutes in between updates). I'm checking the timestamp of the location using:
myLastPos.getElapsedRealtimeNanos()
I also found that even when the screen is on I get some strange results. Sometimes I get a few milliseconds between updates, other times I get a few seconds. This is all very concerning. Can someone either help me use FusedLocationApi properly or suggest an alternative. All I really want is to poll the gps directly for lat/long a few times a second without google libraries getting in the way.
The getLastLocation() method just gets the last known location that the device happens to know. The "last known location" here means exactly that: It may not be up-to-date. Locations do come with a time stamp which could be used to asses if the location might still be relevant.
The device doesn't determine its location on its own, but only when some application request the location. So your app is now dependent on other applications requesting location updates.
If you need updates every few seconds, then request regular location updates yourself.
Android documentation recommends the FusedLocationProvider, but the LocationManager is also a perfectly valid option, if there's any reason to avoid the Google Play services.
The basic idea is to first request location updates:
// Using LocationManager as an example.
mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
// Using GPS, requesting location updates as soon as available and even for
// the smallest changes. Here 'this' refers to our LocationListener
// implementation.
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
The updates are then received by a listener:
#Override
public void onLocationChanged(Location location) {
// We received a location update.
// Copy the value from the method parameter to our
// class member variable.
mLocation = location;
}
And when you no longer need the updates you should cancel the request:
mLocationManager.removeUpdates(this);
The approach is very similar for the FusedLocationProvider.

Prevent GPS draining battery of cell phone when location is searched

I'm using LocationManager's method requestLocationUpdates to get the location of the cell phone.
I'm using GPS as the Provider and working with a LocationListener to update the UI of my app.
I need to call a method on my Activity every 1000 milliseconds. To do that, I configured the requestLocationUpdates like this:
locationManager.requestLocationUpdates(provider, 0, 1000, listener);
Everything is working well. The onLocationChanged method is called and the Latitude and Logitude are showed ok.
But I have some doubts.
What happens if I'm in a place with no GPS signal?.
There is some automatic Timeout?
Or the App will try to get the position using the GPS all the time and will drain the battery.
What happens if I switch to WiFI/3G Provider and thats signals also aren't working? It happens the same?
I search over Internet looking for the answer but I can't find the right solution.
For example let's say you are driving in a car and the LocationManager is connected to a valid GPS provider. Now you driving through a tunnel and lose the signal. Now onLocationChanged() isn't triggered anymore. But the system will keep searching in background for a valid GPS provider. If you are through the tunnel the system reconnects to the GPS provider, if still available, and onLocationChanged() is triggered again.
The drain of the battery while connected and getting location updates is much higher as when the system is looking for a valid provider.
If you switch to WiFi or 3G the system will look for the last set provider and overrides the previous one. But the behaviour will be the same.
You can react on this event by monitoring the LocationListener.onStatusChanged() callback and the GpsStatus.Listener interface. E.g. switch to another provider or if no provider is available call removeLocationUpdates() and call requestLocationUpdates() again after a period of time with a Timer. This will save your battery much better.
Edit:
LocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) returns true if GPS is enabled in the settings of the device. It's no indicator that you are connected to a GPS provider.
Use the method LocationManager.getBestProvider(Criteria, boolean) to know which provider is available.
As a note: You will almost never get a connection to GPS if you are inside of a room.

Network provider stops providing updates

I have noticed that rarely (every few days), my app stops receiving new location updates.
The location listener is registered with both network and GPS providers. The GPS provider is off so any location updates come from the network provider. Every few days or so, I notice the location is old and not updating. From my debug log I can see that the location listener is being registered with location manager but there are just no new locations being found. onLocationChanged() is not called.
The strange thing is, Google Maps has no problem getting a new network location. Restarting/reinstalling/clearing data on the app does not solve the issue. The only thing that solves it is to restart the phone.
This has happened on 3 different devices (2 ICS, 1 JB).
Similar problem but not worded very well here.

LocationManager returns old cached "Wifi" location with current timestamp

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.

Categories

Resources