Rheinwerk Computing < openbook >

 
Inhaltsverzeichnis
Vorwort
Teil I Grundlagen
1 Android – eine offene, mobile Plattform
2 Hallo Android!
3 Von der Idee zur Veröffentlichung
Teil II Elementare Anwendungsbausteine
4 Wichtige Grundbausteine von Apps
5 Benutzeroberflächen
6 Multitasking
Teil III Gerätefunktionen nutzen
7 Telefonieren und surfen
8 Sensoren, GPS und Bluetooth
Teil IV Dateien und Datenbanken
9 Dateien lesen, schreiben und drucken
10 Datenbanken
Teil V Multimedia und Produktivität
11 Multimedia
12 Kontakte und Organizer
A Einführung in Kotlin
B Jetpack Compose
C Häufig benötigte Codebausteine
D Literaturverzeichnis
E Die Begleitmaterialien
Stichwortverzeichnis

Ihre Meinung?
Spacer
<< zurück
Android 11 von Thomas Künneth
Das Praxisbuch für App-Entwickler
Buch: Android 11

Android 11
Pfeil 8 Sensoren, GPS und Bluetooth
Pfeil 8.1 Sensoren
Pfeil 8.1.1 Die Klasse »SensorManager«
Pfeil 8.1.2 Dynamische Sensoren und Trigger
Pfeil 8.1.3 Ein Schrittzähler
Pfeil 8.2 GPS und ortsbezogene Dienste
Pfeil 8.2.1 Den aktuellen Standort ermitteln
Pfeil 8.2.2 Positionen auf einer Karte anzeigen
Pfeil 8.3 Bluetooth
Pfeil 8.3.1 Geräte finden und koppeln
Pfeil 8.3.2 Daten senden und empfangen
Pfeil 8.3.3 Bluetooth Low Energy
Pfeil 8.4 Authentifizierung durch biometrische Merkmale
Pfeil 8.4.1 Fingerabdrucksensor im Emulator einrichten
Pfeil 8.4.2 Jetpack Biometric
Pfeil 8.5 Zusammenfassung
 
Zum Seitenanfang

8.2    GPS und ortsbezogene Dienste Zur vorigen ÜberschriftZur nächsten Überschrift

Eine sehr nützliche Fähigkeit von Smartphones und Tablets ist, den aktuellen Standort ermitteln zu können. Wer in einer fremden Stadt schon einmal schnellstmöglich den Bahnhof erreichen oder einen Geldautomaten finden musste, möchte den Komfort solcher Apps sicherlich nicht mehr missen. Dabei sind die Einsatzgebiete ortsbezogener Dienste noch lange nicht vollständig ausgelotet. Haben Sie Lust bekommen, sich damit zu beschäftigen? Android bietet komfortable und einfach zu nutzende Programmierschnittstellen an. Lassen Sie Ihrer Kreativität freien Lauf.

 
Zum Seitenanfang

8.2.1    Den aktuellen Standort ermitteln Zur vorigen ÜberschriftZur nächsten Überschrift

Die App LocationDemo1 (Abbildung 8.3) gibt den aktuellen Standort aus und zeigt Informationen zu Location Providern an – sie sind für die Standortbestimmung zuständig. Die Hauptklasse LocationDemo1Activity (Listing 8.5) lädt in der Methode onCreate() die Benutzeroberfläche und zeigt sie an. Dann wird geprüft, ob der Benutzer die Standortbestimmung bereits erlaubt hat. Falls nicht, wird die entsprechende Berechtigung angefordert. Android kennt drei:

  1. ACCESS_COARSE_LOCATION erlaubt eine ungefähre Ortsbestimmung.

  2. ACCESS_FINE_LOCATION erlaubt eine genaue Ermittlung des Standortes.

  3. ACCESS_BACKGROUND_LOCATION erlaubt die Standortbestimmung im Hintergrund. Sie müssen zusätzlich ACCESS_FINE_LOCATION oder ACCESS_COARSE_LOCATION beantragen.

