Android für Fortgeschrittene mit Kotlin 04.1: Google Maps für Android

Dieses Codelab ist Teil des Kurses „Advanced Android in Kotlin“. Sie können den größten Nutzen aus diesem Kurs ziehen, wenn Sie die Codelabs der Reihe nach durcharbeiten. Das ist jedoch nicht zwingend erforderlich. Alle Codelabs des Kurses sind auf der Landingpage für Codelabs zu „Android für Fortgeschrittene mit Kotlin“ aufgeführt.

Wenn Sie Apps mit Google Maps entwickeln, können Sie Ihrer App Funktionen wie Satellitenbilder, robuste UI-Steuerelemente für Karten, Standortverfolgung und Standortmarkierungen hinzufügen. Sie können Google Maps um Informationen aus Ihrem eigenen Datensatz ergänzen, z. B. um die Standorte bekannter Angel- oder Klettergebiete. Sie können auch Spiele erstellen, in denen der Spieler die physische Welt erkundet, z. B. eine Schatzsuche oder sogar Augmented Reality-Spiele.

In dieser Lektion erstellen Sie eine Google Maps-App namens „Wander“, in der benutzerdefinierte Karten angezeigt werden und der Standort des Nutzers zu sehen ist.

Vorbereitung

Kenntnisse in folgenden Bereichen:

  • So erstellen Sie eine einfache Android-App und führen sie mit Android Studio aus.
  • Ressourcen wie Strings erstellen und verwalten
  • Code umgestalten und Variablen mit Android Studio umbenennen
  • Google Maps als Nutzer verwenden
  • Laufzeitberechtigungen festlegen

Lerninhalte

  • API-Schlüssel über die Google API Console abrufen und für Ihre App registrieren
  • Google Maps in Ihre App einbinden
  • Verschiedene Kartentypen anzeigen
  • Google Maps-Karte gestalten
  • Markierungen zur Karte hinzufügen
  • Nutzer in die Lage versetzen, eine Markierung auf einem POI zu platzieren
  • Standortermittlung aktivieren
  • Die App Wander erstellen, in die eine Google-Karte eingebettet ist
  • Benutzerdefinierte Funktionen für Ihre App erstellen, z. B. Markierungen und Formatierung
  • Standort-Tracking in Ihrer App aktivieren

In diesem Codelab erstellen Sie die App Wander, in der eine Google-Karte mit benutzerdefinierten Stilen angezeigt wird. Mit der Wander-App können Sie Markierungen an Orten platzieren, Overlays hinzufügen und Ihren Standort in Echtzeit sehen.

Für das Maps SDK for Android ist ein API-Schlüssel erforderlich. Um den API-Schlüssel zu erhalten, registrieren Sie Ihr Projekt auf der Seite APIs & Dienste. Der API-Schlüssel ist an ein digitales Zertifikat gebunden, das die App mit ihrem Autor verknüpft. Weitere Informationen zur Verwendung digitaler Zertifikate und zum Signieren Ihrer App finden Sie unter App signieren.

In diesem Codelab verwenden Sie den API-Schlüssel für das Debug-Zertifikat. Das Debugzertifikat ist von Natur aus unsicher, wie im Abschnitt Debug-Build signieren beschrieben. Für veröffentlichte Android-Apps, die das Maps SDK for Android verwenden, ist ein zweiter API-Schlüssel erforderlich: der Schlüssel für das Release-Zertifikat. Weitere Informationen zum Abrufen eines Release-Zertifikats finden Sie unter API-Schlüssel verwenden.

Android Studio enthält eine Google Maps-Aktivitätsvorlage, mit der hilfreicher Vorlagencode generiert wird. Der Vorlagencode enthält die Datei google_maps_api.xml mit einem Link, der das Abrufen eines API-Schlüssels vereinfacht.

Schritt 1: Wander-Projekt mit der Kartenvorlage erstellen

  1. Erstellen Sie ein neues Android Studio-Projekt.
  2. Wählen Sie die Vorlage Google Maps-Aktivitäten aus.

  1. Geben Sie dem Projekt den Namen Wander.
  2. Legen Sie das Mindest-API-Level auf API 19 fest. Die Sprache muss Kotlin sein.
  3. Klicken Sie auf Fertig.
  4. Sehen Sie sich nach dem Erstellen der App Ihr Projekt und die folgenden kartenbezogenen Dateien an, die Android Studio für Sie erstellt:

google_maps_api.xml: In dieser Konfigurationsdatei wird Ihr API-Schlüssel gespeichert. Mit der Vorlage werden zwei google_maps_api.xml-Dateien generiert: eine für Debugging und eine für die Veröffentlichung. Die Datei für den API-Schlüssel für das Debug-Zertifikat befindet sich unter src/debug/res/values. Die Datei für den API-Schlüssel für das Release-Zertifikat befindet sich unter src/release/res/values. In diesem Codelab verwenden Sie nur das Debug-Zertifikat.

