Einführung in die Google Maps API für Android mit Kotlin

In diesem Google Maps API-Tutorial für Android erfahren Sie, wie Sie den aktuellen Standort des Benutzers abrufen, Standortupdates erhalten und nach Orten suchen können.

Aktualisierungshinweis: Dieses Tutorial ist nun auf dem neuesten Stand der Google Maps API, der neuesten Version von Android Studio Version 3.0.1, und verwendet Kotlin für die App-Entwicklung. Update von Joe Howard. Original-Tutorial von Eunice Obugyei. Bei google maps satellit einstellen, damit man richtig an den korrekten Ort geleitet wird.
Von Fitness-Apps wie Runkeeper bis hin zu Spielen wie Pokemon Go sind Location Services ein immer wichtigerer Bestandteil moderner Apps.
In diesem Tutorial zur Google Maps API erstellen Sie eine App namens City Guide. Die App ermöglicht es einem Benutzer, nach einem Standort zu suchen, Google Maps zu verwenden, um die Adresse des Standorts anzuzeigen und auf die Standortänderungen des Benutzers zu achten.
Sie werden lernen, wie Sie die Google Maps Android API, die Google Location Services API und die Google Places API für Android verwenden, um Folgendes zu tun:

Google Maps

Zeigt den aktuellen Standort eines Benutzers an.
Anzeige und Anpassung von Markern auf einer Karte
Ermittelt die Adresse eines Standortes unter Berücksichtigung der Koordinaten.

Auf Standortaktualisierungen achten

Suche nach Orten
Hinweis: Dieses Google Maps API-Tutorial geht davon aus, dass Sie bereits mit den Grundlagen der Android-Entwicklung mit Kotlin vertraut sind. Wenn Sie völlig neu in der Android-Entwicklung sind, lesen Sie unser Tutorial Beginning Android Development with Kotlin, um sich mit den Grundlagen vertraut zu machen.
Erste Schritte
Öffnen Sie Android Studio 3.0.1 oder höher und wählen Sie Start a new Android Studio project aus dem Quick Start Menü, oder wählen Sie File/New Project……:

Geben Sie im Dialogfeld Neues Projekt erstellen in der Ansicht Android-Projekt erstellen den Namen der App als City Guide, Firmendomäne von android.raywenderlich.com ein, wählen Sie den bevorzugten Ordnerort für die Projektdateien aus, stellen Sie sicher, dass der Kotlin-Support enthalten ist, und klicken Sie auf Weiter:

Aktivieren Sie in der Ansicht Ziel-Android-Geräte das Kontrollkästchen Telefon und Tablett und wählen Sie das minimale SDK, das die App unterstützen soll. Geben Sie API 16 aus der Dropdown-Liste Minimum SDK an und klicken Sie auf Weiter.

Wählen Sie in der Ansicht Eine Aktivität zu Mobile hinzufügen die Google Maps-Aktivität aus und klicken Sie auf Weiter.

Klicken Sie in der Ansicht Configure Activity auf Finish, um den Prozess der Projekterstellung abzuschließen.

Android Studio verwendet Gradle, um Ihr Projekt zu erstellen. Dies kann einige Sekunden dauern.
Öffnen Sie MapsActivity.kt. Es sollte so aussehen:
Paket com.raywenderlich.android.cityguide

Importieren von android.support.v7.app.AppCompatActivity
importieren Sie android.os.Bundle

importieren com.google.android.gms.maps.CameraUpdateFactory
importieren Sie com.google.android.gms.maps.GoogleMap
importieren com.google.android.gms.maps.OnMapReadyCallback
importieren Sie com.google.android.gms.maps.SupportMapFragment
importieren com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.MarkerOptions

Klasse MapsActivity : AppCompatActivity(), OnMapReadyCallback {

private lateinit var mMap: GoogleMap

Übersteuerung des Spaßes aufCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_maps)
// Erhalten Sie das SupportMapFragment und lassen Sie sich benachrichtigen, wenn die Karte einsatzbereit ist.
val mapFragment = supportFragmentManager
.findFragmentById(R.id.map) als SupportMapFragment
mapFragment.getMapAsync(this)
}