Alle drei sind gefährliche Berechtigungen. Sie müssen in der Manifestdatei eingetragen und durch Aufruf der Methoden checkSelfPermission() und requestPermissions() geprüft und angefordert werden. Wurde ACCESS_FINE_LOCATION gewährt, gilt dies implizit auch für ACCESS_COARSE_LOCATION. Die eigentliche Arbeit (das Anzeigen aller Provider und Informationen zu ihnen) geschieht in der privaten Methode doIt().

getSystemService(LocationManager::class.java) liefert ein Objekt des Typs android.location.LocationManager und ermöglicht den Zugriff auf alle ortsbezogenen Funktionen des Systems. Sie können mit requestLocationUpdates() einen Listener registrieren, um unterrichtet zu werden, sobald sich der Standort des Geräts ändert. Mein Code ruft diese Methode allerdings in onResume() auf. Wenn möglich, sollten Sie nämlich nur so lange den Standort abfragen, wie die Activity aktiv ist. Um den Listener wieder zu entfernen, rufen Sie removeUpdates() auf. onPause() ist (analog zu onResume()) eine gute Wahl.

Mit der LocationManager-Methode getAllProviders() (oder in Kotlin einfach allProviders) ermitteln Sie, welche Location Provider vorhanden sind. Sie liefert eine Liste mit den Namen der grundsätzlich verfügbaren Provider. Einen solchen Namen übergeben Sie an getProvider().

Die App »LocationDemo1«

Abbildung 8.3    Die App »LocationDemo1«

Vorher sollten Sie aber unbedingt mit isProviderEnabled() seine Verfügbarkeit prüfen. Alternativ können Sie getProviders(true) aufrufen – dann erhalten Sie nur die aktiven. getProvider() liefert eine Instanz des Typs android.location.LocationProvider. Die Klasse bietet einige Auskunftsmethoden an. Beispielsweise können Sie ermitteln, ob der Provider für die Standortbestimmung einen Satelliten, einen Sendemast oder ein Netzwerk erfordert (requiresCell(), requiresNetwork() oder requiresSatellite()).

package com.thomaskuenneth.androidbuch.locationdemo1

import android.Manifest
import android.content.pm.PackageManager
import android.location.Criteria
import android.location.Location
import android.location.LocationListener
import android.location.LocationManager
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*

private const val REQUEST_FINE_LOCATION = 123
class LocationDemo1Activity : AppCompatActivity() {
private val listener = object : LocationListener {
override fun onStatusChanged(
provider: String, status: Int,
extras: Bundle
) {
tv.append("onStatusChanged()\n")
}

override fun onProviderEnabled(provider: String) {
tv.append("onProviderEnabled()\n")
}

override fun onProviderDisabled(provider: String) {
tv.append("onProviderDisabled()\n")
}

override fun onLocationChanged(loc: Location) {
tv.append("\nonLocationChanged()\n")
tv.append("Breite: ${loc.latitude}\nLänge: ${loc.longitude}\n")
}
}

private lateinit var manager: LocationManager
private lateinit var provider: String

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
tv.text = ""
if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED
) {
requestPermissions(
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
REQUEST_FINE_LOCATION
)
} else {
doIt()
}
}

override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>,
grantResults: IntArray
) {
if (requestCode == REQUEST_FINE_LOCATION &&
grantResults.isNotEmpty() && grantResults[0] ==
PackageManager.PERMISSION_GRANTED
) {
doIt()
}
}

override fun onResume() {
super.onResume()
if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED
) {
try {
manager.requestLocationUpdates(provider, 3000L, 0.0f, listener)
} catch (t: Throwable) {
tv.append("${t.message}\n")
}
}
}

override fun onPause() {
super.onPause()
if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED
) {
manager.removeUpdates(listener)
}
}

