¿Cómo puedo verificar el estado actual del receptor GPS?

¿Cómo puedo verificar el estado actual del receptor GPS? Ya revisé el método LocationListener onStatusChanged , pero de alguna manera parece que no está funcionando, o simplemente es una posibilidad incorrecta.

Básicamente, solo necesito saber si el ícono del GPS en la parte superior de la pantalla está parpadeando (no hay una solución real) o es sólido (la solución está disponible).

Como desarrollador de SpeedView: velocímetro GPS para Android, debo haber intentado todas las soluciones posibles a este problema, todas con el mismo resultado negativo. Reiteremos lo que no funciona:

  1. onStatusChanged () no se llama en Eclair y Froyo.
  2. Simplemente contar todos los satélites disponibles es, por supuesto, inútil.
  3. Comprobar si alguno de los satélites devuelve verdadero para usedInFix () tampoco es muy útil. El sistema claramente pierde la solución pero sigue informando que todavía hay varios sats que se usan en ella.

Así que aquí está la única solución de trabajo que encontré, y la que realmente uso en mi aplicación. Digamos que tenemos esta clase simple que implementa GpsStatus.Listener:

 private class MyGPSListener implements GpsStatus.Listener { public void onGpsStatusChanged(int event) { switch (event) { case GpsStatus.GPS_EVENT_SATELLITE_STATUS: if (mLastLocation != null) isGPSFix = (SystemClock.elapsedRealtime() - mLastLocationMillis) < 3000; if (isGPSFix) { // A fix has been acquired. // Do something. } else { // The fix has been lost. // Do something. } break; case GpsStatus.GPS_EVENT_FIRST_FIX: // Do something. isGPSFix = true; break; } } } 

OK, ahora en onLocationChanged () agregamos lo siguiente:

 @Override public void onLocationChanged(Location location) { if (location == null) return; mLastLocationMillis = SystemClock.elapsedRealtime(); // Do something. mLastLocation = location; } 

Y eso es. Básicamente, esta es la línea que lo hace todo:

 isGPSFix = (SystemClock.elapsedRealtime() - mLastLocationMillis) < 3000; 

Por supuesto, puede ajustar el valor de millis, pero le sugiero que lo configure entre 3 y 5 segundos.

Esto realmente funciona y aunque no he mirado el código fuente que dibuja el ícono del GPS nativo, esto está cerca de replicar su comportamiento. Espero que esto ayude a alguien.

El ícono de GPS parece cambiar su estado de acuerdo con los bashs de transmisión recibidos. Puede cambiar su estado usted mismo con los siguientes ejemplos de código:

Notificar que el GPS ha sido habilitado:

 Intent intent = new Intent("android.location.GPS_ENABLED_CHANGE"); intent.putExtra("enabled", true); sendBroadcast(intent); 

Notifique que el GPS está recibiendo correcciones:

 Intent intent = new Intent("android.location.GPS_FIX_CHANGE"); intent.putExtra("enabled", true); sendBroadcast(intent); 

Notifique que el GPS ya no está recibiendo correcciones:

 Intent intent = new Intent("android.location.GPS_FIX_CHANGE"); intent.putExtra("enabled", false); sendBroadcast(intent); 

Notificar que el GPS ha sido deshabilitado:

 Intent intent = new Intent("android.location.GPS_ENABLED_CHANGE"); intent.putExtra("enabled", false); sendBroadcast(intent); 

Código de ejemplo para registrar el receptor a los bashs:

 // MyReceiver must extend BroadcastReceiver MyReceiver receiver = new MyReceiver(); IntentFilter filter = new IntentFilter("android.location.GPS_ENABLED_CHANGE"); filter.addAction("android.location.GPS_FIX_CHANGE"); registerReceiver(receiver, filter); 

Al recibir estos bashs de transmisión, puede observar los cambios en el estado del GPS. Sin embargo, se le notificará únicamente cuando el estado cambie. Por lo tanto, no es posible determinar el estado actual usando estos bashs.

nuevo miembro, por lo que desafortunadamente no puedo comentar ni votar, sin embargo, la publicación anterior de Stephen Daye fue la solución perfecta para el mismo problema exacto con el que he estado buscando ayuda.

una pequeña modificación a la siguiente línea:

 isGPSFix = (SystemClock.elapsedRealtime() - mLastLocationMillis) < 3000; 

a:

 isGPSFix = (SystemClock.elapsedRealtime() - mLastLocationMillis) < (GPS_UPDATE_INTERVAL * 2); 

Básicamente como estoy construyendo un juego de ritmo lento y mi intervalo de actualización ya está configurado en 5 segundos, una vez que la señal de GPS está fuera por más de 10 segundos, ese es el momento adecuado para disparar algo.

aplausos, pasé unas 10 horas tratando de resolver esta solución antes de encontrar tu publicación 🙂

Ok, intentemos una combinación de todas las respuestas y actualizaciones hasta el momento y hagamos algo como esto:

  • Agregue el permiso ACCESS_FINE_LOCATION a su manifiesto
  • Obtenga una instancia del sistema LocationManager
  • Crea un GpsStatus.Listener que reaccione a GPS_EVENT_SATELLITE_STATUS
  • Registre el oyente con LocationManager con addGpsStatusListener

El oyente del GPS podría ser algo como esto:

 GpsStatus.Listener listener = new GpsStatus.Listener() { void onGpsStatusChanged(int event) { if (event == GPS_EVENT_SATELLITE_STATUS) { GpsStatus status = mLocManager.getGpsStatus(null); Iterable sats = status.getSatellites(); // Check number of satellites in list to determine fix state } } } 

Las API son un poco confusas sobre cuándo y qué información de GPS y satélites se proporciona, pero creo que una idea sería ver cuántos satélites están disponibles. Si está por debajo de tres, entonces no puedes tener una solución. Si es más, entonces deberías tener una solución.

Prueba y error es probablemente el camino a seguir para determinar la frecuencia con la que Android informa el satélite y la información que contiene cada objeto GpsSatellite .

Después de algunos años de trabajar con GPS en Windows Mobile, me di cuenta de que el concepto de “perder” una corrección de GPS puede ser subjetivo. Para simplemente escuchar lo que el GPS le dice, agregar un NMEAListener y analizar la oración le dirá si la corrección fue “válida” o no. Ver http://www.gpsinformation.org/dale/nmea.htm#GGA . Desafortunadamente con algunos GPS, este valor fluctuará de ida y vuelta incluso durante el curso normal de la operación en un área de “buena solución”.

Entonces, la otra solución es comparar la hora UTC de la ubicación del GPS con la hora del teléfono (convertida a UTC). Si están separados por una diferencia de tiempo determinada, puedes asumir que has perdido la posición GPS.

se mete en un problema similar mientras trabajo en mi proyecto de maestría, parece que la respuesta de Daye informó erróneamente “sin solución” mientras el dispositivo se queda en una ubicación estática. He modificado la solución solo un poco, lo que parece funcionar bien para mí en una ubicación estática. No sé cómo afectaría la batería, ya que no es mi principal preocupación, pero así es como lo hice al volver a solicitar actualizaciones de ubicación cuando se agotó el tiempo de espera.

 private class MyGPSListener implements GpsStatus.Listener { public void onGpsStatusChanged(int event) { switch (event) { case GpsStatus.GPS_EVENT_SATELLITE_STATUS: if (Global.getInstance().currentGPSLocation != null) { if((SystemClock.elapsedRealtime() - mLastLocationMillis) < 20000) { if (!hasGPSFix) Log.i("GPS","Fix Acquired"); hasGPSFix = true; } else { if (hasGPSFix) { Log.i("GPS","Fix Lost (expired)"); lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2000, 10, locationListener); } hasGPSFix = false; } } break; case GpsStatus.GPS_EVENT_FIRST_FIX: Log.i("GPS", "First Fix/ Refix"); hasGPSFix = true; break; case GpsStatus.GPS_EVENT_STARTED: Log.i("GPS", "Started!"); break; case GpsStatus.GPS_EVENT_STOPPED: Log.i("GPS", "Stopped"); break; } } } 

Si solo necesita saber si hay una solución, busque la última ubicación conocida proporcionada por el receptor GPS y compruebe el valor .getTime () para saber qué edad tiene. Si es lo suficientemente reciente (como … algunos segundos), tienes una solución.

  LocationManager lm = (LocationManager)context.getSystemService(LOCATION_SERVICE); Location loc = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER); // Get the time of the last fix long lastFixTimeMillis = loc.getTime(); 

… y finalmente comparar eso con la hora actual (¡En UTC!). Si es lo suficientemente reciente, tienes una solución.

Lo hago en mi aplicación y hasta ahora todo va bien.

Podría intentar usar LocationManager.addGpsStatusListener para actualizarse cuando cambie el estado del GPS. Parece que GPS_EVENT_STARTED y GPS_EVENT_STOPPED podrían ser lo que estás buscando.

Puedo estar equivocado, pero parece que la gente parece estar fuera de tema

Solo necesito saber si el ícono GPS en la parte superior de la pantalla está parpadeando (no hay una solución real)

Eso se hace fácilmente con

 LocationManager lm = (LocationManager) getSystemService(LOCATION_SERVICE); boolean gps_on = lm.isProviderEnabled(LocationManager.GPS_PROVIDER); 

Para ver si tienes una solución sólida, las cosas se ponen un poco más complicadas:

 public class whatever extends Activity { LocationManager lm; Location loc; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); lm = (LocationManager) getSystemService(LOCATION_SERVICE); loc = null; request_updates(); } private void request_updates() { if (lm.isProviderEnabled(LocationManager.GPS_PROVIDER)) { // GPS is enabled on device so lets add a loopback for this locationmanager lm.requestLocationUpdates(LocationManager.GPS_PROVIDER,0, 0, locationListener); } } LocationListener locationListener = new LocationListener() { public void onLocationChanged(Location location) { // Each time the location is changed we assign loc loc = location; } // Need these even if they do nothing. Can't remember why. public void onProviderDisabled(String arg0) {} public void onProviderEnabled(String provider) {} public void onStatusChanged(String provider, int status, Bundle extras) {} }; 

¿Ahora cuando quieras ver si tienes una solución?

 if (loc != null){ // Our location has changed at least once blah..... } 

Si quieres ser elegante, siempre puedes tener un tiempo de espera utilizando System.currentTimeMillis () y loc.getTime ()

Funciona de manera confiable, al menos en un N1 desde 2.1.

Bueno, armar todos los enfoques de trabajo resultará en esto (también se trata de GpsStatus.Listener desuso):

 private GnssStatus.Callback mGnssStatusCallback; @Deprecated private GpsStatus.Listener mStatusListener; private LocationManager mLocationManager; @Override public void onCreate() { mLocationManager = (LocationManager) getSystemService(LOCATION_SERVICE); mLocationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE); if (checkPermission()) { mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, GPS_UPDATE_INTERVAL, MIN_DISTANCE, this); } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { mGnssStatusCallback = new GnssStatus.Callback() { @Override public void onSatelliteStatusChanged(GnssStatus status) { satelliteStatusChanged(); } @Override public void onFirstFix(int ttffMillis) { gpsFixAcquired(); } }; mLocationManager.registerGnssStatusCallback(mGnssStatusCallback); } else { mStatusListener = new GpsStatus.Listener() { @Override public void onGpsStatusChanged(int event) { switch (event) { case GpsStatus.GPS_EVENT_SATELLITE_STATUS: satelliteStatusChanged(); break; case GpsStatus.GPS_EVENT_FIRST_FIX: // Do something. gpsFixAcquired(); break; } } }; mLocationManager.addGpsStatusListener(mStatusListener); } } private void gpsFixAcquired() { // Do something. isGPSFix = true; } private void satelliteStatusChanged() { if (mLastLocation != null) isGPSFix = (SystemClock.elapsedRealtime() - mLastLocationMillis) < (GPS_UPDATE_INTERVAL * 2); if (isGPSFix) { // A fix has been acquired. // Do something. } else { // The fix has been lost. // Do something. } } @Override public void onLocationChanged(Location location) { if (location == null) return; mLastLocationMillis = SystemClock.elapsedRealtime(); mLastLocation = location; } @Override public void onStatusChanged(String s, int i, Bundle bundle) { } @Override public void onProviderEnabled(String s) { } @Override public void onProviderDisabled(String s) { } 

Nota: esta respuesta es una combinación de las respuestas anteriores.

Con LocationManager puede obtener LastKnownLocation () después de obtener BestProvider (). Esto le da un objeto Location, que tiene los métodos getAccuracy () en metros y getTime () en milisegundos UTC

¿Esto te da suficiente información?

O tal vez podría iterar sobre LocationProviders y averiguar si cada uno cumple con Criteria (ACCURACY_COARSE)

tantas publicaciones …

 GpsStatus.Listener gpsListener = new GpsStatus.Listener() { public void onGpsStatusChanged(int event) { if( event == GpsStatus.GPS_EVENT_FIRST_FIX){ showMessageDialog("GPS fixed"); } } }; 

agregando este código, con addGpsListener … showMessageDialog … solo muestra una ventana de diálogo estándar con la cadena

hizo el trabajo perfecto para mí 🙂 muchas gracias: =) (sry para este post, aún no puede votar)

Si no necesita una actualización en el mismo instante en que se pierde la solución, puede modificar la solución de Stephen Daye de esa manera, que tiene un método que verifica si la solución aún está presente.

Entonces puede verificarlo cuando necesite datos de GPS y no necesita ese GpsStatus.Listener.

Las variables “globales” son:

 private Location lastKnownLocation; private long lastKnownLocationTimeMillis = 0; private boolean isGpsFix = false; 

Este es el método que se llama dentro de “onLocationChanged ()” para recordar el tiempo de actualización y la ubicación actual. Además de eso, actualiza “isGpsFix”:

 private void handlePositionResults(Location location) { if(location == null) return; lastKnownLocation = location; lastKnownLocationTimeMillis = SystemClock.elapsedRealtime(); checkGpsFix(); // optional } 

Se llama ese método cada vez que necesito saber si hay una corrección de GPS:

 private boolean checkGpsFix(){ if (SystemClock.elapsedRealtime() - lastKnownLocationTimeMillis < 3000) { isGpsFix = true; } else { isGpsFix = false; lastKnownLocation = null; } return isGpsFix; } 

En mi implementación, primero corro checkGpsFix () y si el resultado es verdadero, utilizo la variable "lastKnownLocation" como mi posición actual.

Sé que esto es un poco tarde. Sin embargo, ¿por qué no utilizar NMEAListener si quieres saber si tienes una solución? Por lo que he leído, NMEAListener te dará las oraciones NMEA y a partir de ahí elegirás la oración correcta.

La oración RMC contiene el estado del arreglo que es A para OK o V para advertencia. La oración GGA contiene la calidad de corrección (0 inválido, 1 GPS o 2 DGPS)

No puedo ofrecerte ningún código de Java porque recién estoy empezando con Android, pero he creado una biblioteca de GPS en C # para aplicaciones de Windows, que estoy buscando usar con Xamarin. Solo encontré este hilo porque estaba buscando información de proveedores.

Por lo que he leído hasta ahora sobre el objeto Location, no estoy tan cómodo con métodos como getAccuracy () y hasAccuracy (). Estoy acostumbrado a extraer de las frases NMEA los valores HDOP y VDOP para determinar la precisión de mis correcciones. Es bastante común tener una solución, pero tiene un HDOP pésimo, lo que significa que su precisión horizontal no es muy buena en absoluto. Por ejemplo, si te sientas en tu escritorio depurando con un dispositivo GPS externo con Bluetooth contra una ventana, es muy probable que tengas una solución, pero muy pobre HDOP y VDOP. Coloque su dispositivo GPS en una maceta afuera o algo similar o agregue una antena externa al GPS e inmediatamente obtendrá buenos valores HDOP y VDOP.

Tal vez sea la mejor posibilidad crear un TimerTask que establezca la ubicación recibida en un cierto valor (nulo?) Regularmente. Si el GPSListener recibe un nuevo valor, actualizará la ubicación con los datos actuales.

Creo que sería una solución de trabajo.

Usted dice que ya probó onStatusChanged (), pero eso funciona para mí.

Este es el método que uso (dejo que la clase maneje el onStatusChanged):

 private void startLocationTracking() { final int updateTime = 2000; // ms final int updateDistance = 10; // meter final Criteria criteria = new Criteria(); criteria.setCostAllowed(false); criteria.setAccuracy(Criteria.ACCURACY_FINE); final String p = locationManager.getBestProvider(criteria, true); locationManager.requestLocationUpdates(p, updateTime, updateDistance, this); } 

Y manejo el onStatusChanged de la siguiente manera:

 void onStatusChanged(final String provider, final int status, final Bundle extras) { switch (status) { case LocationProvider.OUT_OF_SERVICE: if (location == null || location.getProvider().equals(provider)) { statusString = "No Service"; location = null; } break; case LocationProvider.TEMPORARILY_UNAVAILABLE: if (location == null || location.getProvider().equals(provider)) { statusString = "no fix"; } break; case LocationProvider.AVAILABLE: statusString = "fix"; break; } } 

Tenga en cuenta que los métodos onProvider {Dis, En} abled () tratan de habilitar y deshabilitar el seguimiento GPS por parte del usuario; no es lo que estás buscando

Establecer intervalo de tiempo para verificar la corrección no es una buena opción. Noté que no se llama a onLocationChanged si no se está moviendo … lo que es comprensible ya que la ubicación no está cambiando 🙂

Mejor manera sería, por ejemplo:

  • verificar intervalo a la última ubicación recibida (en gpsStatusChanged)
  • si ese intervalo es más de 15 s, configure la variable: long_interval = true
  • elimine el agente de escucha de ubicación y vuelva a agregarlo; por lo general, obtendrá una posición actualizada si la ubicación está realmente disponible; de ​​lo contrario, probablemente haya perdido la ubicación
  • en onLocationChanged simplemente estableces long_interval en falso …