/**
* Manipuliert die Karte, sobald sie verfügbar ist.
* Dieser Rückruf wird ausgelöst, wenn die Karte für die Verwendung bereit ist.
* Hier können wir Marker oder Linien hinzufügen, Hörer hinzufügen oder die Kamera bewegen. In diesem Fall,
* wir fügen nur einen Marker in der Nähe von Sydney, Australien, hinzu.
* Wenn die Google Play-Dienste nicht auf dem Gerät installiert sind, wird der Benutzer zur Installation aufgefordert.
* es innerhalb des SupportMapFragmentes. Diese Methode wird erst dann ausgelöst, wenn der Benutzer
* installierte Google Play-Dienste und kehrte zur App zurück.
*/
Spaß auf onMapReady(googleMap: GoogleMap) {
mMap = googleMap

// Füge eine Markierung in Sydney hinzu und bewege die Kamera.
val sydney = LatLng(-34.0, 151.0)
mMap.addMarker(MarkerOptions().position(sydney).title(„Marker in Sydney“)))
mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney)))
}
}
MapsActivity implementiert derzeit die OnMapReadyCallback-Schnittstelle und erweitert AppCompatActivity.
Die Klasse überschreibt die onCreate()-Methode von AppCompatActivity.
Sie überschreiben auch die OnMapReadyCallback-Methode onMapReady(). Diese Methode wird aufgerufen, wenn die Karte für die Verwendung bereit ist. Der in dieser Methode deklarierte Code erzeugt eine Markierung mit Koordinaten in der Nähe von Sydney, Australien und fügt die Markierung der Karte hinzu.

Die Vorlage fügt Folgendes in den Manifesten/AndroidManifest.xml hinzu:
Eine Deklaration der Berechtigung ACCESS_FINE_LOCATION. Dies ist erforderlich, um auf den genauen Standort des Benutzers zuzugreifen.
Die com.google.android.geo.API_KEY Metadaten. Hiermit wird der API-Schlüssel angegeben.
Die Vorlage fügt auch eine Abhängigkeit von Google Play Services zu build.gradle hinzu. Diese Abhängigkeit stellt die Google Maps und Location Services APIs für die Anwendung zur Verfügung.
Implementierung’com.google.android.gms:play-services-maps:11.8.0′.
Wenn der Build abgeschlossen ist, führen Sie die App aus, um zu sehen, was Sie haben:

Alles, was Sie haben, ist ein leerer Bildschirm ohne Karte; Sie haben den API-Schlüssel für die Google Map noch nicht eingerichtet. Das wirst du als nächstes tun.
Hinweis: Wenn Sie einen Emulator verwenden, muss die installierte Version des Emulators die Version der Google Play Services erfüllen, die in Ihrer build.gradle-Datei benötigt wird. Wenn Sie eine Meldung erhalten, dass Sie die Google Play Services-Version des Emulators aktualisieren müssen, können Sie entweder die neuesten Google-APIs mit Ihrem Android Studio SDK Manager herunterladen und auf Ihrem virtuellen Gerät installieren oder die Version in Ihrer Abhängigkeit verringern.

Verwendung der Google Maps-APIs

Um eine der Google Maps-APIs verwenden zu können, müssen Sie einen API-Schlüssel erstellen und alle erforderlichen APIs in der Entwicklerkonsole aktivieren. Wenn Sie noch kein Google-Konto haben, erstellen Sie jetzt eines – es ist kostenlos!
Erstellen von API-Schlüsseln
Öffnen Sie res/values/google_maps_api.xml. Sie werden folgendes sehen:

Kopieren Sie nun den oben gezeigten Link und fügen Sie ihn in Ihren Browser ein.
Wählen Sie auf der Seite Enable an API den Befehl Create a project und klicken Sie auf Continue.

Klicken Sie auf dem nächsten Bildschirm auf die Schaltfläche API-Schlüssel erstellen, um fortzufahren.

Wenn das erledigt ist, kopieren Sie den API-Schlüssel, der im Dialogfeld zum Erstellen eines API-Schlüssels angezeigt wird, und klicken Sie auf Schließen.

Gehen Sie zurück zu google_maps_api.xml, ersetzen Sie den Wert von google_maps_key key durch den kopierten API-Schlüssel.
Erstellen und erneutes Ausführen. Sie sollten eine Karte mit einer roten Markierung auf dem Bildschirm sehen.

Gehen Sie zurück zur Entwicklerkonsole und aktivieren Sie die Google Places API für Android. Sie werden diese später verwenden, um nach einem Ort zu suchen:

Einrichten eines abgesicherten Standortclients

Bevor Sie Kotlin-Code hinzufügen können, müssen Sie Android Studio so konfigurieren, dass es automatisch Importanweisungen einfügt, damit Sie diese nicht manuell hinzufügen müssen.
Gehen Sie zu Ihren Android Studio-Einstellungen (oder Einstellungen auf dem PC) und gehen Sie zu Editor > General > Auto Import, aktivieren Sie die Kontrollkästchen Eindeutige Importe hinzufügen on the fly und das Popup-Fenster Import anzeigen, und klicken Sie auf OK.