private fun doIt() {
manager = getSystemService(LocationManager::class.java)
// Liste mit Namen aller Provider ausgeben
val providers: List<String> = manager.allProviders
for (name in providers) {
val enabled: Boolean = manager.isProviderEnabled(name)
tv.append("Name: $name\n")
tv.append(" --> isProviderEnabled(): $enabled\n")
if (!enabled) {
continue
}
val p = manager.getProvider(name)
tv.append(" --> requiresCell(): ${p?.requiresCell()}\n")
tv.append(" --> requiresNetwork(): ${p?.requiresNetwork()}\n")
tv.append(" --> requiresSatellite(): ${p?.requiresSatellite()}\n")
}
// Provider mit grober Auflösung
// und niedrigem Energieverbrauch
val criteria = Criteria()
criteria.accuracy = Criteria.ACCURACY_COARSE
criteria.powerRequirement = Criteria.POWER_LOW
provider = manager.getBestProvider(criteria, true) ?: ""
tv.append("\nVerwende $provider\n")
val loc = Location(LocationManager.GPS_PROVIDER)
loc.latitude = Location.convert("49:27")
loc.longitude = Location.convert("11:5")
tv.append("latitude: ${loc.latitude}\nlongitude: ${loc.longitude}\n")
}
}

Listing 8.5    Die Klasse »LocationDemo1Activity«

Warum gibt es eigentlich mehrere Location Provider? Sie können den Standort eines Geräts auf unterschiedliche Weise ermitteln. Die Nutzung des Global Positioning Systems (GPS) liefert recht genaue Positionen, funktioniert aber nur im Freien zuverlässig und benötigt vergleichsweise viel Strom. Eine andere Möglichkeit besteht darin, Informationen von Sendemasten oder Wi-Fi-Zugangspunkten auszuwerten, was natürlich nur klappt, wenn das Tablet oder Smartphone in ein Netz eingebucht ist. Jede Variante hat also spezifische Vor- und Nachteile. Android bietet deshalb mit getBestProvider() die Möglichkeit, anhand von bestimmten Kriterien den am besten geeigneten Location Provider zu suchen.

[»]  Hinweis

Welche Berechtigung Ihre App benötigt, hängt vom verwendeten Location Provider ab. passive und gps benötigen ACCESS_FINE_LOCATION. network gibt sich mit ACCESS_COARSE_LOCATION zufrieden. Schon seit Android 5 sollte in der Manifestdatei mit <uses-feature ... /> zusätzlich zu den Berechtigungen das Feature android.hardware.location.gps oder android.hardware.location.network (oder beide) angefordert werden.

Mein Beispiel ermittelt den Namen eines Providers, der die Position nach Möglichkeit nur grob auflöst und mit einem niedrigen Energieverbrauch auskommt. Hierzu wird ein android.location.Criteria-Objekt erzeugt und durch Setzen von accuracy und powerRequirement konfiguriert. Falls Android keinen Provider findet, der den Kriterien entspricht, wird der am wenigsten abweichende geliefert. Mit dem Namen können Sie wie gewohnt die LocationManager-Methode getProvider() aufrufen. Mein Code tut dies nicht, weil der Name direkt an requestLocationUpdates() übergeben werden kann.

Es gibt zwei Möglichkeiten, den aktuellen Standort zu ermitteln. Die Methode getLastKnownLocation() des Location Managers liefert die letzte bekannte Position, die ein Location Provider ermittelt hat. Diese kann – muss aber nicht – dem aktuellen Aufenthaltsort entsprechen. Insofern bietet sich diese Methode vor allem an, um dem Anwender einen ersten Hinweis darauf zu geben, wo er sich befindet (oder zuletzt befunden hat). Beachten Sie aber, dass getLastKnownLocation() auch null liefern kann. Die zweite Variante besteht darin, einen LocationListener zu registrieren, der bei Positionsänderungen aufgerufen wird. Die hierfür zuständige Methode requestLocationUpdates() steht in zahlreichen Ausprägungen zur Verfügung, beispielsweise können Sie steuern, wie viel Zeit mindestens zwischen zwei Aufrufen der Callback-Methode onLocationChanged() liegen sollte.

Ortswechsel simulieren

Wenn Sie das Projekt LocationDemo1 im Emulator ausprobieren, können Sie Positionswechsel simulieren, indem Sie die in Abbildung 8.4 gezeigten erweiterten Einstellungen öffnen und ggf. auf Location klicken.