activity_maps.xml: Diese Layoutdatei enthält ein einzelnes Fragment, das den gesamten Bildschirm ausfüllt. Die Klasse SupportMapFragment ist eine abgeleitete Klasse der Klasse Fragment. Mit einem SupportMapFragment lässt sich eine Karte am einfachsten in eine App einfügen. Es handelt sich um einen Wrapper für eine Kartenansicht, mit dem die erforderlichen Lebenszyklus-Anforderungen automatisch verarbeitet werden.

Sie können SupportMapFragment in eine Layoutdatei einfügen, indem Sie in einem beliebigen ViewGroup ein <fragment>-Tag mit einem zusätzlichen name-Attribut verwenden.

android:name="com.google.android.gms.maps.SupportMapFragment"

MapsActivity.java: In der Datei MapsActivity.kt wird SupportMapFragment in der Methode onCreate() instanziiert und die getMapAsync() der Klasse verwendet, um das Kartensystem und die Ansicht automatisch zu initialisieren. Die Aktivität, die SupportMapFragment enthält, muss die OnMapReadyCallback-Schnittstelle und die onMapReady()-Methode dieser Schnittstelle implementieren. Die Methode onMapReady() wird aufgerufen, wenn die Karte geladen wird.

Schritt 2: API-Schlüssel abrufen

  1. Öffnen Sie die Debug-Version der Datei google_maps_api.xml.
  2. Suchen Sie in der Datei nach einem Kommentar mit einer langen URL. Die Parameter der URL enthalten spezifische Informationen zu Ihrer App.
  3. Kopieren Sie die URL und fügen Sie sie in einen Browser ein.
  4. Folgen Sie der Anleitung, um auf der Seite APIs & Dienste ein Projekt zu erstellen. Aufgrund der Parameter in der angegebenen URL wird das Maps SDK for Android auf der Seite automatisch aktiviert.
  5. Klicken Sie auf API-Schlüssel erstellen.
  6. Rufen Sie auf der nächsten Seite den Bereich „API-Schlüssel“ auf und klicken Sie auf den gerade erstellten Schlüssel.
  7. Klicken Sie auf Schlüssel einschränken und wählen Sie Maps SDK for Android aus, um die Verwendung des Schlüssels auf Android-Apps zu beschränken.
  8. Kopieren Sie den generierten API-Schlüssel. Er beginnt mit „AIza"“.
  9. Fügen Sie in der Datei google_maps_api.xml den Schlüssel in den String google_maps_key ein, an der Stelle, an der YOUR_KEY_HERE steht.
  10. Führen Sie die App aus. In Ihrer Aktivität sollte eine eingebettete Karte mit einer Markierung für Sydney (Australien) angezeigt werden. Die Markierung für Sydney ist Teil der Vorlage und wird später geändert.

Schritt 3: mMap umbenennen

MapsActivity hat ein privates lateinit var mit dem Namen mMap vom Typ GoogleMap. Um den Kotlin-Namenskonventionen zu entsprechen, ändern Sie den Namen von mMap in map.

  1. Klicken Sie in MapsActivity mit der rechten Maustaste auf mMap und dann auf Refactor> Rename...

  1. Ändern Sie den Variablennamen in map.

Beachten Sie, dass sich alle Verweise auf mMap in der Funktion onMapReady() auch in map ändern.

Google Maps umfasst mehrere Kartentypen: „Normal“, „Hybrid“, „Satellit“, „Gelände“ und „Keine“ (für keine Karte).

Normal Map

Satellitenkarte

Hybridkarte

Geländekarte

Jeder Kartentyp bietet unterschiedliche Informationen. Wenn Sie beispielsweise Karten zur Navigation in einem Auto verwenden, ist es hilfreich, Straßennamen zu sehen. In diesem Fall sollten Sie die normale Option verwenden. Beim Wandern kann die Geländekarte hilfreich sein, um zu entscheiden, wie viel Sie noch aufsteigen müssen, um den Gipfel zu erreichen.

In dieser Aufgabe führen Sie folgende Schritte aus:

  1. Fügen Sie eine App-Leiste mit einem Optionsmenü hinzu, über das der Nutzer den Kartentyp ändern kann.
  2. Verschieben Sie den Startpunkt der Karte an Ihren eigenen Wohnort.
  3. Unterstützung für Markierungen hinzugefügt, mit denen einzelne Orte auf einer Karte gekennzeichnet werden können. Markierungen können auch ein Label enthalten.

Menü für Kartentypen hinzufügen

