I'm building an app for Android and iOS that takes a picture, retrieve the device location and send the package to a server for processing.
To get the device location, I know I need to use one of the LocationManager's getCurrentLocation method. But they all look alike to me, so I picked up one but I'm not sure I picked the right one since it does not work very well (I'll explain later) on Android (KitKat).
Indeed I have experienced the same kinf of oddities as recently reported [here] (How to make an immediate reading location using GPS) and even worse. For example connected to home/office Wifi the location (although indoor) is accurate. I understood that the device is basing its results on network. But then when I am 5km (and 40 min) away with open sky and performing a location test with getCurrentLocation or getCurrentLocationAsync or even with a timeout, the device outputs my home/office past location with an accuracy of eg 50 m.
Also I noticed that the location icon that appears normally in Android status bar near to the clock does not appear. To make it appear I noticed that launching Maps app from Google made the location icon appear and then my app was able to locate the device.
Here is the last method I used to get the location :
`public static final void updateGeolocation (){
Location location = null;
try {
location = LocationManager.getLocationManager().getCurrentLocation();
setLocation(location);
setGeolocationAccuracy(location.getAccuracy() > 0.0f ? location.getAccuracy() : DEFAULT_GEOLOCATION_ACCURACY);
} catch (IOException e) {
setLocation(null);
setGeolocationAccuracy(DEFAULT_GEOLOCATION_ACCURACY);
}
}`
Now here is how I update the location thanks to timerTask :
// On lance la mise à jour périodique de la position de l'appareil
// la tache se lance en dehors de l'EDT
ParametresGeneraux.setCheckTimer(new Timer());
ParametresGeneraux.setCheckTask(new TimerTask(){
@Override
public void run() {
ParametresGeneraux.updateGeolocation();
}
});
ParametresGeneraux.getCheckTimer().schedule(ParametresGeneraux.getCheckTask(), 0, ParametresGeneraux.GEOLOCATION_CHECK_INTERVAL);
NB : Regarding the build hints I explained my need for GPS with the hint ios.locationUsageDescription and I disabled the android.captureRecord hint because I did need it and did not want to make the user suspicious about why I would ever need capture Record.
So my questions are :
do I use the getCurrentLocation in the proper way so that I can blame my phone's hardware or am I using it wrong ?
Why does the location icon in the upper part of the screen does appear only if I launched Google Maps and not my app (as if my app did not trigger the location). ?
What's if I don't use a timeout and the location needs 10 minutes to come ? What will happen ? What would be the difference if I set the timeout to 10 seconds and the location comes 10 minutes later (for example I am in a tunnel) ?
Is it preferred to use a LocationListener although it may only trigger when the device location changes ?
Thanks in advance to whoever can make this clearer to my mind,
Edit : Following @ShaiAlmog advices to make all smoothly works I had to :
- do no use the above described updateGeolocation() method
- create my GeolocationListener listener that implements LocationListener and do my stuff in the overriden updateLocation method (see below)
- set the LocationListener to my GeolocationListener in the main class' init method
Now the updated location is available and the location icon appears as expected.
My GeolocationListener is as simple as the following code :
public class GeolocationListener implements LocationListener{
@Override
public void providerStateChanged(int newState) {
}
/**
* Met à jour les valeur de la position et la précision de la géolocalisation si le service de géoloc est dispo. Sinon met à jour les valeurs avec null pour la position
* et DEFAULT_GEOLOCATION_ACCURACY pour la précision
*/
@Override
public void locationUpdated(Location location) {
// Par défaut
ParametresGeneraux.setLocation(null);
ParametresGeneraux.setGeolocationAccuracy(ParametresGeneraux.DEFAULT_GEOLOCATION_ACCURACY);
/*On met à jour la position et la précision
*/
if (location != null && (location.getStatus() == LocationManager.AVAILABLE)){
ParametresGeneraux.setLocation(location);
if ( location.getAccuracy() > 0.0f ) {
ParametresGeneraux.setGeolocationAccuracy(location.getAccuracy());
}
} // fin de la mise à jour de la position
}
}
Regards