Android: LocationManager vs Google Play Services


151

Voglio creare un'app che si concentri su come ottenere la posizione corrente dell'utente e quindi trovare punti di interesse (come bar, ristoranti, ecc.) Che gli sono vicini tramite l' API di Google Places .

Durante la ricerca sul Web di un punto di partenza, mi sono imbattuto in alcuni tutorial che utilizzano la LocationManagerclasse e altri che utilizzano Google Play Services per trovare la posizione degli utenti.

A prima vista entrambi fanno la stessa cosa, ma da quando sono nuovo, mi sono un po 'confuso e non so quale sia il metodo più adatto alle mie esigenze. Quindi, voglio chiederti:

Quali sono le differenze tra questi due metodi per trovare posizioni (se ce ne sono)?


Risposte:


320

Posizione dell'utente su Android

Ottenere la posizione dell'utente su Android è un po 'meno semplice rispetto a iOS. Per iniziare la confusione, ci sono due modi totalmente diversi per farlo. Il primo utilizza API di Android android.location.LocationListenere il secondo utilizza API di Google Play Services com.google.android.gms.location.LocationListener. Analizziamo entrambi.

  1. API di localizzazione di Android

    Le API di localizzazione di Android utilizzano tre diversi provider per ottenere la posizione:

    • LocationManager.GPS_PROVIDER- Questo provider determina la posizione utilizzando i satelliti. A seconda delle condizioni, questo provider potrebbe richiedere del tempo per restituire una correzione della posizione.
    • LocationManager.NETWORK_PROVIDER- Questo provider determina la posizione in base alla disponibilità di cell tower e punti di accesso WiFi. I risultati vengono recuperati mediante una ricerca di rete.
    • LocationManager.PASSIVE_PROVIDER- Questo fornitore restituirà le posizioni generate da altri fornitori. Ricevete passivamente gli aggiornamenti delle posizioni quando altre applicazioni o servizi li richiedono senza effettivamente richiedere le posizioni da soli.

L'essenza è che si ottiene un oggetto LocationManagerdal sistema, si implementa il LocationListenere si chiama il requestLocationUpdatesil LocationManager.

Ecco uno snippet di codice:

    LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
// Define a listener that responds to location updates
LocationListener locationListener = new LocationListener() {
    public void onLocationChanged(Location location) {
      // Called when a new location is found by the network location provider.
      makeUseOfNewLocation(location);
    }

    public void onStatusChanged(String provider, int status, Bundle extras) {}

    public void onProviderEnabled(String provider) {}

    public void onProviderDisabled(String provider) {}
  };

// Register the listener with the Location Manager to receive location updates
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);

Guida dell'API di Google sulle strategie di localizzazionespiega il codice abbastanza bene. Ma menzionano anche che nella maggior parte dei casi otterrai prestazioni della batteria migliori, oltre a una precisione più adeguata, utilizzando invece l' API dei servizi di localizzazione di Google . Ora inizia la confusione!

  1. API dei servizi di localizzazione di Google

L'API dei servizi di localizzazione di Google fa parte dell'APK di Google Play Services ( ecco come configurarlo ). Sono basati sull'API di Android. Queste API forniscono un "fornitore di posizione fusa" anziché i fornitori sopra menzionati. Questo provider sceglie automaticamente quale provider sottostante utilizzare, in base alla precisione, all'utilizzo della batteria, ecc. È rapido perché si ottiene la posizione da un servizio a livello di sistema che continua ad aggiornarlo. E puoi utilizzare funzionalità più avanzate come il geofencing.