In diesem Schritt fügen Sie eine App-Leiste mit einem Optionsmenü hinzu, über das der Nutzer den Kartentyp ändern kann.

  1. Klicken Sie zum Erstellen einer neuen XML-Datei für das Menü mit der rechten Maustaste auf das Verzeichnis res und wählen Sie Neu> Android-Ressourcendatei aus.
  2. Geben Sie im Dialogfeld map_options als Dateinamen ein.
  3. Wählen Sie Menü als Ressourcentyp aus.
  4. Klicken Sie auf OK.
  5. Ersetzen Sie auf dem Tab Code den Code in der neuen Datei durch den folgenden Code, um die Kartenmenüoptionen zu erstellen. Der Kartentyp „none“ wird ausgelassen, da er dazu führt, dass überhaupt keine Karte angezeigt wird. Dieser Schritt führt zu einem Fehler, den Sie im nächsten Schritt beheben.
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto">
   <item
       android:id="@+id/normal_map"
       android:title="@string/normal_map"
       app:showAsAction="never" />
   <item
       android:id="@+id/hybrid_map"
       android:title="@string/hybrid_map"
       app:showAsAction="never" />
   <item
       android:id="@+id/satellite_map"
       android:title="@string/satellite_map"
       app:showAsAction="never" />
   <item
       android:id="@+id/terrain_map"
       android:title="@string/terrain_map"
       app:showAsAction="never" />
</menu>
  1. Fügen Sie in strings.xml Ressourcen für die title-Attribute hinzu, um die Fehler zu beheben.
<resources>
   ...
   <string name="normal_map">Normal Map</string>
   <string name="hybrid_map">Hybrid Map</string>
   <string name="satellite_map">Satellite Map</string>
   <string name="terrain_map">Terrain Map</string>
   <string name="lat_long_snippet">Lat: %1$.5f, Long: %2$.5f</string>
   <string name="dropped_pin">Dropped Pin</string>
   <string name="poi">poi</string>
</resources>
  1. Überschreiben Sie in MapsActivity die Methode onCreateOptionsMenu() und blähen Sie das Menü aus der Ressourcendatei map_options auf.
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
   val inflater = menuInflater
   inflater.inflate(R.menu.map_options, menu)
   return true
}
  1. Überschreiben Sie in MapsActivity.kt die Methode onOptionsItemSelected(). Ändern Sie den Kartentyp mithilfe von Konstanten für Kartentypen, um die Auswahl des Nutzers zu berücksichtigen.
override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
   // Change the map type based on the user's selection.
   R.id.normal_map -> {
       map.mapType = GoogleMap.MAP_TYPE_NORMAL
       true
   }
   R.id.hybrid_map -> {
       map.mapType = GoogleMap.MAP_TYPE_HYBRID
       true
   }
   R.id.satellite_map -> {
       map.mapType = GoogleMap.MAP_TYPE_SATELLITE
       true
   }
   R.id.terrain_map -> {
       map.mapType = GoogleMap.MAP_TYPE_TERRAIN
       true
   }
   else -> super.onOptionsItemSelected(item)
}
  1. Starten Sie die App.
  2. Klicken Sie auf , um den Kartentyp zu ändern. Achten Sie darauf, wie sich das Aussehen der Karte in den verschiedenen Modi ändert.

Standardmäßig enthält der onMapReady()-Callback Code, mit dem eine Markierung in Sydney, Australien, platziert wird, wo Google Maps entwickelt wurde. Der Standard-Callback animiert die Karte auch so, dass sie auf Sydney geschwenkt wird.

In dieser Aufgabe soll die Kamera der Karte zu Ihrem Zuhause bewegt, auf eine von Ihnen angegebene Ebene gezoomt und dort eine Markierung platziert werden.

Schritt 1: An Ihr Zuhause heranzoomen und eine Markierung hinzufügen

  1. Suchen Sie in der Datei MapsActivity.kt nach der Methode onMapReady(). Entfernen Sie den Code, mit dem die Markierung in Sydney platziert und die Kamera bewegt wird. So sollte die Methode jetzt aussehen.
override fun onMapReady(googleMap: GoogleMap) {
   map = googleMap

}
  1. Folgen Sie dieser Anleitung, um die Breiten- und Längenkoordinaten Ihres Zuhauses zu ermitteln.
  2. Erstellen Sie einen Wert für den Breitengrad und einen Wert für den Längengrad und geben Sie die entsprechenden Gleitkommawerte ein.
val latitude = 37.422160
val longitude = -122.084270
  1. Erstellen Sie ein neues LatLng-Objekt mit dem Namen homeLatLng. Übergeben Sie im homeLatLng-Objekt die Werte, die Sie gerade erstellt haben.
val homeLatLng = LatLng(latitude, longitude)
  1. Erstellen Sie einen val für den gewünschten Zoomfaktor der Karte. Verwenden Sie die Zoomstufe 15f.
val zoomLevel = 15f

Mit der Zoomstufe wird festgelegt, wie stark Sie in die Karte hineingezoomt sind. Die folgende Liste gibt Ihnen einen Eindruck davon, welche Detailebene bei den einzelnen Zoomstufen angezeigt wird:

  • 1: Welt
  • 5: Landmasse/Kontinent
  • 10: Stadt
  • 15: Straßen
  • 20: Gebäude
  1. Bewegen Sie die Kamera zu homeLatLng, indem Sie die Funktion moveCamera() für das map-Objekt aufrufen und ein CameraUpdate-Objekt mit CameraUpdateFactory.newLatLngZoom() übergeben. Übergeben Sie das Objekt homeLatLng und die zoomLevel.