Die Methoden getLastKnownLocation() und onLocationChanged() liefern Instanzen der Klasse android.location.Location. Sie repräsentieren geografische Positionen (angegeben durch Länge und Breite) zu einem bestimmten Zeitpunkt. Informationen über Höhe, Geschwindigkeit und Richtung können zusätzlich vorhanden sein. Die Erde wird in 360 Längen- und 180 Breitengrade unterteilt. Da Letztere vom Äquator aus gezählt werden, liegen die beiden Pole bei 90° Nord bzw. Süd. Der Nullmeridian teilt die Längengrade in westlicher und östlicher Richtung.

Innerhalb eines Location-Objekts werden Länge und Breite als double gespeichert. Die textuelle Darstellung hängt von der gewünschten Genauigkeit ab. Aus diesem Grund können Sie mit der Methode convert() eine Zeichenkette in eine Fließkommazahl umwandeln. Auch die andere Richtung ist möglich. Hierzu ein Beispiel: Die ungefähre geografische Position von Nürnberg ist 49° 27' Nord und 11° 5' Ost. Grad und Minuten werden durch einen Doppelpunkt getrennt und dann als Zeichenkette an convert() übergeben. Dies ist am Ende von Listing 8.5 zu sehen. Soll aus einem double-Wert eine Zeichenkette bestehend aus Grad, Minuten und Sekunden erzeugt werden, übergeben Sie diesen an convert(). Der zweite Parameter steuert die Formatierung des Strings. Mögliche Werte sind Location.FORMAT_DEGREES, FORMAT_MINUTES und FORMAT_SECONDS.

Standort im Emulator simulieren

Abbildung 8.4    Standort im Emulator simulieren

 
Zum Seitenanfang

8.2.2    Positionen auf einer Karte anzeigen Zur vorigen ÜberschriftZur nächsten Überschrift

In diesem Abschnitt zeige ich Ihnen, wie Sie den aktuellen Standort auf einer Google-Maps-Karte visualisieren können. Hierfür ist die Bibliothek Google Play Services erforderlich. Sie gestattet den Zugriff auf eine ganze Reihe von Google-Diensten, unter anderem Drive, Fit und Wallet. Für Sie als Entwickler hat die Nutzung dieser Komponente den Vorteil, dass neue Funktionen auch den Besitzern älterer Geräte zugutekommen. Auf der anderen Seite sind die Google Play Services recht umfangreich, benötigen also vergleichsweise viel Speicherplatz. Unglücklicherweise ist eine Nutzung von Googles Kartenmaterial ohne diese Bibliothek nur noch mit erheblichem Aufwand möglich.

Damit eine App Google Maps nutzen kann, muss sie einen Schlüssel übermitteln. Melden Sie sich unter https://console.developers.google.com/ an, und erstellen Sie über die Dropdown-Liste im oberen Bereich ein neues Projekt. Als Nächstes weisen Sie unter APIs & DiensteBibliothek dem Projekt das Maps SDK for Android zu. Jetzt müssen Sie noch unter Anmeldedaten einen neuen Schlüssel erstellen. Klicken Sie hierzu auf Anmeldedaten erstellen, und wählen Sie danach API-Schlüssel. Klicken Sie nicht auf Schliessen, sondern auf Schlüssel einschränken. Aktivieren Sie nun, wie in Abbildung 8.5 zu sehen, Android-Apps.

Der Maps-API-Schlüssel ist an das Zertifikat gebunden, mit dem Sie Ihre Apps signieren. Sie müssen deshalb den SHA1-Fingerabdruck des Zertifikats sowie einen Paketnamen eintragen. Öffnen Sie dazu in Android Studio das Werkzeugfenster Terminal, und wechseln Sie in den Unterordner .android Ihres Heimatverzeichnisses. Geben Sie anschließend das folgende Kommando in einer Zeile ein. Es ermittelt den Fingerabdruck für das Debug-Zertifikat, das während der Entwicklung verwendet wird. ‐storepass und -keypass nennen die Passwörter für den Keystore und den Schlüssel.

keytool -list -alias androiddebugkey -keystore debug.keystore -storepass android -keypass android

