13

Sto effettuando alcuni test con la funzione requestLocationUpdates() da FusedLocationApi. Sto usando il PRIORITY_BALANCED_POWER_ACCURACY. Per me la precisione di un isolato urbano mi sta bene.L'autorizzazione ACCESS_COARSE_LOCATION fornisce una precisione cella cellulare su Android

Quando richiedo l'autorizzazione ACCESS_FINE_LOCATION, ottengo una precisione di 100 m che è ottima con GPS disattivata. Dato che non ho bisogno di precisione GPS ma precisione di un isolato, vorrei richiedere solo l'autorizzazione ACCESS_COARSE_LOCATION. Tuttavia, quando richiedo l'autorizzazione ACCESS_COARSE_LOCATION, ottengo una precisione di 2 km. Sembra che il dispositivo non utilizzi più l'autorizzazione Wifi e solo una precisione della torre cellulare.

Come posso ottenere una maggiore precisione con l'autorizzazione ACCESS_COARSE_LOCATION?

Nota: il GPS è disabilitato sul mio dispositivo di prova.

+0

Google crea il modello di posizione raccogliendo le informazioni sui punti di accesso dagli utenti che si connettono tramite wifi e torri cellulari. Più dati raccolgono, migliore è la precisione, quindi tecnicamente avresti bisogno di più utenti Android nella tua zona. D'altra parte sembra strano che il GPS possa avere una precisione dell'ordine di 100m o 2km per l'accesso grossolano. Sei sicuro di non aver calcolato male? – inmyth

+0

La precisione del GPS è circa il metro. Sto facendo tutti i miei test con il GPS spento. Il dispositivo utilizza il wifi quando sto usando il permesso ACCESS_FINE_LOCATION (ho abbastanza utenti Android nella mia area). Dovrei ottenere lo stesso identico risultato quando utilizzo ACCESS_COARSE_LOCATION invece di una precisione di 2000m. – poiuytrez

risposta

37

Questo è un problema interessante e ho avuto l'impressione che l'utilizzo di ACCESS_COARSE_LOCATION avrebbe utilizzato il WiFi, poiché è quello che dice la documentazione.

La documentazione per ACCESS_COARSE_LOCATION stati:

Consente un app per accedere posizione approssimativa derivata dalla rete fonti di localizzazione, come torri cellulari e Wi-Fi.

Quindi, ho messo alla prova, ed i risultati sono sorprendenti.

Ecco il codice che ho usato per testare con:

public class MainActivity extends Activity implements 
     GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener { 

    LocationRequest mLocationRequest; 
    GoogleApiClient mGoogleApiClient; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     buildGoogleApiClient(); 
     mGoogleApiClient.connect(); 
    } 

    @Override 
    protected void onPause(){ 
     super.onPause(); 
     if (mGoogleApiClient != null) { 
      LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this); 
     } 
    } 

    protected synchronized void buildGoogleApiClient() { 
     Toast.makeText(this,"buildGoogleApiClient",Toast.LENGTH_SHORT).show(); 
     mGoogleApiClient = new GoogleApiClient.Builder(this) 
       .addConnectionCallbacks(this) 
       .addOnConnectionFailedListener(this) 
       .addApi(LocationServices.API) 
       .build(); 
    } 

    @Override 
    public void onConnected(Bundle bundle) { 
     Toast.makeText(this,"onConnected",Toast.LENGTH_SHORT).show(); 

     mLocationRequest = new LocationRequest(); 
     mLocationRequest.setInterval(10); 
     mLocationRequest.setFastestInterval(10); 
     mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY); 
     //mLocationRequest.setPriority(LocationRequest.PRIORITY_LOW_POWER); 
     //mLocationRequest.setSmallestDisplacement(0.1F); 

     LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this); 
    } 

    @Override 
    public void onConnectionSuspended(int i) { 
     Toast.makeText(this,"onConnectionSuspended",Toast.LENGTH_SHORT).show(); 
    } 

    @Override 
    public void onConnectionFailed(ConnectionResult connectionResult) { 
     Toast.makeText(this,"onConnectionFailed",Toast.LENGTH_SHORT).show(); 
    } 

    @Override 
    public void onLocationChanged(Location location) { 

     Log.d("locationtesting", "accuracy: " + location.getAccuracy() + " lat: " + location.getLatitude() + " lon: " + location.getLongitude()); 

     Toast.makeText(this,"Location Changed",Toast.LENGTH_SHORT).show(); 
    } 
} 