map.moveCamera(CameraUpdateFactory.newLatLngZoom(homeLatLng, zoomLevel))
  1. Füge der Karte bei homeLatLng eine Markierung hinzu.
map.addMarker(MarkerOptions().position(homeLatLng))

Ihre endgültige Methode sollte so aussehen:

override fun onMapReady(googleMap: GoogleMap) {
   map = googleMap

   //These coordinates represent the latitude and longitude of the Googleplex.
   val latitude = 37.422160
   val longitude = -122.084270
   val zoomLevel = 15f

   val homeLatLng = LatLng(latitude, longitude)
   map.moveCamera(CameraUpdateFactory.newLatLngZoom(homeLatLng, zoomLevel))
   map.addMarker(MarkerOptions().position(homeLatLng))
}
  1. Führen Sie Ihre App aus. Die Karte sollte zu Ihrem Zuhause schwenken, auf die gewünschte Stufe zoomen und eine Markierung auf Ihrem Zuhause platzieren.

Schritt 2: Nutzern erlauben, Markierungen durch langes Klicken hinzuzufügen

In diesem Schritt fügen Sie eine Markierung hinzu, wenn der Nutzer einen Ort auf der Karte berührt und hält.

  1. Erstellen Sie in MapsActivity einen Methoden-Stub namens setMapLongClick(), der ein GoogleMap als Argument akzeptiert.
  2. Fügen Sie dem Kartenobjekt einen setOnMapLongClickListener-Listener hinzu.
private fun setMapLongClick(map:GoogleMap) {
   map.setOnMapLongClickListener { }
}
  1. Rufen Sie in setOnMapLongClickListener() die Methode addMarker() auf. Übergeben Sie ein neues MarkerOptions-Objekt, bei dem die Position auf den übergebenen LatLng-Wert festgelegt ist.
private fun setMapLongClick(map: GoogleMap) {
   map.setOnMapLongClickListener { latLng ->
       map.addMarker(
           MarkerOptions()
               .position(latLng)
       )
   }
}
  1. Rufen Sie am Ende der Methode onMapReady() setMapLongClick() mit map auf.
override fun onMapReady(googleMap: GoogleMap) {
   ...
  
   setMapLongClick(map)
}
  1. Führen Sie die App aus.
  2. Halten Sie die Karte gedrückt, um eine Markierung an einem Ort zu platzieren.
  3. Tippen Sie auf die Markierung, um sie auf dem Bildschirm zu zentrieren.

Schritt 3: Infofenster für die Markierung hinzufügen

In diesem Schritt fügen Sie ein InfoWindow hinzu, in dem die Koordinaten der Markierung angezeigt werden, wenn auf die Markierung getippt wird.

  1. Erstellen Sie in setMapLongClick()setOnMapLongClickListener() ein val für snippet. Ein Snippet ist zusätzlicher Text, der nach dem Titel angezeigt wird. In Ihrem Snippet werden der Längen- und der Breitengrad einer Markierung angezeigt.
private fun setMapLongClick(map: GoogleMap) {
   map.setOnMapLongClickListener { latLng ->
       // A snippet is additional text that's displayed after the title.
       val snippet = String.format(
           Locale.getDefault(),
           "Lat: %1$.5f, Long: %2$.5f",
           latLng.latitude,
           latLng.longitude
       )
       map.addMarker(
           MarkerOptions()
               .position(latLng)
       )
   }
}
  1. Legen Sie in addMarker() den title der Markierung mit einer R.string.dropped_pin-String-Ressource auf „Dropped Pin“ fest.
  2. Setzen Sie den snippet des Markers auf snippet.

Die fertige Funktion sieht so aus:

private fun setMapLongClick(map: GoogleMap) {
   map.setOnMapLongClickListener { latLng ->
       // A Snippet is Additional text that's displayed below the title.
       val snippet = String.format(
           Locale.getDefault(),
           "Lat: %1$.5f, Long: %2$.5f",
           latLng.latitude,
           latLng.longitude
       )
       map.addMarker(
           MarkerOptions()
               .position(latLng)
               .title(getString(R.string.dropped_pin))
               .snippet(snippet)
              
       )
   }
}
  1. Führen Sie die App aus.
  2. Halten Sie die Karte gedrückt, um eine Standortmarkierung zu setzen.
  3. Tippen Sie auf die Markierung, um das Infofenster aufzurufen.

Schritt 4: POI-Listener hinzufügen

Standardmäßig werden Points of Interest (POIs) zusammen mit den entsprechenden Symbolen auf der Karte dargestellt. POIs sind beispielsweise Parks, Schulen und Behördengebäude. Wenn der Kartentyp auf normal festgelegt ist, werden auch Unternehmens-POIs auf der Karte angezeigt. Unternehmens-POIs sind beispielsweise Geschäfte, Restaurants und Hotels.

