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.LocationListener
und die zweite verwendet Google Play Services-APIs com.google.android.gms.location.LocationListener
. Lassen Sie uns beide durchgehen.
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 LocationManager
vom System erhalten, das implementieren LocationListener
und das requestLocationUpdates
auf 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!
- 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.ConnectionCallbacks
und GooglePlayServicesClient.OnConnectionFailedListener
Schnittstellen 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 location
ist 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.LocationListener
Schnittstelle 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 onConnected
Rückruf befinden muss, sonst erhalten Sie eine, IllegalStateException
weil 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 onLocationChanged
niemals 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 onCreate
Methode:
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 locationEnabled
Flag in Ihrer onConnected
Methode 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.