¿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.
- GeoFence no activado con ubicación falsa
- ¿Cuál es la mejor manera de esperar a una corrección de ubicación GPS?
- PendingIntents y Google Play Services - cómo hacer la limpieza
- Calcular la velocidad de una aplicación de navegación sin el método getSpeed ()
- cómo obtener longitud y latitud en android
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.
- Administrador de ubicación quita el permiso de actualizaciones
- GetGoogleAppid falló / cargar no es posible Android Studio
- Servicio de fondo con oyente de localización en android
- Cambiar el modo de ubicación a alta precisión mediante programación Android
- Android - ¿Cómo obtener el tiempo estimado de conducción de un lugar a otro?
- Esperando hasta que la ubicación esté encendida después de encenderla a través de la alerta de servicios de ubicación
- ¿Cuándo debo usar el permiso ACCESS_COARSE_LOCATION?
- Uso de GoogleApiClient + LocationServices sin actualizar
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); } }
- Cómo determinar si la tarea del temporizador ha finalizado
- Establecer la fuente personalizada para el texto en PreferenceScreen