Android: LocationManager gegen Google Play Services


151

Ich möchte eine App erstellen, die sich darauf konzentriert, den aktuellen Standort des Benutzers abzurufen und dann über die Google Places-API Sonderziele (wie Bars, Restaurants usw.) zu finden, die ihm nahe stehen .

Beim Durchsuchen des Webs nach einem Startpunkt stieß ich auf einige Tutorials, die die LocationManagerKlasse verwenden, und auf andere, die Google Play Services verwenden, um den Standort des Benutzers zu finden.

Auf den ersten Blick machen beide dasselbe, aber da ich neu in diesem Bereich bin, war ich etwas verwirrt und weiß nicht, welche Methode am besten zu meinen Bedürfnissen passt. Also möchte ich dich fragen:

Was sind die Unterschiede zwischen diesen beiden Methoden zum Auffinden von Orten (falls vorhanden)?


Antworten:


319

Benutzerstandort auf Android

Das Abrufen des Standorts des Benutzers unter Android ist etwas unkomplizierter als unter iOS. Um die Verwirrung zu beginnen, gibt es zwei völlig verschiedene Möglichkeiten, wie Sie dies tun können. Die erste verwendet Android-APIs von android.location.LocationListenerund die zweite verwendet Google Play Services-APIs com.google.android.gms.location.LocationListener. Lassen Sie uns beide durchgehen.

  1. Die Standort-API von Android

    Die Standort-APIs von Android verwenden drei verschiedene Anbieter, um den Standort abzurufen.

    • LocationManager.GPS_PROVIDER- Dieser Anbieter ermittelt den Standort mithilfe von Satelliten. Abhängig von den Bedingungen kann es eine Weile dauern, bis dieser Anbieter einen Standortfix zurückgibt.
    • LocationManager.NETWORK_PROVIDER- Dieser Anbieter bestimmt den Standort basierend auf der Verfügbarkeit von Mobilfunkmasten und WLAN-Zugangspunkten. Die Ergebnisse werden mittels einer Netzwerksuche abgerufen.
    • LocationManager.PASSIVE_PROVIDER- Dieser Anbieter gibt Standorte zurück, die von anderen Anbietern generiert wurden. Sie erhalten passiv Standortaktualisierungen, wenn andere Anwendungen oder Dienste diese anfordern, ohne die Standorte selbst anzufordern.

Der Kern davon ist, dass Sie ein Objekt LocationManagervom System erhalten, das implementieren LocationListenerund das requestLocationUpdatesauf dem aufrufen LocationManager.

Hier ist ein Code-Snippet:

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

Googles API-Handbuch zu Standortstrategienerklärt den Code ziemlich gut. Sie erwähnen jedoch auch, dass Sie in den meisten Fällen eine bessere Akkuleistung sowie eine angemessenere Genauigkeit erzielen, wenn Sie stattdessen die Google Location Services-API verwenden. Jetzt beginnt die Verwirrung!

  1. Google Location Services API

Die Location Services-API von Google ist Teil der Google Play Services-APK ( hier erfahren Sie , wie Sie sie einrichten ). Sie basieren auf der Android-API. Diese APIs bieten anstelle der oben genannten Anbieter einen "Fused Location Provider". Dieser Anbieter wählt automatisch den zugrunde liegenden Anbieter aus, basierend auf Genauigkeit, Batterieverbrauch usw. Er ist schnell, da Sie den Standort von einem systemweiten Dienst erhalten, der ihn ständig aktualisiert. Außerdem können Sie erweiterte Funktionen wie Geofencing verwenden.

Um die Ortungsdienste von Google nutzen zu können, muss Ihre App eine Verbindung zu herstellen GooglePlayServicesClient. Um eine Verbindung zum Client herzustellen, müssen Ihre Aktivitäten (oder Fragmente oder so) implementiert GooglePlayServicesClient.ConnectionCallbacksund GooglePlayServicesClient.OnConnectionFailedListenerSchnittstellen eingerichtet werden. Hier ist ein Beispielcode:

    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 
    }
  • Warum ist locationClient.getLastLocation()null?