In diesem Schritt fügen Sie der Karte ein GoogleMap.OnPoiClickListener hinzu. Dieser Klick-Listener platziert sofort eine Markierung auf der Karte, wenn der Nutzer auf einen POI klickt. Der Klick-Listener zeigt auch ein Infofenster mit dem Namen des POI an.

  1. Erstellen Sie in MapsActivity einen Methoden-Stub namens setPoiClick(), der ein GoogleMap als Argument akzeptiert.
  2. Legen Sie in der Methode setPoiClick() einen OnPoiClickListener für das übergebene GoogleMap fest.
private fun setPoiClick(map: GoogleMap) {
   map.setOnPoiClickListener { poi ->

   }
}
  1. Erstellen Sie in setOnPoiClickListener() ein val poiMarker für die Markierung .
  2. Legen Sie sie mit map.addMarker() auf eine Markierung fest und legen Sie mit MarkerOptions den title auf den Namen des POI fest.
private fun setPoiClick(map: GoogleMap) {
   map.setOnPoiClickListener { poi ->
       val poiMarker = map.addMarker(
           MarkerOptions()
               .position(poi.latLng)
               .title(poi.name)
       )
   }
}
  1. Rufen Sie in der Funktion setOnPoiClickListener() showInfoWindow() für poiMarker auf, um das Infofenster sofort anzuzeigen.
poiMarker.showInfoWindow()

Der endgültige Code für die Funktion setPoiClick() sollte so aussehen.

private fun setPoiClick(map: GoogleMap) {
   map.setOnPoiClickListener { poi ->
       val poiMarker = map.addMarker(
           MarkerOptions()
               .position(poi.latLng)
               .title(poi.name)
       )
       poiMarker.showInfoWindow()
   }
}
  1. Rufen Sie am Ende von onMapReady() setPoiClick() auf und übergeben Sie map.
override fun onMapReady(googleMap: GoogleMap) {
   ...

   setPoiClick(map)
}
  1. Führen Sie Ihre App aus und suchen Sie nach einem POI, z. B. einem Park oder einem Café.
  2. Tippen Sie auf den POI, um eine Markierung darauf zu platzieren und den Namen des POI in einem Infofenster anzeigen zu lassen.

Sie können Google Maps auf vielfältige Weise anpassen und Ihrer Karte so ein einzigartiges Erscheinungsbild verleihen.

Sie können ein MapFragment-Objekt mit den verfügbaren XML-Attributen anpassen, wie Sie es auch bei anderen Fragmenten tun würden. In diesem Schritt passen Sie jedoch das Erscheinungsbild des Inhalts des MapFragment mit Methoden für das GoogleMap-Objekt an.

Wenn Sie einen benutzerdefinierten Stil für Ihre Karte erstellen möchten, generieren Sie eine JSON-Datei, in der angegeben wird, wie die Elemente auf der Karte dargestellt werden. Sie müssen diese JSON-Datei nicht manuell erstellen. Google bietet den Maps Platform Styling Wizard an, mit dem Sie JSON-Code generieren können, nachdem Sie Ihre Karte visuell gestaltet haben. In dieser Aufgabe gestalten Sie die Karte mit einem Retro-Design. Das bedeutet, dass die Karte Vintage-Farben verwendet und Sie farbige Straßen hinzufügen.

Schritt 1: Stil für die Karte erstellen

  1. Rufen Sie in Ihrem Browser https://mapstyle.withgoogle.com/ auf.
  2. Wählen Sie Stil erstellen aus.
  3. Wählen Sie Retro aus.

  1. Klicke auf Weitere Optionen.

  1. Wählen Sie in der Liste Funktionstyp die Option Straße> Füllen aus.
  2. Ändern Sie die Farbe der Straßen in eine beliebige Farbe, z. B. Rosa.

  1. Klicken Sie auf Fertig.

  1. Kopieren Sie den JSON-Code aus dem resultierenden Dialogfeld und speichern Sie ihn bei Bedarf in einer Nur-Text-Notiz für den nächsten Schritt.

Schritt 2: Stil zur Karte hinzufügen

  1. Erstellen Sie in Android Studio im Verzeichnis res ein Ressourcenverzeichnis mit dem Namen raw. Sie verwenden die raw-Verzeichnisressourcen wie JSON-Code.
  2. Erstellen Sie im Ordner res/raw eine Datei mit dem Namen map_style.json.
  3. Fügen Sie den zwischengespeicherten JSON-Code in die neue Ressourcendatei ein.
  4. Erstellen Sie in MapsActivity eine TAG-Klassenvariable über der onCreate()-Methode. Dies wird für Protokollierungszwecke verwendet.
private val TAG = MapsActivity::class.java.simpleName
  1. Erstellen Sie auch in MapsActivity eine setMapStyle()-Funktion, die ein GoogleMap akzeptiert.
  2. Fügen Sie in setMapStyle() einen try{}-Block hinzu.
  3. Erstellen Sie im Block try{} eine val success für den Erfolg des Stylings. (Sie fügen den folgenden Catch-Block hinzu.)
  4. Legen Sie im try{}-Block den JSON-Stil für die Karte fest, indem Sie setMapStyle() für das GoogleMap-Objekt aufrufen. Übergeben Sie ein MapStyleOptions-Objekt, mit dem die JSON-Datei geladen wird.
  5. Weisen Sie das Ergebnis success zu. Die Methode setMapStyle() gibt einen booleschen Wert zurück, der den Erfolgsstatus des Parsens der Formatierungsdatei und des Festlegens des Stils angibt.