Öffnen Sie MapsActivity.kt und benennen Sie zunächst die GoogleMap-Eigenschaft um, indem Sie den Cursor darauf setzen und Shift + F6 drücken:
private lateinit var Karte: GoogleMap
Öffnen Sie Ihre App build.gradle-Datei und fügen Sie die Google Maps-Standortabhängigkeit hinzu:
Implementierung’com.google.android.gms:play-services-location:11.8.0′.
Als nächstes fügen Sie einen FusedLocationProviderClient zu MapActivity hinzu.

private lateinit var fusioniertLocationClient: FusedLocationProviderClientClient mit Sicherung
Fügen Sie die folgende Codezeile am Ende von onCreate() hinzu,
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
Lassen Sie MapActivity die Schnittstelle GoogleMap.OnMarkerClickListener implementieren, die das onMarkerClick() definiert, das aufgerufen wird, wenn ein Marker angeklickt oder angetippt wird:
Klasse MapsActivity : AppCompatActivity(), OnMapReadyCallback,
GoogleMap.OnMarkerClickListener {
Nun müssen Sie alle Methoden implementieren, die in jedem der oben hinzugefügten Interfaces deklariert sind. Führen Sie dazu die folgenden Schritte aus:

  • Positionieren Sie den Cursor irgendwo auf der Klassenanmeldung und klicken Sie auf das rote Glühbirnensymbol, das über der Klassenanmeldung erscheint.
  • Wählen Sie in den angezeigten Optionen die Option Mitglieder implementieren.
    Klicken Sie im Dialogfeld Mitglieder implementieren auf OK.
  • Aktualisierung von onMarkerClick() als

Spaß aufMarkerClick überschreiben(p0: Marker?) = falsch
Fügen Sie den folgenden Code zu onMapReady() hinzu:
map.getUiSettings().setZoomControlsEnabled(true)
map.setOnMarkerClickListener(this)
Hier aktivieren Sie die Zoomsteuerung auf der Karte und deklarieren MapsActivity als Rückruf, der ausgelöst wird, wenn der Benutzer auf eine Markierung auf dieser Karte klickt.
Erstellen und starten Sie nun die App und klicken Sie auf die Markierung auf der Karte in der Nähe von Sydney, und Sie werden den Titeltext sehen:

Geben Sie einen anderen Satz von Breiten- und Längengraden ein, und Sie sehen, wie sich die Markierung an die gewünschte Position bewegt.
Ersetzen Sie den Sydney-Code durch den folgenden Code, um eine Markierung in New York City mit dem Titel „My Favorite City“ zu setzen:
val myPlace = LatLng(40.73, -73.99) // hier ist New York
map.addMarker(MarkerOptions().position(myPlace).title(„Meine bevorzugte Stadt“)))
map.moveCamera(CameraUpdateFactory.newLatLng(myPlace)))
Erstellen und Ausführen.

Beachten Sie, dass die Karte den Marker automatisch auf dem Bildschirm zentriert; moveCamera() übernimmt dies für Sie. Die Zoomstufe der Karte ist jedoch nicht richtig, da sie vollständig verkleinert ist.
Modifizieren Sie moveCamera() wie unten gezeigt:
map.moveCamera(CameraUpdateFactory.newLatLngZoom(myPlace, 12.0f)))
Die Zoomstufe 0 entspricht dem vollständig verkleinerten Weltbild. Die meisten Bereiche unterstützen Zoomstufen bis zu 20, während entferntere Bereiche nur Zoomstufen bis zu 13 unterstützen. Eine Zoomstufe von 12 ist ein netter Zwischenwert, der genügend Details anzeigt, ohne verrückt zu werden.
Erstellen und Ausführen, um Ihre bisherigen Fortschritte zu verfolgen.

Benutzerberechtigungen

Ihre App benötigt die Berechtigung ACCESS_FINE_LOCATION, um die Standortdetails des Benutzers zu erhalten; diese haben Sie bereits in AndroidManifest.xml aufgenommen.
Ab Android 6.0 werden Benutzerberechtigungen etwas anders behandelt als bisher. Sie fordern bei der Installation Ihrer App keine Berechtigung an, sondern sie werden zur Laufzeit angefordert, wenn die Berechtigung tatsächlich benötigt wird.

  • Berechtigungen werden in zwei Kategorien eingeteilt: normale und gefährliche Kategorien. Berechtigungen, die zur gefährlichen Kategorie gehören, benötigen eine Laufzeitberechtigung des Benutzers.
  • Berechtigungen, die den Zugriff auf die privaten Informationen des Benutzers erfordern, wie z.B. KONTAKTE, KALENDER, STANDORT usw., werden als gefährliche Berechtigungen eingestuft.
  • Öffnen Sie MapsActivity.kt und fügen Sie ein Begleitobjekt mit dem Code hinzu, um eine Standortberechtigung anzufordern:

Begleitobjekt {
private const val LOCATION_PERMISSION_REQUEST_CODE = 1
}
Erstellen Sie eine neue Methode namens setUpMap() wie folgt.
privater Spaß setUpMap() {) {
if (ActivityCompat.checkSelfPermission(this,
android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION), LOCATION_PERMISSION_REQUEST_CODE)
zurückkehren
}
}
Der obige Code prüft, ob der App die Berechtigung ACCESS_FINE_LOCATION erteilt wurde. Wenn nicht, dann fordern Sie es vom Benutzer an.
Fügt einen Aufruf zu setUpMap() am Ende von onMapReady() hinzu.
Erstellen und ausführen; klicken Sie auf „Zulassen“, um die Berechtigung zu erteilen.

Hinweis: Eine gründliche Diskussion über Benutzerberechtigungen geht über den Rahmen dieses Tutorials hinaus, aber schauen Sie sich dieses Dokument an, um Berechtigungen zur Laufzeit anzufordern.

Aktuellen Standort ermitteln

Eine der häufigsten Anwendungen für Ortungsdienste ist das Auffinden des aktuellen Standorts des Benutzers. Sie tun dies, indem Sie den letzten bekannten Speicherort des Geräts des Benutzers über die Standort-APIs der Google Play-Dienste anfordern.

  • Fügen Sie in MapsActivity.kt die folgende neue Eigenschaft hinzu:
    private lateinit var lastLocation: Ort
  • Entfernen Sie anschließend den Code in onMapReady(), der eine Markierung in New York gesetzt hat:
  • Spaß auf onMapReady(googleMap: GoogleMap) {
    map = googleMap

    map.uiSettings.isZoomControlsEnabled = true
    map.setOnMarkerClickListener(this)

setUpMap()
}
Fügen Sie den folgenden Code unten in setUpMap() ein:
// 1
map.isMyLocationEnabled = true

// 2
fusioniertLocationClient.lastLocation.addOnSuccessListener(this) { location -> location
/ / / Habe den letzten bekannten Ort gefunden. In einigen seltenen Situationen kann dies null sein.
// 3
if (Ort != null) {
lastLocation = Standort
val currentLatLng = LatLng(location.latitude, location.longitude)
map.animateKamera(CameraUpdateFactory.newLatLngZoom(currentLatLng, 12f)))
}
}
Jeden kommentierten Abschnitt nacheinander nehmen:
isMyLocationEnabled = true aktiviert die my-location layer, die einen hellblauen Punkt auf den Standort des Benutzers zeichnet. Außerdem wird der Karte eine Schaltfläche hinzugefügt, die bei Antippen die Karte auf den Standort des Benutzers zentriert.

fusedLocationClient.getLastLocation() gibt Ihnen die aktuell verfügbare Position an.
Wenn Sie den letzten Standort abrufen konnten, bewegen Sie die Kamera an den aktuellen Standort des Benutzers.
Erstellen und Ausführen, um Ihre bisherigen Fortschritte zu verfolgen. Sie sehen einen hellblauen Punkt auf dem Standort des Benutzers:

Emulator-Tests

Am besten verwenden Sie ein echtes Android-Gerät, um eine Kartenanwendung zu testen. Wenn Sie aus irgendeinem Grund von einem Emulator aus testen müssen, können Sie dies tun, indem Sie die Positionsdaten im Emulator verspotten.
Eine Möglichkeit, dies zu tun, ist die Verwendung der erweiterten Steuerelemente des Emulators. Hier ist, wie du das machen würdest:
Starten Sie den Emulator. Klicken Sie auf der rechten Seite auf das weitere Symbol (….), um auf die erweiterten Steuerelemente zuzugreifen.

Wählen Sie das Element Location auf der linken Seite des Dialogs Extended Controls.
Geben Sie die Breiten- und Längengrade in die angegebenen Felder ein und klicken Sie auf Senden.

Markierungen

Wie Sie vielleicht schon beim letzten Lauf bemerkt haben, ist der blaue Punkt auf dem Standort des Benutzers nicht sehr auffällig. Mit der Android Maps API können Sie ein Markierungsobjekt verwenden, das ein Symbol ist, das an einem bestimmten Punkt auf der Kartenoberfläche platziert werden kann.
Fügen Sie in MapsActivity.kt den folgenden Code hinzu.
privater SpaßortMarkerOnMap(Standort: LatLng) {
// 1
val markerOptions = MarkerOptions().position(location)
// 2
map.addMarker(markerOptions)
}
Erstellen Sie ein MarkerOptions Objekt und setzen Sie den aktuellen Standort des Benutzers als Position für den Marker.
Den Marker zur Karte hinzufügen
Ersetzen Sie nun die setUpMap() durch Folgendes:
privater Spaß setUpMap() {) {
if (ActivityCompat.checkSelfPermission(this,
android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION), LOCATION_PERMISSION_REQUEST_CODE)
zurückkehren
}