Auf der Webseite klicken Sie auf Hinzufügen und tragen »com.thomaskuenneth.androidbuch.locationdemo2« sowie die durch Doppelpunkt getrennten Hexadezimalwerte ein. Beim Paketnamen handelt es sich um den Inhalt des Attributs package im <manifest />-Element einer Manifestdatei. Klicken Sie zuerst auf Fertig und danach auf Speichern, um den API-Schlüssel zu generieren.

Die Seite »Zugangsdaten«

Abbildung 8.5    Die Seite »Zugangsdaten«

[»]  Hinweis

Um einen Schlüssel für den produktiven Einsatz zu generieren, wechseln Sie stattdessen in das Verzeichnis mit dem Schlüsselbund aus Abschnitt 3.3.1, »Die App vorbereiten«. Das einzugebende Kommando weicht ebenfalls leicht ab. Ersetzen Sie bei der Eingabe die Werte nach –alias und –keystore entsprechend Ihren Eingaben beim Anlegen des Schlüsselbundes, zum Beispiel keytool -list ‐alias thomas ‐keystore Android-Keyring.

Der Android Studio-Projektassistent enthält die Vorlage Google Maps Activity. Mein Beispiel LocationDemo2 basiert darauf. Sie ist sehr praktisch, weil unter src/debug/res/values und src/release/res/values die Datei google_maps_api.xml hinzugefügt wird. Diese wird für die Entwicklung bzw. für den Release-Build verwendet. Beide sind in Abbildung 8.6 zu sehen. Wechseln Sie im Werkzeugfenster Project in die Sicht Project, und navigieren Sie zum gewünschten Knoten. Ersetzen Sie den Wert (YOUR_KEY_HERE) des <string />-Elements mit dem Namen google_maps_key durch Ihren API-Schlüssel. Unter debug tragen Sie den Schlüssel ein, den Sie mit dem Fingerabdruck aus der Datei debug.keystore verbunden haben. Der release-Zweig enthält den API-Key, der zu Ihrem eigenen Produktionszertifikat passt.

Zwei Varianten der Datei »google_maps_api.xml«

Abbildung 8.6    Zwei Varianten der Datei »google_maps_api.xml«

[»]  Hinweis

Möglicherweise erscheint eine Meldung, dass das Gerät Google Play Services nicht unterstützt. In Logcat wird zudem die Meldung »Google Play Store is missing« ausgegeben. Um das Problem zu beheben, müssen Sie den Emulator mit einem Systemabbild betreiben, das die Google APIs beinhaltet. Laden Sie einfach ein entsprechendes Image herunter. Nach dem Start von LocationDemo2 erwartet Sie in seltenen Fällen eine weitere Meldung, die Sie zum Herunterladen der Google Play Services auffordert. Dieser Download ist nötig, um mithilfe der Google Play Services auf Google Maps zuzugreifen. Nach dem Download ist die App dann aber einsatzbereit.

Bevor ich Ihnen zeige, wie Sie bestimmte geografische Koordinaten »ansteuern«, werfen wir einen kurzen Blick auf die vom Projektassistenten generierte Manifestdatei. Außer der angeforderten Berechtigung ACCESS_FINE_LOCATION ist das <meta-data />-Element mit dem Attribut android:name="com.google.android.geo.API_KEY" interessant. Auf diesem Weg wird den Google Play Services der für die Kommunikation mit Google Maps erforderliche API-Schlüssel übermittelt. Er befindet sich, wie Sie bereits wissen, in einem <string />-Tag mit dem Attribut name="google_maps_key" in der zweimal vorhandenen Datei google_maps_api.xml.

Eine Karte mit Marker in Sydney

Abbildung 8.7    Eine Karte mit Marker in Sydney

Die vom Projektassistenten bereitgestellte Implementierung der Karten-Activity zeigt in der Nähe von Sydney eine Markierung mit dem Label Marker in Sydney. Dies ist in Abbildung 8.7 zu sehen. Um stattdessen den letzten bekannten Standort »anzusteuern«, genügen ein paar Zeilen Code. Erzeugen Sie ein com.google.android.gms.maps.model.LatLng-Objekt, und übergeben Sie dieses an die Methode position() einer Instanz von com.google.android.gms.maps.model.MarkerOptions. Breite und Länge erfragen Sie mit latitude und longitude. addMarker() fügt der Karte das MarkerOptions-Objekt hinzu.

