2010-06-25 22 views
9

Mi aplicación verifica a una hora específica si un usuario se encuentra en una ubicación determinada. Yo uso el gestor de alarma para iniciar un servicio que hace que esta llamada:Android: obtención confiable de la ubicación actual

locationManager.requestLocationUpdates(bestProvider, 0, 0, listener); 

Y también comprueba:

locationManager.getLastKnownLocation(bestProvider); 

pero estoy teniendo problemas cuando se ejecuta en un dispositivo real. Por un lado, es muy probable que getLastKnownLocation sea el último lugar en el que se encontraba el GPS, que podría estar en cualquier lugar (es decir, podría estar a millas de la ubicación actual del usuario). Así que solo esperaré las devoluciones de llamada requestLocationUpdates, y si no están allí en dos minutos, elimine el oyente y desista, ¿no?

Incorrecto, porque si la ubicación del usuario ya es estable (es decir, han usado GPS recientemente y no se han movido), entonces mi escucha no se volverá a llamar porque la ubicación no cambia. Pero el GPS se ejecutará hasta que se elimine mi oyente, agotando la batería ...

¿Cuál es la forma correcta de obtener la ubicación actual sin confundir una ubicación anterior con la ubicación actual? No me importa esperar unos minutos.

EDITAR: Es posible que me equivoque sobre el hecho de que el oyente no ha sido llamado, puede tardar un poco más de lo que pensaba ... Es difícil de decir. Apreciaría una respuesta definitiva aún.

Respuesta

5

El código puede ser algo así:

public class MyLocation { 
    Timer timer1; 
    LocationManager lm; 

    public boolean getLocation(Context context) 
    { 
     lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); 
     lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListenerGps); 
     timer1=new Timer(); 
     timer1.schedule(new GetLastLocation(), 20000); 
     return true; 
    } 

    LocationListener locationListenerGps = new LocationListener() { 
     public void onLocationChanged(Location location) { 
      timer1.cancel(); 
      lm.removeUpdates(this); 
      //use location as it is the latest value 
     } 
     public void onProviderDisabled(String provider) {} 
     public void onProviderEnabled(String provider) {} 
     public void onStatusChanged(String provider, int status, Bundle extras) {} 
    }; 

    class GetLastLocation extends TimerTask { 
     @Override 
     public void run() { 
      lm.removeUpdates(locationListenerGps); 
      Location location=lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER); 
      //use location as we have not received the new value from listener 
     } 
    } 
} 

Empezamos el oyente y esperamos a que la actualización desde hace algún tiempo (20 segundos en mi ejemplo). Si recibimos una actualización durante este tiempo, la usamos. Si no recibimos una actualización durante este tiempo, usamos getLastKnownLocation value y detenemos el oyente.

se puede ver el código completo aquí What is the simplest and most robust way to get the user's current location on Android?

EDITAR (autor de la pregunta): Se trata de la mayor parte de la respuesta, pero mi solución final utiliza un Handler en lugar de un temporizador.

+0

¿Puede proporcionarnos algún código de ejemplo? Por ejemplo, ¿cómo esperarías 2 minutos o algo así si no se llama al oyente de la ubicación? – noah

+0

Se agregó un fragmento de código – Fedor

4

Si la ubicación del usuario ya es estable, getLastKnownLocation devolverá la ubicación actual. Llamaría primero al getLastKnownLocation, mire la marca de tiempo (compare Location.getElapsedRealTimeNanos() con SystemClock.elapsedRealTimeNanos()) luego registre un oyente si la solución es demasiado antigua.

+0

Gracias, no sabía acerca de getTime(). El problema con esto es, ¿qué edad tiene que pasar un tiempo antes de que el proveedor de la ubicación lo considere demasiado viejo? ¿Cómo puedo garantizar que se llamará a mi oyente si no uso esa ubicación? – noah

+1

El proveedor de ubicación no considera que sea demasiado viejo, nunca lo descarta (hasta donde yo sé). Debe decidir cuándo considera que la solución es demasiado antigua y solicitar actualizaciones si es necesario. Entonces aún puede usar la ubicación anterior si no hay actualizaciones dentro de un tiempo determinado. – cristis

+2

Aquí hay un pequeño problema: la API no define el origen de la marca de tiempo devuelta por Location.getTime(). Para el GPS, parece ser el tiempo del satélite. Para el proveedor de red, parece ser la hora del dispositivo local. Eso hace que sea algo difícil determinar de manera confiable la antigüedad de una ubicación, ya que considera la posibilidad de que el reloj de un usuario sea inexacto o la zona horaria no esté bien configurada. – sstn

Cuestiones relacionadas