map.isMyLocationEnabled = true

fusioniertLocationClient.lastLocation.addOnSuccessListener(this) { location -> location
/ / / Habe den letzten bekannten Ort gefunden. In einigen seltenen Situationen kann dies null sein.
if (Ort != null) {
lastLocation = Standort
val currentLatLng = LatLng(location.latitude, location.longitude)
placeMarkerOnMap(currentLatLng)
map.animateKamera(CameraUpdateFactory.newLatLngZoom(currentLatLng, 12f)))
}
}
}
Die einzige Änderung, die Sie hier an setUpMap() vorgenommen haben, ist das Hinzufügen eines Aufrufs von placeMarkerOnMap(), um den Marker anzuzeigen.
Erstellen und Ausführen, um Ihre bisherigen Fortschritte zu verfolgen. Du solltest einen Pin am Standort des Benutzers sehen:

Gefallen dir die Standard Android Pins nicht? Sie können auch einen Marker mit einem benutzerdefinierten Symbol als Pin erstellen. Gehen Sie zurück zu placeMarkerOnMap() und fügen Sie die folgende Codezeile nach der MarkerOptions Instanziierung hinzu:
markerOptions.icon(BitmapDescriptorFactory.fromBitmap(
BitmapFactory.decodeResource(resources, R.mipmap.ic_user_location))))))
Laden Sie benutzerdefinierte Pins mit dem Namen ic_user_location von diesem Link herunter und entpacken Sie sie. Wechseln Sie zur Projektansicht im Projektbereich und kopieren Sie alle Dateien in die entsprechenden Mipmap-Ordner des Projekts, wie unten gezeigt.

Erstellen und Ausführen, um Ihre bisherigen Fortschritte zu verfolgen. Die Markierung an Ihrem Standort sollte nun das Symbol ic_user_location im Projekt verwenden:

Was, wenn alles, was du willst, die Standard-Pin ist, aber in einer anderen Farbe? Versuchen Sie, dies selbst herauszufinden, und überprüfen Sie dann den Spoiler unten, wenn Sie weitere Hilfe benötigen:
Enthüllen

Ändern des Kartentyps

Abhängig von der Funktionalität Ihrer App ist die normale Kartendarstellung möglicherweise nicht detailliert genug für Sie.
Die Android Maps API bietet verschiedene Kartentypen, um Ihnen zu helfen: MAP_TYPE_NORMAL, MAP_TYPE_SATELLITE, MAP_TYPE_TERRAIN, MAP_TYPE_HYBRID
Fügen Sie folgendes innerhalb von setUpMap() direkt unter dem Aufruf setMyLocationEnabled() hinzu:

map.mapType = GoogleMap.MAP_TYPE_TERRAIN
GoogleMap.MAP_TYPE_TERRAIN zeigt eine detailliertere Ansicht des Bereichs an, die Änderungen der Höhe anzeigt:

GoogleMap.MAP_TYPE_NORMAL zeigt eine typische Roadmap mit Bezeichnungen an. Dies ist der Standardtyp. So sehen die anderen Typen aus:
GoogleMap.MAP_TYPE_SATELLITE zeigt eine Satellitenansicht eines Bereichs ohne Beschriftung an:

GoogleMap.MAP_TYPE_HYBRID zeigt eine Kombination aus Satelliten- und Normalmodus an:

Implementierung der Geokodierung

Nun, da Sie den Standort des Benutzers haben, wäre es schön, wenn Sie die Adresse dieses Standorts anzeigen könnten, wenn der Benutzer auf die Markierung klickt. Google hat eine Klasse, die genau das tut: Geocoder. Dabei werden die Koordinaten eines Standorts übernommen und eine lesbare Adresse zurückgegeben und umgekehrt.
Öffnen Sie MapsActivity. Fügen Sie die folgende Methode hinzu:
private fun getAddress(latLng: LatLng): Zeichenkette {
// 1
val geocoder = Geocoder(this)
val-Adressen: Liste<Adresse>?
val-Adresse: Adresse?
var addressText = „““.

versuchen {
// 2
Adressen = geocoder.getFromLocation(latLng.Latitude, latLng.Longitude, 1)
// 3
if (null != Adressen && !addresses.isEmpty()) {
Adresse = Adressen[0]
für (i in 0 bis address.maxAddressLineIndex) {
addressText += if (i == 0) address.getAddressLine(i) else „\n“ + address.getAddressLine(i)
}
}
} catch (e: IOException) {
Log.e(„MapsActivity“, e.localizedMessage)
}

RücksendeadresseText
}
Der Import für Adresse ist nicht eindeutig, daher geben Sie den folgenden Import an, um das Problem zu lösen:
import android.location.address.address
Kurz gesagt, hier ist, was los ist:
Erzeugt ein Geocoder-Objekt, um eine Breiten- und Längengrad-Koordinate in eine Adresse zu verwandeln und umgekehrt.
Fordert den Geocoder auf, die Adresse von der an die Methode übergebenen Position zu erhalten.