com.google.android.gms.maps.model.BitmapDescriptorFactory hilft Ihnen beim Erstellen von Markierungssymbolen. defaultMarker() liefert eine Standardmarkierung. Im folgenden Beispiel ist sie blau eingefärbt:

@Throws(SecurityException::class)
private fun markerDemo() {
val options = MarkerOptions()
val m = getSystemService(LocationManager::class.java)
// Hier könnte eine SecurityException geworfen werden
val loc = m.getLastKnownLocation(LocationManager.PASSIVE_PROVIDER)
loc?.run {
val pos = LatLng(latitude, longitude)
options.position(pos)
options.icon(
BitmapDescriptorFactory.defaultMarker(
BitmapDescriptorFactory.HUE_BLUE
)
)
mMap.addMarker(options)
}
}

Listing 8.6    Eine blaue Markierung am letzten bekannten Standort anzeigen

Vor der Verwendung des LocationManager müssen Sie den Benutzer um Erlaubnis fragen. Fügen Sie das folgende Quelltextfragment am besten am Ende der Methode onMapReady() ein. REQUEST_FINE_LOCATION ist eine (private) Int-Konstante mit beliebigem Wert.

if (checkSelfPermission(
Manifest.permission.ACCESS_FINE_LOCATION
)
!= PackageManager.PERMISSION_GRANTED
) {
requestPermissions(
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
REQUEST_FINE_LOCATION
)
} else {
markerDemo()
}

Listing 8.7    Anfordern einer Berechtigung

Darüber hinaus müssen Sie wie üblich onRequestPermissionsResult() überschreiben:

override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String?>,
grantResults: IntArray
) {
if (requestCode == REQUEST_FINE_LOCATION &&
grantResults.isNotEmpty() && grantResults[0] ==
PackageManager.PERMISSION_GRANTED
) {
markerDemo()
}
}

Listing 8.8    Auf das Gewähren oder Verweigern von Berechtigungen reagieren

Die BitmapDescriptorFactory-Methode fromResource() nutzt Bitmap-Grafiken als Marker. Probieren Sie doch einmal die folgende Anweisung als Alternative zum Setzen des Default-Markers (defaultMarker()) aus. <my_bitmap> müssen Sie durch den Namen einer Bitmap in drawable ersetzen.

options.icon(BitmapDescriptorFactory.fromResource(
R.drawable.<my_bitmap>))

Sie können Karten in weiten Grenzen konfigurieren. Der Ausdruck mMap.uiSettings.isZoomControlsEnabled = true blendet zum Beispiel Bedienelemente ein, mit denen Sie in die Karte hinein- und aus ihr herauszoomen können. Dies ist in Abbildung 8.8 zu sehen.

Das von uiSettings gelieferte Objekt bietet einige weitere Einstellungen. isCompassEnabled zeigt den Kompass an oder verbirgt ihn. Bitte beachten Sie dabei, dass er nur dann dargestellt wird, wenn die Kartenansicht gedreht oder geneigt wurde. isMapToolbarEnabled steuert die Sichtbarkeit einer kontextabhängigen Werkzeugleiste. Mit ihr kann unter anderem der aktuelle Kartenausschnitt in der Google-Maps-App dargestellt werden. Die Toolbar erscheint üblicherweise erst nach dem Antippen eines Markersymbols.

Kartenansicht mit Kompass, Zoom-Controls und Map-Toolbar

Abbildung 8.8    Kartenansicht mit Kompass, Zoom-Controls und Map-Toolbar

Kamera