Der locationClient.getLastLocation()ruft den letzten bekannten Standort vom Client ab. Der Fused Location Provider behält jedoch nur dann den Hintergrundspeicherort bei, wenn mindestens ein Client mit ihm verbunden ist. Sobald der erste Client eine Verbindung herstellt, versucht er sofort, einen Standort zu ermitteln. Wenn Ihre Aktivität der erste Client ist, der eine Verbindung herstellt, und Sie getLastLocation()sofort anrufen onConnected(), reicht dies möglicherweise nicht aus, um den ersten Standort zu erreichen. Dies führt dazu, dass dies der Fall locationist null.

Um dieses Problem zu lösen, müssen Sie (auf unbestimmte Zeit) warten, bis der Anbieter den Standort erhält, und dann anrufen getLastLocation(), was nicht zu wissen ist. Eine andere (bessere) Option besteht darin, die com.google.android.gms.location.LocationListenerSchnittstelle zu implementieren , um regelmäßige Standortaktualisierungen zu erhalten (und sie auszuschalten, sobald Sie die erste Aktualisierung erhalten).

    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 diesem Code überprüfen Sie, ob der Client bereits den letzten Speicherort (in onConnected) hat. Wenn nicht, fordern Sie Standortaktualisierungen an und schalten die Anforderungen (im onLocationChanged()Rückruf) aus, sobald Sie eine Aktualisierung erhalten.

Beachten Sie, dass sich das locationClient.requestLocationUpdates(locationRequest, this);im onConnectedRückruf befinden muss, sonst erhalten Sie eine, IllegalStateExceptionweil Sie versuchen, Standorte anzufordern, ohne eine Verbindung zum Google Play Services-Client herzustellen.

  • Der Benutzer hat die Ortungsdienste deaktiviert

Oft hat der Benutzer die Ortungsdienste deaktiviert (um Batterie zu sparen oder aus Datenschutzgründen). In einem solchen Fall fordert der obige Code weiterhin Standortaktualisierungen an, wird jedoch onLocationChangedniemals aufgerufen. Sie können die Anforderungen stoppen, indem Sie überprüfen, ob der Benutzer die Ortungsdienste deaktiviert hat.

Wenn Ihre App erfordert, dass sie Ortungsdienste aktivieren, möchten Sie eine Nachricht oder einen Toast anzeigen. Leider gibt es keine Möglichkeit zu überprüfen, ob der Nutzer die Ortungsdienste in der Google-Ortungsdienst-API deaktiviert hat. Dazu müssen Sie auf die Android-API zurückgreifen.

In Ihrer onCreateMethode:

    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;

Und verwenden Sie das locationEnabledFlag in Ihrer onConnectedMethode wie folgt:

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

AKTUALISIEREN

Das Dokument wird aktualisiert, LocationClient wird entfernt und die API unterstützt die Aktivierung von GPS mit einem Klick aus dem Dialogfeld:

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

Neuer Standortclient: FusedLocationProviderClient

  private FusedLocationProviderClient fusedLocationClient;

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

Es wird empfohlen, https://developer.android.com/training/location zu durchsuchen, bevor Sie Standortaufgaben ausführen.


9
Sie können SettingsApi.checkLocationSettings()damit überprüfen, ob der Benutzer die Ortungsdienste aktiviert hat (siehe hier: developer.google.com/android/reference/com/google/android/gms/… ).
Kaolick

3
LocationClient existiert nicht mehr. Eine aktualisierte und übersichtliche Anleitung zum Standort finden Sie in diesem Artikel: blog.teamtreehouse.com/beginners-guide-location-android
lm2a

1
Und Trainingsseite mit SettingsApi-Beispiel: developer.android.com/training/location/…
androidguy

2
Sie können auch einen Geo-Zaun mit erstellen LocationManager! Funktioniert die API für fusionierte Standorte auf Geräten ohne Google Play-Dienste?
Muhammad Babar

Dies kann ein weiterer besserer Weg sein, um den GPS-Aktivierungs- / Deaktivierungsstatus zu überprüfen 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