private fun setMapStyle(map: GoogleMap) {
   try {
       // Customize the styling of the base map using a JSON object defined
       // in a raw resource file.
       val success = map.setMapStyle(
           MapStyleOptions.loadRawResourceStyle(
               this,
               R.raw.map_style
           )
       )
   }
}
  1. Fügen Sie eine IF-Anweisung für den Fall hinzu, dass success „false“ ist. Wenn die Formatierung nicht erfolgreich ist, geben Sie ein Protokoll aus, dass die Verarbeitung fehlgeschlagen ist.
private fun setMapStyle(map: GoogleMap) {
   try {
       ...
       if (!success) {
           Log.e(TAG, "Style parsing failed.")
       }
   }
}
  1. Fügen Sie einen catch{}-Block hinzu, um den Fall einer fehlenden Formatvorlagendatei zu verarbeiten. Wenn die Datei im Block catch nicht geladen werden kann, geben Sie eine Resources.NotFoundException aus.
private fun setMapStyle(map: GoogleMap) {
   try {
       ...
   } catch (e: Resources.NotFoundException) {
       Log.e(TAG, "Can't find style. Error: ", e)
   }
}

Die fertige Methode sollte so aussehen:

private fun setMapStyle(map: GoogleMap) {
   try {
       // Customize the styling of the base map using a JSON object defined
       // in a raw resource file.
       val success = map.setMapStyle(
           MapStyleOptions.loadRawResourceStyle(
               this,
               R.raw.map_style
           )
       )

       if (!success) {
           Log.e(TAG, "Style parsing failed.")
       }
   } catch (e: Resources.NotFoundException) {
       Log.e(TAG, "Can't find style. Error: ", e)
   }
}
  1. Rufen Sie schließlich die Methode setMapStyle() in der Methode onMapReady() auf und übergeben Sie Ihr GoogleMap-Objekt.
override fun onMapReady(googleMap: GoogleMap) {
   ...
   setMapStyle(map)
}
  1. Führen Sie die App aus.
  2. Stellen Sie die Karte auf den Modus normal ein. Der neue Stil sollte mit dem Retro-Design und den Straßen in der von Ihnen ausgewählten Farbe sichtbar sein.

Schritt 3: Markierung gestalten

Sie können Ihre Karte weiter personalisieren, indem Sie die Kartenmarkierungen gestalten. In diesem Schritt ändern Sie die roten Standardmarkierungen in etwas Cooleres.

  1. Fügen Sie in der Methode onMapLongClick() der MarkerOptions() des Konstruktors die folgende Codezeile hinzu, um die Standardmarkierung zu verwenden, aber die Farbe in Blau zu ändern.
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE))

Jetzt sieht onMapLongClickListener() so aus:

map.setOnMapLongClickListener { latLng ->
   // A snippet is additional text that's displayed after the title.
   val snippet = String.format(
       Locale.getDefault(),
       "Lat: %1$.5f, Long: %2$.5f",
       latLng.latitude,
       latLng.longitude
   )
   map.addMarker(
       MarkerOptions()
           .position(latLng)
           .title(getString(R.string.dropped_pin))
           .snippet(snippet)
         .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE))
   )
}
  1. Führen Sie die App aus. Die Markierungen, die nach dem langen Klicken angezeigt werden, sind jetzt blau schattiert. POI-Markierungen sind weiterhin rot, da Sie der onPoiClick()-Methode kein Styling hinzugefügt haben.

Eine Möglichkeit, die Google-Karte anzupassen, besteht darin, darauf zu zeichnen. Diese Technik ist nützlich, wenn Sie einen bestimmten Ortstyp hervorheben möchten, z. B. beliebte Angelplätze.

  • Formen:Sie können der Karte Polylinien, Polygone und Kreise hinzufügen.
  • GroundOverlay-Objekte:Ein Boden-Overlay ist ein Bild, das auf einer Karte fixiert ist. Im Unterschied zu Markierungen sind Boden-Overlays an der Erdoberfläche und nicht am Bildschirm ausgerichtet. Wenn Sie die Karte drehen, neigen oder zoomen, ändert sich die Ausrichtung des Bildes. Boden-Overlays sind nützlich, um ein einzelnes Bild an einem Punkt der Karte zu fixieren.

Schritt: Boden-Overlay hinzufügen

