2013-04-09 6 views
9

Desidero ricevere una notifica quando l'utente abilita o disabilita le posizioni di rete o GPS e, soprattutto, desidero sapere quale è stata modificata e come. Ho un destinatario di trasmissione per l'intento di trasmissione android.location.PROVIDERS_CHANGED e questo sta ricevendo la trasmissione corretta.È possibile ricevere una notifica quando un provider di posizione è abilitato/disabilitato e verificare quale azione si è verificata?

Ora devo provare e determinare quale azione si è verificata, ovvero abilitare o disabilitare e quale provider è stato modificato. So che potrei mantenere lo stato di ciascun provider e poi quando riceverò la notifica che sono cambiati, allora potrei capire cosa è cambiato, sto cercando un metodo più "standard" per farlo. L'intento di trasmissione non sembra avere alcun extra per indicare quale provider è cambiato.

Questo è il codice che ho attualmente.

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); 
     } 
     } 
    } 
    } 

e questo è un piccolo estratto dal mio manifesto

<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> 

questo sarebbe perfetto se ci fosse un extra all'interno del Broadcast che ha dichiarato che aveva cambiato fornitore e se è stato attivato o disattivato. Purtroppo questo non è il caso. Qualcuno è a conoscenza di qualsiasi meccanismo attraverso il quale posso determinare quale stato è cambiato senza mantenere le mie variabili di stato.

In un mondo ideale, vorrei monitorare costantemente i cambiamenti ma solo occasionalmente ascoltare i cambiamenti di posizione. Vorrei evitare di monitorare costantemente i cambiamenti di posizione.

risposta

4

mi auguro che questo non contraddice il vostro requisito

So che avrei potuto mantenere lo stato di ogni fornitore e poi quando ho ricevo notifica che hanno cambiato poi ho potuto capire cosa ha cambiato, sto cercando un metodo più "standard" per farlo.

... ma vorrei che il modo migliore, "standard", e più flessibile di fare questo è quello di lasciare il vostro LocationProviderChangedReceiver implementi l'interfaccia LocationListener e quindi implementare onProviderEnabled() e onProviderDisabled() in questo modo:

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

Si noti che è necessario aggiungere l'autorizzazione ACCESS_FINE_LOCATION al manifest, se non lo si è già fatto. Inoltre, altri provider (oltre "Rete" e "GPS") possono essere applicati a seconda del contesto, ad esempio PASSIVE_PROVIDER o anche FUSED_PROVIDER.

risposta Aggiornato:
Se costantemente l'ascolto per le modifiche di localizzazione è disponibile alcuna opzione per voi, il LocationManager sa anche which provider is currently enabled:

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

... in modo che si potrebbe usare questi controlli insieme al vostro BroadcastReceiver per evitare di mantenere manualmente eventuali flag abilitati/disabilitati. Oltre a ciò, esiste un intento chiamato android.location.GPS_ENABLED_CHANGE che potresti provare a ricevere (ed elaborare). Ma dal momento che questo intento è nascosto nella documentazione ufficiale, potrebbe non essere sicuro utilizzarlo, come indicato in this answer.

Anche un altro approccio:
impostazioni di default di Android Toggle Widget (sapete cosa intendo) visualizza i GPS abilitato Stato/disabilitato mediante la sottoscrizione di android.location.PROVIDERS_CHANGED intenti (come si fa) per innescare una richiesta dello stato GPS tramite le impostazioni utente:

@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; 
} 

(dallo official sources).
È possibile adattare questo approccio anche ad altri fornitori di servizi di localizzazione.

+0

Spiacente di cambiare la domanda e i requisiti dopo aver risposto, ma stavo cercando un modo per monitorare questo senza ascoltare le posizioni. Richiedo aggiornamenti di posizione in vari punti ma volevo monitorare costantemente le modifiche ai provider senza dover costantemente ascoltare le posizioni. –

+0

Ok, in questo caso anche il 'LocationManager' potrebbe essere d'aiuto. Ho aggiornato la mia risposta. – saschoar

0

sul ricevitore si potrebbe semplicemente controllare quali i prestatori sono abilitati:

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

In questo modo si ottiene tutti i fornitori di attivare.

5

questo funziona per me:

Add ricevitore per il file manifesto:

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

controllare entrambi i fornitori di posizione a ricevitore:

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); 


    } 

} 

Anche se questo ricevitore è chiamato più di una volta a causa per ovvi motivi, ma questo ti dirà lo stato.

0

Grazie alla risposta di @usman, è possibile applicare la soluzione senza la classe extends nel seguente modo;

AndroidManifest.xml;

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

classe (non ho mai testato);

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); 
    } 

}