Manifest-Eintrag
Wenn die App den Standort bestimmen will, benötigt sie dafür eine Berechtigung, die in der Manifestdatei der App zu hinterlegen ist.Im Projektordner app/manifests/AndroidManifest.xml anklicken. In der xml-Datei vor das Tag application ein Tag für die Benutzerberechtigungen (uses-permission) eintragen. Es wird die Berechtigung benötigt, den Standort sehr genau (ACCESS_FINE_LOCATION) oder wenigstens in etwa (ACCESS_COARSE_LOCATION) festzustellen.
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="de.willemer.wobinich"> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> <application ...
Abhängigkeiten in build.gradle
Unter Gradle Scripts die Datei build.gradle (Module: app) anklicken. Dort wird in den Bereich dependencies { als letztes ein Verweis auf die Location-Dienste der Google-Play-Services eingetragen:dependencies { implementation ... ... implementation 'com.google.android.gms:play-services-location:11.8.0' }Die Versionsnummer kann ein Problem darstellen. Aus diesem Grund kann es sinnvoll sein, die Bibliothek nicht direkt einzutragen, sondern über das Android Studio suchen zu lassen.
- File|Project Structure: Der passende Dialog erscheint.
- In der linken Spalte sieht man unter Modules den Punkt app. Anklicken!
- Aus den Reitern wählt man den Punkt Dependencies. Es erscheint eine Liste der Abhängigkeiten.
- Auf der rechten Seite der Liste klickt man das Pluszeichen an, aus dem Menü den Punkt Library Dependeny. Ein neuer Dialog erscheint.
- In der obersten Zeile kann ein Suchbegriff eingegeben werden. Hier geben Sie ein: com.google.android.gms:play-services und klicken auf die Lupe.
- Wählen Sie den Punkt aus der location enthält. Gibt es keinen, nehmen Sie den reinen com.google.android.gms:play-services (beispielsweise in der Version 12.0.1).
- Bestätigen Sie alles mit OK.
- Wenden Sie sich mit dem Editor der build.gradle zu.
- Ergänzen Sie ggf. von Hand
com.google.android.gms:play-services
zucom.google.android.gms:play-services-location
Sofern Sie nicht viele Pakete aus der Google-Play-Bibliothek verwenden, reduziert das Hinzufügen von -location die APK-Größe.
- Klicken Sie auf Sync Now, das immer erscheint, wenn Sie die build.gradle verändern.
Activity-Anpassungen
In der Activity, die die Position nutzen soll, muss geprüft werden, ob die API verfügbar ist. Dazu wird die Methode onCreate um einige Zeilen ergänzt:@Override protected void onCreate(Bundle savedInstanceState) { // ... // API-Verfügbarkeit prüfen GoogleApiAvailability availability = GoogleApiAvailability.getInstance(); int result = availability.isGooglePlayServicesAvailable(this); if (result != ConnectionResult.SUCCESS) { if (!availability.isUserResolvableError(result)) { // Hier Warnung ausgeben, dass die API nicht zugreifbar ist. } } // ... }Beim Start der App wird überprüft, ob die App überhaupt das Recht hat, auf den Standort zu schauen.
int erlaubt = ActivityCompat.checkSelfPermission(this, ACCESS_FINE_LOCATION); if (erlaubt == PERMISSION_GRANTED) { holeStandort(); } else { // Erlaubnis noch nicht erteilt, frage nach! ActivityCompat.requestPermissions(this, new String[] { ACCESS_FINE_LOCATION }, LOCATION_PERMISSION_REQUEST); }Die Request-Anforderung läuft asynchron. Um das Ergebnis zu erhalten, überschreiben Sie die Methode onRequestPermissionsResult der Activity, in der die Berechtigung erfragt wird.
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == LOCATION_PERMISSION_REQUEST) { if (grantResults[0] != PERMISSION_GRANTED) { // Nur COARSE-Location erlaubt holeStandort(); } } }Nachdem die Berechtigung erlangt ist, kann der Standort bestimmt werden. Dies übernimmt die Methode holeStandort, die oben bereits zwei Mal aufgerufen wurde.
void holeStandort() { FusedLocationProviderClient fusedLocationClient; fusedLocationClient = LocationServices.getFusedLocationProviderClient(this); if ( ActivityCompat.checkSelfPermission(this, ACCESS_FINE_LOCATION) ==PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(this, ACCESS_COARSE_LOCATION)==PERMISSION_GRANTED) { fusedLocationClient.getLastLocation().addOnSuccessListener( this, new OnSuccessListenerDas ermittelte Objekt der Klasse Location kann mit den Methoden getLatitude und getLongitude nach der Position befragt werden.() { @Override public void onSuccess(Location location) { // location enthält die aktuelle Position } }); } }
Geocoder
Aus der Position Breiten- und Längengrad lässt sich über das Internet leicht ermitteln, wo man ist. Dazu wird die Berechtigung für das Internet benötigt, die in der Datei AndroidManifest.xml eingetragen sein muss:<uses-permission android:name="android.permission.INTERNET"/> </manifest>Die Wandlung übernimmt ein Geocoder, der mit der Regionsumgebung (Locale) erzeugt wird und der dann aus der Location eine Liste von Address macht, die an den Positionen für Breiten- und Längengrad zu finden sind. Meist interessiert nur die erste Adresse.
Jede Adresse kann wiederum nach der kompletten Adresszeile (getAdsressLine) oder Details wie Ort (getLocality), PLZ (getPostalCode) oder Land (getCountryName) befragt werden.
Die folgende Methode ermittelt die Adresse für die übergebene Location und erstellt daraus einen für den Benutzer lesbaren String. Durch Änderungen an der Variable adrZahl können auch mehrere Adressen geholt werden.
import android.location.Address; import android.location.Geocoder; import android.location.Location; // ... String getAdressStr(Location location) { String antwort = ""; if (location == null) { antwort = "Keine Location"; } else if (!Geocoder.isPresent()) { antwort = "Kein Geocoder vorhanden"; } else { Geocoder gc = new Geocoder(this, Locale.getDefault()); try { int adrZahl = 1; // wie viele Adressen? List<Address> adressliste = gc.getFromLocation( location.getLatitude(), location.getLongitude(), adrZahl); StringBuilder strSammel = new StringBuilder(); for (int i=0; i<adressliste.size(); i++) { Address adr = adressliste.get(i); for (int j=0; j<adr.getMaxAddressLineIndex(); j++) { strSammel.append(adr.getAddressLine(j)).append("\n"); } strSammel.append(adr.getLocality()).append("\n"); strSammel.append(adr.getPostalCode()).append("\n"); strSammel.append(adr.getCountryName()); } antwort = strSammel.toString(); } catch (IOException e) { antwort = "IO-Exception"; } } return antwort; }