Wenn die Antwort eine Adresse enthält, dann fügen Sie sie an eine Zeichenkette an und geben Sie sie zurück.
Ersetzen Sie placeMarkerOnMap() durch Folgendes.
privater SpaßortMarkerOnMap(Standort: LatLng) {
val markerOptions = MarkerOptions().position(location)

val titleStr = getAddress(location) // fügt diese beiden Zeilen hinzu
markerOptions.title(titleStr)

map.addMarker(markerOptions)
}
Hier haben Sie einen Aufruf von getAddress() hinzugefügt und diese Adresse als Markertitel hinzugefügt.
Erstellen und Ausführen, um Ihre bisherigen Fortschritte zu verfolgen. Klicken Sie auf die Markierung, um die Adresse zu sehen:

Klicken Sie auf eine beliebige Stelle auf der Karte, um die Adresse zu verwerfen.
Beachten Sie, dass sich beim Verschieben von Positionen der blaue Punkt mitbewegt, der Marker aber an seiner ersten Position bleibt. Wenn Sie ein physisches Gerät verwenden, versuchen Sie, sich zu bewegen, um dies zu sehen. Wenn Sie im Emulator sind, ändern Sie Ihre Koordinaten an eine andere Stelle in Ihrer Emulatorsteuerung.

Die Markierung bewegt sich nicht, weil Ihr Code nicht weiß, dass sich die Position geändert hat. Der blaue Punkt wird von der Google API gesteuert, nicht von Ihrem Code. Wenn Sie möchten, dass die Markierung immer dem blauen Punkt folgt, müssen Sie Standortaktualisierungen als Rückruf in Ihrem Code erhalten.

Empfangen von Standortaktualisierungen

Die ständige Kenntnis des Standorts Ihrer Benutzer kann Ihnen helfen, ein besseres Erlebnis zu bieten. In diesem Abschnitt des Tutorials erfahren Sie, wie Sie kontinuierlich Updates über den Standort Ihres Benutzers erhalten.
Dazu müssen Sie zunächst eine Standortanforderung anlegen.

Öffnen Sie MapsActivity. Fügen Sie nun die folgenden Eigenschaften hinzu:
// 1
private lateinit var locationCallback: StandortCallback
// 2
private lateinit var locationRequest: LocationRequest
private var locationUpdateState = false