Nach meiner Erfahrung bedeutet "angemessenere Genauigkeit" keineswegs besser. Wenn Sie nicht sicherstellen möchten, dass GPS verwendet wird, ist LocationManager der einzige Weg. Wir verfolgen Fahrzeuge mit unserer App und, sofern mir nichts fehlt, bietet Google Play Services häufig sehr ungenaue Standorte.


2
Ja, meiner Erfahrung nach bieten Google Play Services manchmal einen ungenauen Standort.
VY

2
Ja, die Location Services-API von Google Play Services kann sehr irreführende Standortinformationen liefern. WiFi-Modems werden verschoben, WiFi-Modems werden mit falschen Standortinformationen aktualisiert (dh wenn der Standort von einem Android-Gerät gefälscht wird, das den Standort des WiFi-Modems aktualisiert), und es gibt eine Vielzahl anderer Umstände, die zu falschen Standortdaten aus der WiFi-Modem-Triangulation führen können. In allen unseren Apps, in denen ein genauer Standort erforderlich ist, verwenden wir nur GPS.
user1608385

27

Sie sollten die Standort-API von Google Play Services anstelle von LocationManager verwenden. Laut den Dokumenten:

Die Standort-APIs der Google Play-Dienste werden den Standort-APIs des Android-Frameworks (android.location) vorgezogen, um Ihrer App die Standorterkennung hinzuzufügen. Wenn Sie derzeit die Standort-APIs des Android-Frameworks verwenden, wird dringend empfohlen, so bald wie möglich zu den Standort-APIs der Google Play-Dienste zu wechseln.

Google sagt, warum Sie wechseln sollten:

Die Google Location Services-API, die Teil von Google Play Services ist, bietet ein leistungsfähigeres Framework auf hoher Ebene, das Standortanbieter, Benutzerbewegungen und Standortgenauigkeit automatisch verwaltet. Es verwaltet auch die Planung von Standortaktualisierungen basierend auf den von Ihnen angegebenen Stromverbrauchsparametern. In den meisten Fällen erzielen Sie mithilfe der Location Services-API eine bessere Akkuleistung sowie eine angemessenere Genauigkeit.


2
Haben Sie Links zu dieser Dokumentation, aus der diese Zitate stammen? Es wäre interessant zu sehen, ob Google jetzt etwas anderes sagt.
Edward Brey

3
Natürlich sagen sie das, weil sie Ihre Standortdaten wollen!
Flyview

Wenn Sie Ihrer App Google Play-Dienste hinzufügen und ein Nutzer Ihre App installiert, wird er aufgefordert, die Google Play-Dienste zu "aktualisieren", um Ihre App zu verwenden. Falls sein / ihr Telefon fast voll ist (mit WhatsApp-Memes und so) oder der Benutzer nicht über die Daten verfügt, entschuldigen Sie bitte meinen Freund
Dr. Deo

2
@Flyview Ja! Lol, so wie sie es ausdrücken, klingt es wie eine magische Lösung! Der größte Nachteil ist, dass Sie Google Play Services auf dem Gerät benötigen !!!
Varun

24

Ich verwende die Google Location Services-API seit einiger Zeit. Es hat Vorteile, da es die Komplexität mehrerer Quellen zur Positionsbestimmung zusammenfasst. Es ist jedoch zu stark gekapselt , sodass Sie bei einer seltsamen Position nicht feststellen können, woher diese seltsame Position stammt.

Im wirklichen Leben sind mehrere Freak-Werte aufgetaucht, die 10 Kilometer von der tatsächlichen Position entfernt sind. Die einzige Erklärung ist, dass diese verrückten Orte auf Fehler in Googles Wi-Fi- oder NWK-Datenbanken zurückzuführen sind - Fehler, die immer vorhanden sein werden, da sich die Wi-Fi- und Netzwerktopologien täglich ändern. Leider (und überraschenderweise) gibt Ihnen die API keine Informationen darüber, wie eine einzelne Position abgeleitet wurde.

Geben Sie hier die Bildbeschreibung ein