AndroidManifest.xml:

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> 

build.gradle:

compile 'com.google.android.gms:play-services:7.3.0' 

Il primo test ho fatto è stato con PRIORITY_BALANCED_POWER_ACCURACY e senza WiFi. Si noti che ho anche disabilitato Always Allow Scanning, in quanto afferma:

Let Google Location Service e altre applicazioni di scansione per il Wi-Fi reti, anche quando la connessione Wi-Fi è spento

Quindi, che sarebbe certamente distorce i risultati se è stato abilitato.

Nota che ho anche impostato la Modalità posizione in Modalità risparmio batteria per tutti i test, quindi la radio GPS era spenta per tutto il tempo.

Ecco i risultati di PRIORITY_BALANCED_POWER_ACCURACY, ACCESS_COARSE_LOCATION, e nessuna connessione WiFi:

accuracy: 2000.0 lat: 37.78378378378378 lon: -122.40320943772021 

Così, si dice 2.000 accuratezza metro, ed ecco come lontano le coordinate reali sono, la freccia verde mostra dove ho effettivamente sono:

enter image description here

Poi, ho abilitato Wi-Fi, e corse di nuovo il test, e sorprendentemente, i risultati sono stati esattamente la stessa cosa!

accuracy: 2000.0 lat: 37.78378378378378 lon: -122.40320943772021 

Poi, sono passato a LocationRequest.PRIORITY_LOW_POWER nel LocationRequest mantenendo android.permission.ACCESS_COARSE_LOCATION nel AndroidManifest.xml.

No WiFi:

accuracy: 2000.0 lat: 37.78378378378378 lon: -122.40320943772021 

con WiFi:

accuracy: 2000.0 lat: 37.78378378378378 lon: -122.40320943772021 

I risultati sono stati esattamente la stessa cosa di nuovo! L'utilizzo di PRIORITY_LOW_POWER ha avuto gli stessi risultati dell'uso di PRIORITY_BALANCED_POWER_ACCURACY, in quanto lo stato WiFi non sembrava avere alcun effetto sull'accuratezza delle coordinate.

Poi, solo per coprire tutte le basi, ho cambiato di nuovo a LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY, e acceso l'AndroidManifest.xml a ACCESS_FINE_LOCATION:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> 

Primo test, senza WiFi:

accuracy: 826.0 lat: 37.7825458 lon: -122.3948752 

Quindi, dice accuratezza di 826 metri, ed ecco quanto era vicino sulla mappa:

enter image description here

.515.053.691,36321 milioni

Poi, ho acceso Wi-Fi, ed ecco il risultato:

accuracy: 18.847 lat: 37.779679 lon: -122.3930918 

È letteralmente esatte, come si può vedere sulla mappa:

enter image description here

Sembra che conta meno quello che usi nel tuo codice LocationRequest nel codice Java, e più quale permesso usi in AndroidManifest.xml, poiché i risultati qui mostrano chiaramente che quando si utilizza ACCESS_FINE_LOCATION, avere la radio WiFi attivata o disattivata ha fatto un'enorme differenza nella precisione, ed era anche più acc urate in generale.

Sembra quasi che la documentazione sia un po 'trascurata e che mentre si utilizza android.permission.ACCESS_COARSE_LOCATION, l'attivazione o la disattivazione della radio WiFi non fa la differenza quando l'app è l'unica a effettuare richieste di posizione.