Die Sicht auf eine Karte wird mit der Kamera festgelegt. Sie blickt von »schräg oben« auf eine flache Ebene. Dabei können folgende Parameter verändert werden:

  1. Ziel (position): das Zentrum der Karte in geografischer Länge und Breite

  2. Zoom: Hiermit wird der Maßstab festgelegt. Mit steigendem Zoomfaktor werden mehr Details sichtbar. Bei einem Zoomlevel 0 entspricht die Welt in der Breite ca. 256 geräteunabhängigen Pixeln. Bei 1 sind dies in etwa 512 dp. Daraus ergibt sich die Formel 256 × 2n dp.

  3. Orientierung (bearing): Hiermit legen Sie fest, um wie viel Grad im Uhrzeigersinn die Karte gegenüber nördlicher Richtung gedreht werden soll.

  4. Blickwinkel (tilt): Der Blickwinkel steuert die Kameraposition auf einem gedachten Kreisbogen direkt über dem Zentrum der Karte und der Erdoberfläche.

Kameraänderungen erfolgen unter Zuhilfenahme eines com.google.android.gms. maps.CameraUpdate-Objekts. Sie instanziieren es nicht direkt, sondern nutzen die Klasse CameraUpdateFactory im selben Paket. Beispielsweise liefern Ihnen die beiden Aufrufe CameraUpdateFactory.zoomIn() und CameraUpdateFactory.zoomOut() CameraUpdate-Instanzen, die den Zoomfaktor um 1.0 vergrößern oder verkleinern, alle anderen Parameter aber unangetastet lassen. Mit newLatLng() ändern Sie die Position der Kamera. Auch hier bleiben alle anderen Einstellungen erhalten. newCameraPosition() ändert auch Blickwinkel, Zoomlevel und Orientierung. newLatLngZoom() ist praktisch, wenn Sie neben einer neuen Position gleich den Zoomlevel setzen möchten. Um ein CameraUpdate-Objekt auf eine Karte anzuwenden, rufen Sie entweder die Methode moveCamera() oder animateCamera() der Karteninstanz auf. Erstere springt unmittelbar zu der neuen Position.

val berlin = LatLng(
Location.convert("52:31:12"),
Location.convert("13:24:36")
)
val cu1 = CameraUpdateFactory.newLatLngZoom(berlin, 8f)
mMap.moveCamera(cu1)

Listing 8.9    Kameraposition unmittelbar verändern

Dies wirkt für den Anwender möglicherweise sehr abrupt, deshalb ist es besser, mit animateCamera() eine Kamerafahrt zu initiieren. Im folgenden Beispiel wird nicht nur das Ziel, sondern auch Zoom, Orientierung und Blickwinkel gesetzt. Hierfür verwende ich einen CameraPosition.Builder.

val nuernberg = LatLng(
Location.convert("49:27:20"),
Location.convert("11:04:43")
)
val cameraPosition = CameraPosition.Builder()
.target(nuernberg)
.zoom(17f)
.bearing(90f)
.tilt(30f)
.build()
val cu3 = CameraUpdateFactory.newCameraPosition(cameraPosition)
mMap.animateCamera(cu3, 5000, null)

Listing 8.10    Eine Kamerafahrt

Der zweite Parameter der Methode animateCamera() gibt die Dauer der Kamerafahrt in Millisekunden an. Der dritte ist die Referenz auf ein com.google.android.gms.maps. GoogleMap.CancelableCallback-Objekt. Die Methoden onFinish() und onCancel() werden aufgerufen, wenn die Animation erfolgreich beendet oder abgebrochen wurde. Um eine Kamerafahrt vorzeitig zu beenden, rufen Sie stopAnimation() auf.

 


Ihre Meinung?

Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de

<< zurück
Zur Rheinwerk-Konferenz für Kotlin
 Buchempfehlungen
Zum Rheinwerk-Shop: Kotlin

Kotlin


Zum Rheinwerk-Shop: Praxisbuch Usability und UX

Praxisbuch Usability und UX


Zum Rheinwerk-Shop: Flutter und Dart

Flutter und Dart


Zum Rheinwerk-Shop: App-Design

App-Design


 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und in die Schweiz
InfoInfo

 
 


Copyright © Rheinwerk Verlag GmbH 2023
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das Openbook denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt.
Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.

 
[Rheinwerk Computing]

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de

Cookie-Einstellungen ändern