¿Es posible obtener una notificación cuando se habilita / deshabilita cualquier proveedor de ubicación y determina qué acción se ha producido?

Deseo recibir una notificación cuando el usuario activa o desactiva las ubicaciones de red o GPS y, sobre todo, deseo saber cuál ha cambiado y cómo. Tengo un receptor de la difusión para la intención de la difusión de android.location.PROVIDERS_CHANGED y esto está recibiendo la difusión correcta.

Ahora tengo que tratar de determinar qué acción ha ocurrido, es decir, habilitar o deshabilitar y qué proveedor ha sido cambiado. Sé que podría mantener el estado de cada proveedor y, a continuación, cuando reciba notificación de que han cambiado, entonces podría resolver lo que ha cambiado, estoy buscando un método más "estándar" de hacer esto. La intención de difusión no parece tener ningún extras para indicar qué proveedor ha cambiado.

Este es el código que tengo actualmente.

  public class LocationProviderChangedReceiver extends BroadcastReceiver { private final static String TAG = "LocationProviderChangedReceiver"; @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().matches("android.location.PROVIDERS_CHANGED")) { Log.i(TAG,"Location Providers changed"); Bundle bundle = intent.getExtras(); if (bundle == null) { Log.d(TAG, "No extras data"); } else { Log.d(TAG, "Bundle received of size " + bundle.size); } } } } 

Y este es un pequeño extracto de mi Manifiesto

  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <receiver android:name=".LocationProviderChangedReceiver" android:exported="false"> <intent-filter> <action android:name="android.location.PROVIDERS_CHANGED" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </receiver> 

Esto sería perfecto si había un extra dentro de la difusión que indicó qué proveedor había cambiado y si estaba habilitado o deshabilitado. Desafortunadamente, este no es el caso. ¿Alguien sabe de cualquier mecanismo por el cual puedo determinar qué estado ha cambiado sin mantener mis propias variables de estado.

En un mundo ideal supervisaría constantemente los cambios, pero sólo escuchaba ocasionalmente los cambios de ubicación. Me gustaría evitar monitorear constantemente los cambios de ubicación.

Espero que esto no contradiga su requisito

Sé que podría mantener el estado de cada proveedor y, a continuación, cuando reciba notificación de que han cambiado, entonces podría resolver lo que ha cambiado, estoy buscando un método más "estándar" de hacer esto.

… pero creo que la mejor manera "estándar" y más flexible de hacer esto es dejar que su LocationProviderChangedReceiver implemente la interfaz LocationListener y luego implemente onProviderEnabled() y onProviderDisabled() así:

 public void onProviderEnabled(String provider) { if(provider.equals(LocationManager.GPS_PROVIDER)){ ... } else if (provider.equals(LocationManager.NETWORK_PROVIDER)){ ... } } 

Tenga en cuenta que debe agregar el permiso ACCESS_FINE_LOCATION a su manifiesto si aún no lo ha hecho. Además, otros proveedores (más allá de "Red" y "GPS") pueden aplicar dependiendo del contexto, como PASSIVE_PROVIDER o incluso FUSED_PROVIDER .

Respuesta actualizada:
Si constantemente escuchando los cambios de ubicación no es una opción para usted, LocationManager también sabe qué proveedor está habilitado actualmente :

 LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER); 

… para que pueda utilizar estos controles junto con su BroadcastReceiver para evitar mantener manualmente los indicadores habilitados / deshabilitados. Más allá de eso, hay una intención llamada android.location.GPS_ENABLED_CHANGE que podría tratar de recibir (y procesar) también. Pero como esta intención está oculta en la documentación oficial, podría no ser seguro utilizarla, como se menciona en esta respuesta .

Incluso otro enfoque:
El widget de conmutación de ajustes por defecto de Android (sabes a lo que me refiero) muestra el estado activado / desactivado de GPS al suscribirte a la intención de android.location.PROVIDERS_CHANGED (como tú) para activar una solicitud del estado GPS a través de la configuración del usuario:

 @Override public int getActualState(Context context) { ContentResolver resolver = context.getContentResolver(); boolean on = Settings.Secure.isLocationProviderEnabled( resolver, LocationManager.GPS_PROVIDER); return on ? STATE_ENABLED : STATE_DISABLED; } 

(De las fuentes oficiales ).
También puede adaptar este enfoque a otros proveedores de ubicaciones.

Esto funciona para mí:

Agregue el receptor al archivo de manifiesto:

 <receiver android:name="com.eegeo.location.LocationProviderChangedReceiver"> <intent-filter> <action android:name="android.location.PROVIDERS_CHANGED" /> </intent-filter> </receiver> 

Compruebe ambos proveedores de ubicación en el receptor:

 public class LocationProviderChangedReceiver extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { boolean anyLocationProv = false; LocationManager locationManager = (LocationManager) MyMainActivity.context.getSystemService(Context.LOCATION_SERVICE); anyLocationProv |= locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); anyLocationProv |= locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER); Log.i("", "Location service status" + anyLocationProv); } } 

Aunque este receptor se llama más de una vez debido a razones obvias, pero esto le dirá el estado.

En el receptor, puede comprobar qué proveedores están habilitados:

 LocationManager lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE) List<String> providers = lm.getProviders(true); 

De esta manera obtendrá todos los proveedores habilitados.

Gracias a la respuesta de @usman podemos aplicar la solución sin extends la clase de la siguiente manera;

AndroidManifest.xml;

 <receiver android:name="com.eegeo.location.LocationProviderChangedReceiver"> <intent-filter> <action android:name="android.location.PROVIDERS_CHANGED" /> </intent-filter> </receiver> 

Clase (nunca probé);

 public class LocationProviderChangedReceiver { private mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE); private BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String ability = (isGPSProviderEnabled() && isNetworkProviderEnabled()) ? "CAN" : "CANNOT"; Log.d("", "The location " + ability + " be caught in high accuracy!"); } }; public startProviderChangeObserving () { registerReceiver(mReceiver, new IntentFilter(LocationManager.PROVIDERS_CHANGED_ACTION)); } public stopProviderChangeObserving () { unregisterReceiver(mReceiver); } /** * Method to verify that the location providers wheter on or not on the device **/ public boolean isGPSProviderEnabled() { return (Boolean) mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); } public boolean isNetworkProviderEnabled() { return (Boolean) mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER); } } 
  • CursorAdapter clasificación dinámica
  • Permisos de tiempo de ejecución de Android en las versiones de android debajo de M?
  • Obtener distancia entre la ubicación actual y Selected Place en android
  • Android, Solicitud de ubicación, establecer la duración de caducidad no funciona
  • Enviar extra a requestLocationUpdates intentService rompe las actualizaciones de ubicación
  • Comparando dos ubicaciones usando sus longitudes y latitud
  • OnLocationChanged sólo se llama una vez, no se actualiza
  • NullpointerException al llamar a getSystemService (Context.LOCATION_SERVICE) y onLocationChanged no se llama
  • Geocoder devuelve una dirección con longitud cero
  • Android LocationRequest: obtener una devolución de llamada cuando la solicitud caduca
  • Google Selector de lugares no se está lanzando en teléfonos Android Mi
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.