Dies führt zu den Problemen, dass Sie Freak-Werte herausfiltern müssen, die auf der Plausibilitätsprüfung von Geschwindigkeit, Beschleunigung, Peilung usw. basieren.

... oder kehren Sie zur guten alten Framework-API zurück und verwenden Sie nur GPS. Dies habe ich beschlossen, bis Google die fusionierte API verbessert.


7

Die Google Location Services-API , die Teil von Google Play Services ist, bietet ein leistungsfähigeres Framework auf hoher Ebene, das Standortanbieter , Benutzerbewegungen und Standortgenauigkeit automatisch verwaltet. Es verwaltet auch die Planung von Standortaktualisierungen basierend auf den von Ihnen angegebenen Stromverbrauchsparametern. In den meisten Fällen erzielen Sie mithilfe der Location Services-APIeine bessere Akkuleistung sowie eine angemessenere Genauigkeit.

Detailliertere Unterschiede zwischen der beiden APIs Google Play Service Location API und der Android Framework Location API finden Sie hier


Ich habe Ihre Antwort verwendet, um meine eigene Frage zu beantworten, wenn das in Ordnung ist. Vielen Dank! stackoverflow.com/questions/39852955/…
Leniaal

@ Leniaal, denkst du nicht, dass meine Antwort eine positive Bewertung verdient?
Dhruvam Gupta

Das ist ein 3 Jahre altes Dokument. Aber hier ist ein Plus 1
Drew

5

Ja, die Location Services-API von Google Play Services kann sehr irreführende Standortinformationen liefern. WiFi-Modems werden verschoben, WiFi-Modems werden mit falschen Standortinformationen aktualisiert (dh wenn der Standort von einem Android-Gerät gefälscht wird, das den Standort des WiFi-Modems aktualisiert), und es gibt eine Vielzahl anderer Umstände, die zu falschen Standortdaten aus der WiFi-Modem-Triangulation führen können. In allen unseren Apps, in denen ein genauer Standort erforderlich ist, verwenden wir nur GPS.


4

Unterschiede zwischen den beiden APIs Google Play Service Location API und Android Framework Location API basierend auf dem GPS-Dienst

FusedLocationProviderClient

  1. Beim ersten Abruf darf der Speicherort nicht null sein (dh: Eine andere App muss den zuletzt bekannten Speicherort in der GoogleplayService-Datenbank aktualisieren. Wenn er null ist, muss dies umgangen werden.)
  2. Beim nächsten sequentiellen requestLocationUpdates()Abrufen wird die Methode zum Abrufen des Speicherorts verwendet.
  3. Der Standortabruf basiert nur auf locationRequest.setInterval(milliseconds)und setFastestInterval(milliseconds)nicht auf der Änderung des Benutzerstandorts
  4. Der zurückgegebene LatLng-Wert enthält nur 7 Dezimalwerte (z. B. 11.9557996, 79.8234599), die nicht so genau sind
  5. Empfohlen, wenn für Ihre App-Anforderung die aktuelle Standortentfernung vernachlässigbar ist (50 - 100 Meter Genauigkeit).
  6. Wirksam im Batterieverbrauch.

LocationManager Api

  1. Der Benutzerstandortabruf wird mit locationManager.requestLocationUpdates () aufgerufen.
  2. Der Standortabruf basiert auf der Änderung des Benutzerstandorts und den Zeitintervallen locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, milliseconds, mindistance, Mylocationlistener)

  3. Der zurückgegebene LatLng-Wert enthält 14 Dezimalwerte (z. B. 11.94574594963342 79.81166719458997) mit genauen Positionswerten

  4. Empfohlen für standortbasierte Apps, wenn selbst in Metern mehr Genauigkeit erforderlich ist.
  5. Der Batterieverbrauch basiert auf dem Abrufintervall und der Abrufentfernung.

Hallo! 1 ° beträgt höchstens 111_111 Meter (20_000_000 / 180). 0,0000001 ° ist also 0,011 m = 1 cm. Ich weiß nicht, wo Sie eine bessere GPS-Auflösung benötigen. Und ich weiß nicht einmal, wie Sie eine bessere GPS-Auflösung erreichen können.
Babay
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.