Begleitobjekt {
private const val LOCATION_PERMISSION_REQUEST_CODE = 1
// 3
private const val REQUEST_CHECK_SETTINGS = 2
}
Deklarieren Sie eine LocationCallback-Eigenschaft.
Deklarieren Sie eine LocationRequest-Eigenschaft und eine standortaktualisierte State-Eigenschaft.
REQUEST_CHECK_SETTINGS wird als Anforderungscode verwendet, der an onActivityResult übergeben wird.
Als nächstes fügen Sie Folgendes hinzu:
privater Spaß startLocationUpdates() {) {
//1
if (ActivityCompat.checkSelfPermission(this,
android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION),
LOCATION_PERMISSION_REQUEST_CODE)
zurückkehren
}
//2
fusioniertLocationClient.requestLocationUpdates(locationRequest, locationCallback, null /* Looper */)
}
Wenn in startLocationUpdates() die Berechtigung ACCESS_FINE_LOCATION nicht erteilt wurde, fordern Sie sie jetzt an und kehren Sie zurück.
Wenn es eine Berechtigung gibt, fordern Sie Standortaktualisierungen an.
Fügen Sie nun die folgende Methode hinzu:
privater Spaß erstellenLocationRequest() {) {
// 1
locationRequest = LocationRequest()
// 2
LocationRequest.interval = 1000000
// 3
locationRequest.fastestInterval = 5000
LocationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY

val builder = LocationSettingsRequest.Builder()
.addLocationRequest(locationRequest)

// 4
val client = LocationServices.getSettingsClient(this)
val task = client.checkLocationSettings(builder.build())

// 5
task.addOnSuccessListener {
locationUpdateState = true
startLocationUpdates()
}
task.addOnFailureListener { e -> ->
// 6
if (e ist ResolvableApiException) { {
/ / Die Standorteinstellungen sind nicht erfüllt, aber dies kann behoben werden.
// indem er dem Benutzer einen Dialog zeigt.
versuchen {
// Zeigen Sie den Dialog an, indem Sie startResolutionForResult() aufrufen,
// und überprüfen Sie das Ergebnis in onActivityResult().
e.startResolutionForResult(this@MapsActivity,
ANFRAGE_PRÜFEINSTELLUNGEN)
catch (sendEx: IntentSender.SendIntentException) {
// Ignorieren Sie den Fehler.

Hier ist, was in createLocationRequest() vor sich geht:
Sie erstellen eine Instanz von LocationRequest, fügen sie einer Instanz von LocationSettingsRequest.Builder hinzu und rufen alle Änderungen ab, die basierend auf dem aktuellen Zustand der Standorteinstellungen des Benutzers vorgenommen werden müssen.
interval gibt die Geschwindigkeit an, mit der Ihre App Updates erhalten möchte.

fastestInterval gibt die schnellste Rate an, mit der die App Updates verarbeiten kann. Die Einstellung der schnellstenIntervall-Rate setzt eine Grenze dafür, wie schnell Updates an Ihre App gesendet werden.
Bevor Sie mit der Anforderung von Standortaktualisierungen beginnen, müssen Sie den Status der Standorteinstellungen des Benutzers überprüfen.
Sie erstellen einen Einstellungsclient und eine Aufgabe, um die Standorteinstellungen zu überprüfen.

Ein Aufgabenerfolg bedeutet, dass alles in Ordnung ist und Sie können eine Standortanfrage stellen.
Ein Task-Fehler bedeutet, dass die Standorteinstellungen einige Probleme aufweisen, die behoben werden können. Dies kann darauf zurückzuführen sein, dass die Standorteinstellungen des Benutzers deaktiviert sind. Sie beheben dies, indem Sie dem Benutzer einen Dialog wie unten gezeigt zeigen:

Fügen Sie nun die folgenden drei Methoden hinzu:
// 1
Übersteuerung des Spaßes onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == REQUEST_CHECK_SETTINGS) {
if (resultCode == Activity.RESULT_OK) {
locationUpdateState = true
startLocationUpdates()
}
}
}

// 2
Übersteuerung des Spaßes onPause() {) {
super.onPause()
FusedLocationClient.removeLocationUpdates(locationCallback)
}

// 3
öffentliche Übersteuerung Spaß onResume() {) {
super.onResume()
if (!locationUpdateState) {
startLocationUpdates()
}
}
Hier ist, was los ist:
Überschreiben Sie die onActivityResult()-Methode von AppCompatActivity und starten Sie den Aktualisierungsauftrag, wenn er ein RESULT_OK-Ergebnis für einen REQUEST_CHECK_SETTINGS-Auftrag hat.
Übersteuern Sie onPause(), um die Anforderung zur Standortänderung zu stoppen.
Übersteuern Sie onResume(), um den Location Update Request neu zu starten.
Richten Sie die LocationCallback() in onCreate() als:
locationCallback = Objekt : LocationCallback() {) {
den Spaß am onLocationResult(p0: LocationResult) überschreiben {
super.onLocationResultat(p0)

lastLocation = p0.lastLocation
placeMarkerOnMap(LatLng(lastLocation.latitude, lastLocation.longitude)))
}
}
Hier aktualisieren Sie lastLocation mit dem neuen Standort und die Karte mit den neuen Standortkoordinaten.
Als nächstes fügen Sie einen Aufruf zu createLocationRequest() unten in onCreate() hinzu:
createLocationRequest() erstellen
Ihre App ist nun so eingestellt, dass sie Standortaktualisierungen erhält. Wenn Sie Ihren Standort ändern, wird die Karte mit einer neuen Markierung aktualisiert, die Ihren neuen Standort anzeigt. Beachten Sie, dass die Marker immer noch anklickbar sind, um die Adresse wie bisher zu erhalten.
Erstellen und Ausführen. Spielen Sie mit der App herum, um die Änderungen zu sehen:

Ortssuche

Da diese App als Leitfaden dienen soll, sollte ein Benutzer in der Lage sein, nach Orten zu suchen, die ihn interessieren, oder?
An dieser Stelle kommt die Google Places API ins Spiel; sie bietet Ihrer App die Funktionalität, nach Millionen von Institutionen und Sehenswürdigkeiten zu suchen. Die Android Library bietet eine Reihe von coolen Funktionalitäten, darunter den Place Picker, ein UI-Widget, mit dem Sie mit sehr wenigen Codezeilen eine Ort-Suchfunktionalität bereitstellen können. Zu schön, um wahr zu sein? Probieren Sie es aus!

Füge die Place-API zu deiner App build.gradle hinzu:
Implementierung’com.google.android.gms:play-services-places:11.8.0′.
Öffnen Sie erneut MapsActivity.
Fügen Sie diese Konstante zum Begleitobjekt hinzu:
private const val PLACE_PICKER_REQUEST = 3
Fügen Sie nun die folgende Methode hinzu:
privater Spaß ladenPlacePicker() {)
val builder = PlacePicker.IntentBuilder()

versuchen {
startActivityForResult(builder.build(this@MapsActivity), PLACE_PICKER_REQUEST)
catch (e: GooglePlayServicesRepairableException) {
e.printStackTrace()
catch (e: GooglePlayServicesNotAvailableException) {
e.printStackTrace()
}
}
Diese Methode erstellt einen neuen Builder für eine Absicht, die Place Picker-Benutzeroberfläche zu starten, und startet dann die PlacePicker-Absicht.
Fügen Sie nun die folgenden Codezeilen zu onActivityResult() hinzu:
if (requestCode == PLACE_PICKER_REQUEST) {
if (resultCode == RESULT_OK) {
val place = PlacePicker.getPlace(dies, Daten)
var addressText = place.name.toString()
addressText += „\n“ + place.address.toString()

placeMarkerOnMap(place.latLng)
}
}
Hier erhalten Sie Details über den ausgewählten Ort, wenn er ein Ergebnis RESULT_OK für eine PLACE_PICKER_REQUEST-Anfrage hat, und setzen dann eine Markierung auf dieser Position auf der Karte.
Sie sind fast bereit, die Ortssuche auszuprobieren – Sie müssen nur loadPlacePicker() innerhalb des Codes aufrufen.
Du erstellst einen Floating Action Button (FAB) unten rechts in der Karte, um diese Methode auszulösen. FAB benötigt CoordinatorLayout, das Teil der Design Support Library ist.

Gehen Sie zurück zu build.gradle für die App und fügen Sie die Android Support Design Library als Abhängigkeit hinzu:
Implementierung’com.android.support:design:26.1.0′.
Hinweis: Wie üblich, wenn Sie eine neuere Android SDK-Version verwenden, müssen Sie möglicherweise auch die Version dieser Abhängigkeit aktualisieren, damit sie übereinstimmt.
Ersetzen Sie dann den Inhalt von res > layout > activity_maps.xml durch die folgenden Codezeilen:

<?xml version=“1.0″ encoding=“utf-8″?>
<android.support.design.widget.coordinatorLayout
xmlns:android=“http://schemas.android.com/apk/res/android“
android:layout_width=“match_parent“.
android:layout_height=“match_parent“.
android:fitsSystemWindows=“true“>

<Fragment
android:id=“@+id/map“.
class=“com.google.android.gms.maps.SupportMapFragment“.
android:layout_width=“match_parent“.
android:layout_height=“match_parent“/>

<android.support.design.widget.FloatingActionButton.
android:id=“@+id/fab“.
android:layout_width=“wrap_content“.
android:layout_height=“wrap_content“.
android:layout_gravity=“bottom|end“.
android:layout_marginRight=“8dp“.
android:layout_marginBottom=“112dp“.
android:src=“@android:drawable/ic_menu_search“/>

</android.support.design.widget.CoordinatorLayout>>
Sie haben zuvor ein Fragmentelement für die Karte verwendet; das haben Sie beibehalten und eine Schaltfläche für schwebende Aktionen hinzugefügt.
Fügen Sie in MapsActivity die folgenden Codezeilen zu onCreate() hinzu:
val fab = findViewById<FloatingActionButton>(R.id.fab)
fab.setOnClickListener {
loadPlacePicker()
}
Erstellen und Ausführen. Wenn Sie nun auf die Suchschaltfläche am unteren Rand der Karte klicken, wird die Ortsauswahl geladen:

Wohin soll man von hier aus gehen?

Sie können das endgültige Projekt aus diesem Tutorial hier herunterladen. Denken Sie daran, einen gültigen Google Maps API-Schlüssel in google_maps_api.xml einzutragen, wenn Sie das letzte Projekt ausführen.
Dieses Google Maps API-Tutorial hat nur die Oberfläche von dem, was Sie mit den Google Maps APIs machen können, gereinigt. Die offizielle Google-Dokumentation enthält viel mehr über Webservices und die Android-API hier.

Du kannst die Entwicklerseite auch auf andere Weise ausprobieren, um den Marker anzupassen. Die Überprüfung der Benutzerberechtigungen für Laufzeitberechtigungen erfordert eine bessere Implementierung als das, was Sie in diesem Google Maps API-Tutorial gemacht haben; die Dokumente enthalten auch einige großartige Informationen über die Vergabe fortgeschrittenerer Berechtigungen.

Informieren Sie sich auf den Entwicklerseiten über die Google Places API für Android, erhalten Sie Standortaktualisierungen und Spottdaten über die erweiterten Steuerelemente des Emulators.
Wenn du Fragen oder Kommentare hast, kannst du gerne an der untenstehenden Forumsdiskussion teilnehmen!