Un'altra cosa che la documentazione afferma è che l'utilizzo di PRIORITY_BALANCED_POWER_ACCURACY consentirà alla tua app di "fare il backup" sulle richieste di posizione effettuate da altre app. Dalla documentazione:

Saranno assegnati solo colpa di potenza per l'intervallo fissato dal setInterval (lungo), ma possono ancora ricevere posizioni innescati da altre applicazioni ad una velocità fino a setFastestInterval (lungo) .

Quindi, se l'utente apre Google Maps, in base alla documentazione, l'app può ottenere una posizione più precisa a quel punto. Questo è uno dei principali aspetti positivi dell'utilizzo del nuovo Fused Location Provider piuttosto che delle API precedenti, poiché diminuisce la quantità di esaurimento della batteria della tua app senza molto lavoro da parte tua.

Modifica: ho eseguito un test di questa funzionalità per vedere cosa accadrebbe durante l'utilizzo di ACCESS_COARSE_LOCATION.

Primo test: ACCESS_COARSE_LOCATION, PRIORITY_BALANCED_POWER_ACCURACY, e WiFi su:

accuracy: 2000.0 lat: 37.78378378378378 lon: -122.38041129850662 

Questo mi ha messi in acqua, abbastanza lontano dalla mia posizione attuale. Poi, sono uscito dall'app di test, ho lanciato Google Maps, che mi ha localizzato esattamente dove mi trovo, quindi ho riavviato l'app di test. L'app di test non è stata in grado di tornare nella posizione da Google Maps e il risultato era esattamente lo stesso di prima!

accuracy: 2000.0 lat: 37.78378378378378 lon: -122.38041129850662 

ho ri-provato questo un paio di volte, giusto per essere sicuri, ma sembra davvero come l'utilizzo di ACCESS_COARSE_LOCATION disattiva anche la capacità di applicazioni a "piggy-back" a posizioni ottenute da altre applicazioni.

Sembra che l'utilizzo di ACCESS_COARSE_LOCATION in AndroidManifest.xml blocchi davvero l'app in termini di dati precisi sulla posizione.

In conclusione, l'unica cosa che puoi veramente fare è affinare la migliore combinazione di impostazioni che funzionano per te e per la tua app, e speriamo che i risultati di questo test possano aiutarti a prendere questa decisione.

+0

Grandi prove. Tuttavia, penso che tu abbia torto sul tuo ultimo paragrafo (prima della conclusione). Se l'utente apre Google Maps e le nostre app richiedono ACCESS_COARSE_LOCATION, purtroppo (ancora) otterremo 2000m. Sembra che il sistema vorrebbe "nascondere" una posizione più precisa di 2000m. – poiuytrez

+0

@poiuytrez Buon punto, ho fatto un'assunzione lì. Stavo pensando che le coordinate sarebbero state più precise, indipendentemente dalla precisione riportata. Lo proverò oggi e aggiornerò con i risultati! –

+0

@poiuytrez Avevi ragione, i risultati del test mostrano che questa funzionalità non funziona con 'ACCESS_COARSE_LOCATION'. Ho aggiornato la risposta con i risultati dei test di oggi. –

0

Quando si richiede l'autorizzazione ACCESS_COARSE_LOCATION, il client di posizione fuso fornirà un'accuratezza del blocco di una città, questo è il comportamento previsto ed è scritto nella documentazione. Date un'occhiata here sotto "Specifica autorizzazioni app"
Quello che posso suggerire è che si utilizza il normale provider di posizione Android (posizione non fusa) e provare ad accedere al provider di rete. Dovrebbe darti la precisione WIFI.

+0

Dalla documentazione: "La precisione a livello di blocco è considerata di circa 100 metri di precisione, utilizzando una precisione grossolana come questa spesso consuma meno energia". Dovrebbe essere una precisione di 100 m, non una precisione di 2000 m. – poiuytrez