In dieser Aufgabe fügen Sie Ihrer Wohnadresse ein Boden-Overlay in Form eines Android hinzu.

  1. Laden Sie dieses Android-Image herunter und speichern Sie es im Ordner res/drawable. Achten Sie darauf, dass der Dateiname android.png lautet.

  1. Erstellen Sie in onMapReady() nach dem Aufruf zum Bewegen der Kamera an die Position Ihres Zuhauses ein GroundOverlayOptions-Objekt.
  2. Weisen Sie das Objekt einer Variablen mit dem Namen androidOverlay zu.
val androidOverlay = GroundOverlayOptions()
  1. Verwenden Sie die Methode BitmapDescriptorFactory.fromResource(), um ein BitmapDescriptor-Objekt aus der heruntergeladenen Bildressource zu erstellen.
  2. Übergeben Sie das resultierende BitmapDescriptor-Objekt an die Methode image() des GroundOverlayOptions-Objekts.
val androidOverlay = GroundOverlayOptions()
   .image(BitmapDescriptorFactory.fromResource(R.drawable.android))
  1. Erstellen Sie eine float overlaySize für die Breite des gewünschten Overlays in Metern. In diesem Beispiel ist eine Breite von 100f gut geeignet.

Legen Sie die Eigenschaft position für das Objekt GroundOverlayOptions fest, indem Sie die Methode position() aufrufen und das Objekt homeLatLng und die overlaySize übergeben.

val overlaySize = 100f
val androidOverlay = GroundOverlayOptions()
   .image(BitmapDescriptorFactory.fromResource(R.drawable.android))
   .position(homeLatLng, overlaySize)
  1. Rufen Sie addGroundOverlay() für das GoogleMap-Objekt auf und übergeben Sie Ihr GroundOverlayOptions-Objekt.
map.addGroundOverlay(androidOverlay)
  1. Starten Sie die App.
  2. Ändern Sie den Wert von zoomLevel in 18f, um das Android-Bild als Overlay zu sehen.

Nutzer verwenden Google Maps häufig, um ihren aktuellen Standort zu sehen. Wenn Sie den Gerätestandort auf Ihrer Karte anzeigen möchten, können Sie die Ebene mit Standortdaten verwenden.

Durch die Ebene mit Standortdaten wird der Karte Mein Standort hinzugefügt. Wenn der Nutzer auf die Schaltfläche tippt, wird die Karte auf den Standort des Geräts zentriert. Der Standort wird als blauer Punkt angezeigt, wenn das Gerät sich nicht bewegt, und als blauer Navigationspfeil, wenn das Gerät in Bewegung ist.

In dieser Aufgabe aktivieren Sie die Ebene mit Standortdaten.

Schritt: Berechtigungen zur Standortermittlung anfordern

Um die Standortverfolgung in Google Maps zu aktivieren, ist nur eine Codezeile erforderlich. Sie müssen jedoch dafür sorgen, dass der Nutzer Standortberechtigungen erteilt hat (mit dem Laufzeitberechtigungsmodell).

In diesem Schritt fordern Sie Berechtigungen zur Standortermittlung an und aktivieren die Standortermittlung.

  1. Prüfen Sie in der Datei AndroidManifest.xml, ob die Berechtigung FINE_LOCATION bereits vorhanden ist. Android Studio hat diese Berechtigung eingefügt, als Sie die Google Maps-Vorlage ausgewählt haben.
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
  1. Erstellen Sie in MapsActivity eine REQUEST_LOCATION_PERMISSION-Klassenvariable.
private val REQUEST_LOCATION_PERMISSION = 1
  1. Wenn Sie prüfen möchten, ob Berechtigungen erteilt wurden, erstellen Sie in MapsActivity die Methode isPermissionGranted(). Prüfen Sie in dieser Methode, ob der Nutzer die Berechtigung erteilt hat.