Per utilizzare i servizi di localizzazione di Google, la tua app deve connettersi a GooglePlayServicesClient. Per connettersi al client, la tua attività (o frammento, o giù di lì) deve implementare GooglePlayServicesClient.ConnectionCallbackse GooglePlayServicesClient.OnConnectionFailedListenerinterfacce. Ecco un codice di esempio:

    public class MyActivity extends Activity implements ConnectionCallbacks, OnConnectionFailedListener {
    LocationClient locationClient;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my);
        locationClient = new LocationClient(this, this, this);
    }

    @Override
    public void onConnected(Bundle bundle) {
    Location location = locationClient.getLastLocation() ;
        Toast.makeText(this, "Connected to Google Play Services", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onDisconnected() {
    Toast.makeText(this, "Connected from Google Play Services.", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        // code to handle failed connection
        // this code can be found here — http://developer.android.com/training/location/retrieve-current.html 
    }
  • Perché è locationClient.getLastLocation()nullo?

L' locationClient.getLastLocation()ha l'ultima posizione nota da parte del cliente. Tuttavia, il fornitore della posizione fusa manterrà la posizione in background solo se almeno un client è collegato ad esso. Una volta che il primo client si connette, tenterà immediatamente di ottenere una posizione. Se la tua attività è il primo client a connettersi e chiami getLastLocation()subito onConnected(), potrebbe non essere il tempo sufficiente per entrare nella prima posizione. Ciò si tradurrà in locationessere null.

Per risolvere questo problema, devi attendere (indeterminatamente) fino a quando il provider non ottiene la posizione e quindi chiamare getLastLocation(), cosa impossibile da sapere. Un'altra opzione (migliore) è quella di implementare l' com.google.android.gms.location.LocationListenerinterfaccia per ricevere periodici aggiornamenti di posizione (e spegnerlo una volta ottenuto il primo aggiornamento).

    public class MyActivity extends Activity implements ConnectionCallbacks, OnConnectionFailedListener, LocationListener {
    // . . . . . . . . more stuff here 
    LocationRequest locationRequest;
    LocationClient locationClient;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // . . . . other initialization code
        locationClient = new LocationClient(this, this, this);
    locationRequest = new LocationRequest();
    // Use high accuracy
    locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        // Set the update interval to 5 seconds
    locationRequest.setInterval(UPDATE_INTERVAL);
        // Set the fastest update interval to 1 second
    locationRequest.setFastestInterval(FASTEST_INTERVAL);
    }
    // . . . . . . . . other methods 
    @Override
    public void onConnected(Bundle bundle) {
        Location location = locationClient.getLastLocation();
        if (location == null)
            locationClient.requestLocationUpdates(locationRequest, this);
        else
            Toast.makeText(getActivity(), "Location: " + location.getLatitude() + ", " + location.getLongitude(), Toast.LENGTH_SHORT).show();
    }
    // . . . . . . . . other methods
    @Override
    public void onLocationChanged(Location location) {
        locationClient.removeLocationUpdates(this);
        // Use the location here!!!
    }

In questo codice, stai verificando se il client ha già l'ultima posizione (in onConnected). In caso contrario, stai richiedendo aggiornamenti sulla posizione e disattivando le richieste (in onLocationChanged()richiamata) non appena ricevi un aggiornamento.

Si noti che locationClient.requestLocationUpdates(locationRequest, this);deve essere all'interno del onConnectedcallback, altrimenti si otterrà un IllegalStateExceptionperché si tenterà di richiedere posizioni senza connettersi al client di Google Play Services.

  • L'utente ha disabilitato i servizi di localizzazione

Molte volte, l'utente avrebbe disabilitato i servizi di localizzazione (per risparmiare batteria o motivi di privacy). In tal caso, il codice in alto richiederà comunque aggiornamenti della posizione, ma onLocationChangednon verrà mai chiamato. È possibile interrompere le richieste controllando se l'utente ha disabilitato i servizi di localizzazione.

Se la tua app richiede loro di abilitare i servizi di localizzazione, vorresti mostrare un messaggio o un brindisi. Sfortunatamente, non è possibile verificare se l'utente ha disabilitato i servizi di localizzazione nell'API dei servizi di localizzazione di Google. Per questo, dovrai ricorrere all'API di Android.

Nel tuo onCreatemetodo:

    LocationManager manager = (LocationManager) getActivity().getSystemService(Context.LOCATION_SERVICE);
if (!manager.isProviderEnabled(LocationManager.GPS_PROVIDER) && !manager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
    locationEnabled = false;
    Toast.makeText(getActivity(), "Enable location services for accurate data", Toast.LENGTH_SHORT).show();
}
else locationEnabled = true;

E usa la locationEnabledbandiera nel tuo onConnectedmetodo in questo modo:

    if (location != null) {
    Toast.makeText(getActivity(), "Location: " + location.getLatitude() + ", " + location.getLongitude(), Toast.LENGTH_SHORT).show();
}
else if (location == null && locationEnabled) {
    locationClient.requestLocationUpdates(locationRequest, this);
}

AGGIORNARE

Il documento viene aggiornato, LocationClient viene rimosso e l'API supporta l'abilitazione del GPS con un clic dalla finestra di dialogo:

task.addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() {
@Override
public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
    // All location settings are satisfied. The client can initialize
    // location requests here.
    // ...
}
});

task.addOnFailureListener(this, new OnFailureListener() {
    @Override
    public void onFailure(@NonNull Exception e) {
        if (e instanceof ResolvableApiException) {
            // Location settings are not satisfied, but this can be fixed
            // by showing the user a dialog.
            try {
                // Show the dialog by calling startResolutionForResult(),
                // and check the result in onActivityResult().
                ResolvableApiException resolvable = (ResolvableApiException) e;
                resolvable.startResolutionForResult(MainActivity.this,
                        REQUEST_CHECK_SETTINGS);
            } catch (IntentSender.SendIntentException sendEx) {
                // Ignore the error.
            }
        }
    }
});

Link https://developer.android.com/training/location/change-location-settings#prompt

Nuovo client di localizzazione: FusedLocationProviderClient

  private FusedLocationProviderClient fusedLocationClient;

@Override
protected void onCreate(Bundle savedInstanceState) {
    fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
}

Si consiglia di consultare https://developer.android.com/training/location prima di eseguire qualsiasi attività di localizzazione.


9
Puoi utilizzare SettingsApi.checkLocationSettings()per verificare se l'utente ha abilitato i servizi di localizzazione (vedi qui: developers.google.com/android/reference/com/google/android/gms/… ).
Kaolick,

3
LocationClient non esiste più. Per una guida aggiornata e chiara alla posizione, consulta questo articolo: blog.teamtreehouse.com/beginners-guide-location-android
lm2a

1
E pagina di allenamento con SettingsApi esempio: developer.android.com/training/location/…
androidguy

2
Puoi anche creare una geo-fence usando LocationManager! L'API della posizione fusa funziona su dispositivi che non dispongono di servizi Google Play?
Muhammad Babar,

Questo può essere un altro modo migliore per controllare lo stato di abilitazione / disabilitazione GPS fun isLocationEnabled(context: Context): Boolean { val locationMode: Int try { locationMode = Settings.Secure.getInt( context.contentResolver, Settings.Secure.LOCATION_MODE ) } catch (e: SettingNotFoundException) { e.printStackTrace() return false } return locationMode != Settings.Secure.LOCATION_MODE_OFF }
Wahib Ul Haq,

32

Nella mia esperienza, "accuratezza più appropriata" non significa affatto meglio. A meno che non mi manchi qualcosa, se vuoi assicurarti che venga utilizzato il GPS, LocationManager è l'unica strada da percorrere. Tracciamo i veicoli con la nostra app e, di nuovo, a meno che non mi manchi qualcosa, Google Play Services fornisce abbastanza spesso posizioni imprecise.


2
Sì, dalla mia esperienza Google Play Services a volte fornisce una posizione imprecisa.
VY,

2
Sì, l'API dei servizi di localizzazione dei servizi di Google Play può fornire informazioni sulla posizione molto fuorvianti. I modem WiFi vengono spostati, i modem WiFi vengono aggiornati con informazioni sulla posizione errate (ad esempio se la posizione è falsificata da un dispositivo Android che aggiorna la posizione del modem WiFi) e ci sono una serie di altre circostanze che possono causare dati di posizione errati dalla triangolazione del modem WiFi. In tutte le nostre app in cui la posizione precisa è obbligatoria, utilizziamo solo il GPS.
user1608385

27

Dovresti utilizzare l'API di localizzazione di Google Play Services anziché LocationManager. Secondo i documenti:

Le API di posizione dei servizi di Google Play sono preferite rispetto alle API di posizione del framework Android (android.location) come modo per aggiungere la consapevolezza della posizione alla tua app. Se al momento stai utilizzando le API di localizzazione del framework Android, ti consigliamo vivamente di passare alle API di localizzazione dei servizi di Google Play il prima possibile.

Quanto al perché cambiare, Google dice questo:

L'API dei servizi di localizzazione di Google, parte dei servizi di Google Play, fornisce un framework più potente e di alto livello che gestisce automaticamente i fornitori di servizi di localizzazione, il movimento degli utenti e la precisione della posizione. Gestisce inoltre la pianificazione degli aggiornamenti di posizione in base ai parametri di consumo energetico forniti. Nella maggior parte dei casi, otterrai prestazioni della batteria migliori, oltre a una precisione più adeguata, utilizzando l'API dei servizi di localizzazione.


2
Hai collegamenti a quella documentazione da cui provengono queste citazioni? Sarebbe interessante vedere se Google sta dicendo qualcosa di diverso ora.
Edward Brey,

3
Naturalmente lo dicono, perché vogliono i tuoi dati di posizione!
Flyview

Quando aggiungi i servizi di Google Play alla tua app, se un utente installa la tua app, gli verrà richiesto di "aggiornare" i servizi di Google Play per utilizzare la tua app. Nel caso in cui il suo telefono sia quasi pieno (con meme e roba whatsapp) o l'utente non abbia i dati, scusatemi amico mio
Dr Deo,

2
@Flyview Yep! Lol, il modo in cui lo esprimono lo fa sembrare una soluzione magica! Lo svantaggio più grande è che hai bisogno di Google Play Services sul dispositivo !!!
Varun,

25

Uso l'API dei servizi di localizzazione di Google da un po 'di tempo. Ha dei vantaggi, poiché incapsula la complessità di avere diverse fonti per determinare le posizioni. Tuttavia si incapsula troppo pesantemente , in modo che quando ottieni una posizione strana, non hai modo di determinare da dove provenga quella strana posizione.

Nella vita reale ho avuto diversi valori bizzarri, che si trovano a 10 chilometri di distanza dalla posizione attuale. L'unica spiegazione è che queste posizioni folli derivano da errori nei database Wi-Fi o NWK di Google - errori che saranno sempre presenti, poiché le topologie di Wi-Fi e rete cambiano ogni giorno. Ma sfortunatamente (e sorprendentemente) l'API non fornisce informazioni su come è stata derivata una posizione individuale.

inserisci qui la descrizione dell'immagine

Questo ti lascia con il problema di dover filtrare i valori anomali in base al controllo di plausibilità su velocità, accelerazione, rilevamento ecc.

... o torna alla buona vecchia API framework e usa solo il GPS, che è quello che ho deciso di fare fino a quando Google non migliora l'API fusa.


7

L'API dei servizi di localizzazione di Google , parte dei servizi di Google Play, fornisce un framework più potente e di alto livello che gestisce automaticamente i fornitori di servizi di localizzazione , il movimento degli utenti e l' accuratezza della posizione . Gestisce inoltre la pianificazione degli aggiornamenti di posizione in base ai parametri di consumo energetico forniti. Nella maggior parte dei casi, otterrai prestazioni della batteria migliori , oltre a una precisione più adeguata, utilizzando l'API dei servizi di localizzazione.

Diffferences più dettagliato fra il due API di Google Play Service Location API e Android quadro Location API può essere trovato qui


Ho usato la tua risposta per rispondere alla mia domanda se va bene. Molte grazie! stackoverflow.com/questions/39852955/...
Leniaal

@Leniaal, quindi non pensi che la mia risposta meriti un voto?
Dhruvam Gupta,

Questo è un vecchio documento di 3 anni. Ma ecco un plus 1
Drew

5

Sì, l'API dei servizi di localizzazione dei servizi di Google Play può fornire informazioni sulla posizione molto fuorvianti. I modem WiFi vengono spostati, i modem WiFi vengono aggiornati con informazioni sulla posizione errate (ovvero se la posizione è falsificata da un dispositivo Android che aggiorna la posizione del modem WiFi) e ci sono una serie di altre circostanze che possono causare dati errati sulla posizione dalla triangolazione del modem WiFi. In tutte le nostre app in cui la posizione precisa è obbligatoria, utilizziamo solo il GPS.


3

Differenza tra le due API API di posizione del servizio Google Play e API di posizione del framework Android in base al servizio GPS

FusedLocationProviderClient

  1. Per il primo recupero, la posizione non deve essere nulla (ovvero: alcune altre app devono aggiornare la posizione Lastknown nel database di GoogleplayService. Se è null, è necessario aggirare il problema)
  2. Per il successivo requestLocationUpdates()recupero sequenziale, utilizza il metodo per recuperare la posizione.
  3. Il recupero della posizione si basa solo locationRequest.setInterval(milliseconds)e setFastestInterval(milliseconds)non sulla modifica della posizione dell'utente
  4. Il valore LatLng restituito contiene solo 7 valori decimali (ad esempio: 11.9557996, 79.8234599), non altrettanto accurati
  5. Consigliato, quando i requisiti della tua app prendono la distanza della posizione attuale trascurabile di (precisione 50 - 100 metri)
  6. Efficace nell'uso della batteria.

LocationManager Api

  1. Il recupero della posizione dell'utente viene richiamato utilizzando locationManager.requestLocationUpdates ()
  2. La posizione viene recuperata in base alla modifica della posizione dell'utente e agli intervalli di tempo locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, milliseconds, mindistance, Mylocationlistener)

  3. Il valore LatLng restituito contiene 14 valori decimali (ad es. 11.94574594963342 79.81166719458997) valori di posizione precisi

  4. Consigliato per app basate sulla posizione, quando è necessaria una maggiore precisione anche in metri.
  5. L'utilizzo della batteria si basa sull'intervallo di recupero e sulla distanza di recupero.

Hey! 1 ° è al massimo 111_111 metri (20_000_000 / 180). Quindi, 0,0000001 ° è 0,011 m = 1 cm. Non so dove sia necessaria una migliore risoluzione GPS. E non so nemmeno, come puoi ottenere una migliore risoluzione GPS.
babay,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.