private fun isPermissionGranted() : Boolean {
  return ContextCompat.checkSelfPermission(
       this,
      Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
}
  1. Wenn Sie die Standortverfolgung in Ihrer App aktivieren möchten, erstellen Sie in MapsActivity eine Methode namens enableMyLocation(), die keine Argumente akzeptiert und nichts zurückgibt. Prüfen Sie, ob Sie die Berechtigung ACCESS_FINE_LOCATION haben. Wenn die Berechtigung erteilt wurde, aktivieren Sie die Standorte-Ebene. Andernfalls fordern Sie die Berechtigung an.
private fun enableMyLocation() {
   if (isPermissionGranted()) {
       map.isMyLocationEnabled = true 
   }
   else {
       ActivityCompat.requestPermissions(
           this,
           arrayOf<String>(Manifest.permission.ACCESS_FINE_LOCATION),
           REQUEST_LOCATION_PERMISSION
       )
   }
}
  1. Rufen Sie enableMyLocation() über den onMapReady()-Callback auf, um die Standortebene zu aktivieren.
override fun onMapReady(googleMap: GoogleMap) {
   ...
   enableMyLocation()
}
  1. Überschreiben Sie die Methode onRequestPermissionsResult(). Wenn requestCode gleich REQUEST_LOCATION_PERMISSION ist, wird die Berechtigung erteilt. Wenn das grantResults-Array nicht leer ist und PackageManager.PERMISSION_GRANTED im ersten Slot enthält, wird enableMyLocation() aufgerufen.
override fun onRequestPermissionsResult(
   requestCode: Int,
   permissions: Array<String>,
   grantResults: IntArray) {
   if (requestCode == REQUEST_LOCATION_PERMISSION) {
       if (grantResults.contains(PackageManager.PERMISSION_GRANTED)) {
           enableMyLocation()
       }
   }
}
  1. Führen Sie Ihre App aus. Es sollte ein Dialogfeld angezeigt werden, in dem Zugriff auf den Standort des Geräts angefordert wird. Erteilen Sie die Berechtigung.

Auf der Karte wird jetzt der aktuelle Standort des Geräts mit einem blauen Punkt angezeigt. Beachten Sie, dass es eine Schaltfläche für den Standort gibt. Wenn Sie die Karte von Ihrem Standort weg bewegen und auf diese Schaltfläche klicken, wird die Karte wieder auf den Standort des Geräts zentriert.

Laden Sie den Code für das fertige Codelab herunter.

$  git clone https://github.com/googlecodelabs/android-kotlin-geo-maps


Alternativ können Sie das Repository als ZIP-Datei herunterladen, entzippen und in Android Studio öffnen.

ZIP-Datei herunterladen

  • Wenn Sie die Maps API verwenden möchten, benötigen Sie einen API-Schlüssel aus der Google API Console.
  • Wenn Sie in Android Studio die Google Maps Activity-Vorlage verwenden, wird ein Activity mit einem einzelnen SupportMapFragment im Layout der App generiert. Die Vorlage fügt dem App-Manifest auch ACCESS_FINE_PERMISSION hinzu, implementiert OnMapReadyCallback in Ihrer Aktivität und überschreibt die erforderliche Methode onMapReady().

Wenn Sie den Kartentyp eines GoogleMap zur Laufzeit ändern möchten, verwenden Sie die Methode GoogleMap.setMapType(). Eine Google-Karte kann einen der folgenden Kartentypen haben:

  • Normal: Typische Straßenkarte. Straßen, einige von Menschen geschaffene Merkmale und wichtige Landschaftsmerkmale wie Flüsse werden angezeigt. Die Straßen und sonstigen Merkmale sind beschriftet.
  • Hybrid: Enthält Satellitenfotodaten mit zusätzlichen Straßenkarten. Die Straßen und sonstigen Merkmale sind beschriftet.
  • Satellit: Fotodaten. Straßen und sonstige Merkmale sind nicht beschriftet.
  • Gelände: Topografische Daten. Die Karte enthält Farben, Höhenlinien und Labels sowie perspektivische Schattierungen. Außerdem werden einige Straßen und Labels dargestellt.
  • Keine : Keine Basiskartenkacheln.

Über Google Maps:

  • Eine Markierung ist ein Indikator für einen bestimmten geografischen Standort.
  • Wenn auf die Markierung getippt wird, wird standardmäßig ein Infofenster mit Informationen zum Ort eingeblendet.
  • Standardmäßig werden Points of Interest (POIs) zusammen mit ihren Icons auf der Karte dargestellt. POIs sind beispielsweise Parks, Schulen und Behördengebäude.
  • Darüber hinaus werden Unternehmens-POIs (Geschäfte, Restaurants, Hotels usw.) standardmäßig auf der Karte angezeigt, wenn der Kartentyp normal ist.
  • Mit OnPoiClickListener können Sie Klicks auf POIs erfassen.
  • Mit dem Styling-Assistenten können Sie das Erscheinungsbild fast aller Elemente einer Google-Karte ändern. Mit dem Styling Wizard wird eine JSON-Datei generiert, die Sie mit der Methode setMapStyle() an die Google-Karte übergeben.
  • Sie können die Markierungen anpassen, indem Sie die Standardfarbe ändern oder das Standardmarkierungssymbol durch ein benutzerdefiniertes Bild ersetzen.

Weitere wichtige Informationen:

  • Mit einem Boden-Overlay können Sie ein Bild an einem geografischen Ort fixieren.
  • Verwenden Sie ein GroundOverlayOptions-Objekt, um das Bild, die Größe des Bildes in Metern und die Position des Bildes anzugeben. Übergeben Sie dieses Objekt an die GoogleMap.addGroundOverlay()-Methode, um das Overlay auf der Karte festzulegen.
  • Wenn Ihre App die Berechtigung ACCESS_FINE_LOCATION hat, können Sie die Standortverfolgung aktivieren, indem Sie map.isMyLocationEnabled = true festlegen.
  • Das wird in diesem Codelab nicht behandelt, aber Sie können mit Google Street View zusätzliche Informationen zu einem Ort bereitstellen. Dabei handelt es sich um ein navigierbares Panoramabild eines bestimmten Ortes.

Android-Entwicklerdokumentation:

Referenzdokumentation:

Links zu anderen Codelabs in diesem Kurs finden Sie auf der Landingpage für die Codelabs zum Thema „Fortgeschrittenes Android in Kotlin“.