Eine der besonderen Eigenschaften mobiler Apps ist die Standorterkennung. Nutzer verwenden ihre Mobilgeräte überall. Wenn du die Standorterkennung hinzufügst, kannst du die in deiner App bereitgestellten Informationen an den Nutzerkontext anpassen.
Codebeispiele
Das ApiDemos-Repository auf GitHub enthält Beispiele, in denen die Verwendung des Standorts auf einer Karte veranschaulicht wird:
Java
- MyLocationDemoActivity: Ebene „Mein Standort“ verwenden, einschließlich Laufzeitberechtigungen.
- LocationSourceDemoActivity: Benutzerdefiniertes
LocationSource
-Element verwenden. - CurrentPlaceDetailsOnMap: Aktuellen Standort eines Android-Geräts ermitteln und Details (Geschäft oder anderer POI) zu diesem Standort angeben. Weitere Informationen findest du in der Anleitung zum Anzeigen der aktuellen Ortsdaten auf einer Karte.
Kotlin
- MyLocationDemoActivity: Ebene „Mein Standort“ verwenden, einschließlich Laufzeitberechtigungen.
- CurrentPlaceDetailsOnMap: Aktuellen Standort eines Android-Geräts ermitteln und Details (Geschäft oder anderer POI) zu diesem Standort angeben. Weitere Informationen findest du in der Anleitung zum Anzeigen der aktuellen Ortsdaten auf einer Karte.
Mit Standortdaten arbeiten
Die für ein Android-Gerät verfügbaren Standortdaten beinhalten den aktuellen Standort des Geräts, der mithilfe verschiedener Technologien bestimmt wird, die Richtung und Methode der Fortbewegung sowie die Angabe, ob das Gerät über eine vordefinierte geografische Begrenzung, einen sogenannten Geofence, bewegt wurde. Je nach den Anforderungen deiner App kannst du zwischen verschiedenen Methoden zum Arbeiten mit Standortdaten wählen:
- Die Ebene Mein Standort ist eine einfache Möglichkeit, den Standort eines Geräts auf der Karte anzuzeigen. Mit der Ebene werden keine Daten bereitgestellt.
- Wenn Standortdaten programmatisch angefordert werden sollen, empfehlen wir die Standort-API der Google Play-Dienste.
- Über die Schnittstelle
LocationSource
kannst du einen benutzerdefinierten Standortanbieter angeben.
Berechtigungen zur Standortermittlung
Wenn für deine App der Zugriff auf den Standort des Nutzers erforderlich ist, musst du die Berechtigung anfordern, indem du deiner App die entsprechende Android-Berechtigung zur Standortermittlung hinzufügst.
In Android sind zwei Berechtigungen zur Standortermittlung verfügbar: ACCESS_COARSE_LOCATION
und ACCESS_FINE_LOCATION
. Durch die ausgewählte Berechtigung wird die Genauigkeit des von der API zurückgegebenen Standorts bestimmt. Du musst nur eine der Android-Standortberechtigungen anfordern, je nachdem, wie genau es sein soll:
android.permission.ACCESS_COARSE_LOCATION
– Ermöglicht der API, den Standort des Geräts anhand von WLAN- und/oder Mobilfunkdaten zu bestimmen. Der Standort wird von der API mit einer Genauigkeit von etwa einem Häuserblock zurückgegeben.android.permission.ACCESS_FINE_LOCATION
– Sorgt für eine möglichst präzise Standortbestimmung durch die API, indem Daten von Standortanbietern verwendet werden, einschließlich Global Positioning System (GPS) sowie WLAN- und Mobiltelefondaten.
App-Manifest Berechtigungen hinzufügen
Füge eine der folgenden Berechtigungen als untergeordnetes <manifest>
-Element in dein Android-Manifest ein. Entweder die Berechtigung zur Ermittlung des groben Standorts:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.myapp" > ... <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> ... </manifest>
Oder die Berechtigung zur Ermittlung des genauen Standorts:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.myapp" > ... <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> ... </manifest>
Laufzeitberechtigungen anfordern
Mit Android 6.0 (Marshmallow) wird ein neues Modell zur Handhabung von Berechtigungen eingeführt, das den Installations- und Upgradevorgang von Apps für den Nutzer vereinfacht. Wenn deine App für API-Level 23 oder höher vorgesehen ist, kannst du dieses neue Berechtigungsmodell verwenden.
Falls deine App das neue Berechtigungsmodell unterstützt und auf dem Gerät Android 6.0 (Marshmallow) oder höher ausgeführt wird, muss der Nutzer beim Installieren oder Aktualisieren der App keine Berechtigungen erteilen. In der App muss geprüft werden, ob die erforderlichen Berechtigungen zur Laufzeit vorliegen. Ist das nicht der Fall, müssen diese Berechtigungen angefordert werden. Vom System wird ein Dialogfenster angezeigt, in dem der Nutzer aufgefordert wird, die Berechtigung zu erteilen.
Weil es nutzerfreundlicher ist, sollte die Berechtigung im entsprechenden Kontext angefordert werden. Wenn der Standort erforderlich ist, um die App nutzen zu können, sollte die Berechtigung beim Start der App angefordert werden. Eine gute Möglichkeit dazu ist ein freundlicher Begrüßungsbildschirm oder ein Assistent, der die Nutzer darüber informiert, warum die Berechtigung erforderlich ist.
Wenn die Berechtigung nur für einen Teil der App-Funktionen erforderlich ist, solltest du die Standortberechtigungen dann anfordern, wenn die Aktion ausgeführt wird, für die eine Berechtigung benötigt wird.
In der App muss taktvoll auf die Entscheidung der Nutzer reagiert werden, wenn sie sich dazu entscheiden, die Berechtigung nicht zu erteilen. Wenn die Berechtigung beispielsweise für eine bestimmte Funktion benötigt wird, kann sie in der App deaktiviert werden. Falls die App nur funktioniert, wenn die Berechtigung vorliegt, ist der Nutzer darüber zu informieren, dass seine Einwilligung Voraussetzung für die Verwendung der App ist.
Mit folgendem Codebeispiel wird eine Berechtigungsprüfung mithilfe der Android Support Library vor der Aktivierung der Ebene „Mein Standort“ ausgeführt: Das Ergebnis der Berechtigungsanfrage wird dann verarbeitet, indem der ActivityCompat.OnRequestPermissionsResultCallback
aus der Support Library implementiert wird:
Java
// Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.example.mapdemo; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.GoogleMap.OnMyLocationButtonClickListener; import com.google.android.gms.maps.GoogleMap.OnMyLocationClickListener; import com.google.android.gms.maps.OnMapReadyCallback; import com.google.android.gms.maps.SupportMapFragment; import android.Manifest; import android.content.pm.PackageManager; import android.location.Location; import android.os.Bundle; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import android.widget.Toast; /** * This demo shows how GMS Location can be used to check for changes to the users location. The * "My Location" button uses GMS Location to set the blue dot representing the users location. * Permission for {@link android.Manifest.permission#ACCESS_FINE_LOCATION} is requested at run * time. If the permission has not been granted, the Activity is finished with an error message. */ public class MyLocationDemoActivity extends AppCompatActivity implements OnMyLocationButtonClickListener, OnMyLocationClickListener, OnMapReadyCallback, ActivityCompat.OnRequestPermissionsResultCallback { /** * Request code for location permission request. * * @see #onRequestPermissionsResult(int, String[], int[]) */ private static final int LOCATION_PERMISSION_REQUEST_CODE = 1; /** * Flag indicating whether a requested permission has been denied after returning in * {@link #onRequestPermissionsResult(int, String[], int[])}. */ private boolean permissionDenied = false; private GoogleMap map; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.my_location_demo); SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map); mapFragment.getMapAsync(this); } @Override public void onMapReady(GoogleMap googleMap) { map = googleMap; map.setOnMyLocationButtonClickListener(this); map.setOnMyLocationClickListener(this); enableMyLocation(); } /** * Enables the My Location layer if the fine location permission has been granted. */ private void enableMyLocation() { if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { if (map != null) { map.setMyLocationEnabled(true); } } else { // Permission to access the location is missing. Show rationale and request permission PermissionUtils.requestPermission(this, LOCATION_PERMISSION_REQUEST_CODE, Manifest.permission.ACCESS_FINE_LOCATION, true); } } @Override public boolean onMyLocationButtonClick() { Toast.makeText(this, "MyLocation button clicked", Toast.LENGTH_SHORT).show(); // Return false so that we don't consume the event and the default behavior still occurs // (the camera animates to the user's current position). return false; } @Override public void onMyLocationClick(@NonNull Location location) { Toast.makeText(this, "Current location:\n" + location, Toast.LENGTH_LONG).show(); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if (requestCode != LOCATION_PERMISSION_REQUEST_CODE) { return; } if (PermissionUtils.isPermissionGranted(permissions, grantResults, Manifest.permission.ACCESS_FINE_LOCATION)) { // Enable the my location layer if the permission has been granted. enableMyLocation(); } else { // Permission was denied. Display an error message // Display the missing permission error dialog when the fragments resume. permissionDenied = true; } } @Override protected void onResumeFragments() { super.onResumeFragments(); if (permissionDenied) { // Permission was not granted, display error dialog. showMissingPermissionError(); permissionDenied = false; } } /** * Displays a dialog with error message explaining that the location permission is missing. */ private void showMissingPermissionError() { PermissionUtils.PermissionDeniedDialog .newInstance(true).show(getSupportFragmentManager(), "dialog"); } }
Kotlin
// Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.example.kotlindemos import android.Manifest import android.content.pm.PackageManager import android.location.Location import android.os.Bundle import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.core.app.ActivityCompat.OnRequestPermissionsResultCallback import androidx.core.content.ContextCompat import com.example.kotlindemos.PermissionUtils.PermissionDeniedDialog.Companion.newInstance import com.example.kotlindemos.PermissionUtils.isPermissionGranted import com.example.kotlindemos.PermissionUtils.requestPermission import com.google.android.gms.maps.GoogleMap import com.google.android.gms.maps.GoogleMap.OnMyLocationButtonClickListener import com.google.android.gms.maps.GoogleMap.OnMyLocationClickListener import com.google.android.gms.maps.OnMapReadyCallback import com.google.android.gms.maps.SupportMapFragment /** * This demo shows how GMS Location can be used to check for changes to the users location. The * "My Location" button uses GMS Location to set the blue dot representing the users location. * Permission for [Manifest.permission.ACCESS_FINE_LOCATION] is requested at run * time. If the permission has not been granted, the Activity is finished with an error message. */ class MyLocationDemoActivity : AppCompatActivity(), OnMyLocationButtonClickListener, OnMyLocationClickListener, OnMapReadyCallback, OnRequestPermissionsResultCallback { /** * Flag indicating whether a requested permission has been denied after returning in * [.onRequestPermissionsResult]. */ private var permissionDenied = false private lateinit var map: GoogleMap override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.my_location_demo) val mapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment? mapFragment?.getMapAsync(this) } override fun onMapReady(googleMap: GoogleMap?) { map = googleMap ?: return googleMap.setOnMyLocationButtonClickListener(this) googleMap.setOnMyLocationClickListener(this) enableMyLocation() } /** * Enables the My Location layer if the fine location permission has been granted. */ private fun enableMyLocation() { if (!::map.isInitialized) return if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { map.isMyLocationEnabled = true } else { // Permission to access the location is missing. Show rationale and request permission requestPermission(this, LOCATION_PERMISSION_REQUEST_CODE, Manifest.permission.ACCESS_FINE_LOCATION, true ) } } override fun onMyLocationButtonClick(): Boolean { Toast.makeText(this, "MyLocation button clicked", Toast.LENGTH_SHORT).show() // Return false so that we don't consume the event and the default behavior still occurs // (the camera animates to the user's current position). return false } override fun onMyLocationClick(location: Location) { Toast.makeText(this, "Current location:\n$location", Toast.LENGTH_LONG).show() } override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) { if (requestCode != LOCATION_PERMISSION_REQUEST_CODE) { return } if (isPermissionGranted(permissions, grantResults, Manifest.permission.ACCESS_FINE_LOCATION)) { // Enable the my location layer if the permission has been granted. enableMyLocation() } else { // Permission was denied. Display an error message // Display the missing permission error dialog when the fragments resume. permissionDenied = true } } override fun onResumeFragments() { super.onResumeFragments() if (permissionDenied) { // Permission was not granted, display error dialog. showMissingPermissionError() permissionDenied = false } } /** * Displays a dialog with error message explaining that the location permission is missing. */ private fun showMissingPermissionError() { newInstance(true).show(supportFragmentManager, "dialog") } companion object { /** * Request code for location permission request. * * @see .onRequestPermissionsResult */ private const val LOCATION_PERMISSION_REQUEST_CODE = 1 } }
Ebene „Mein Standort“
Wenn die Ebene „Mein Standort“ aktiviert ist, wird die Schaltfläche „Mein Standort“ in der oberen rechten Ecke der Karte angezeigt. Rufe mMap.setMyLocationEnabled()
auf, um die Ebene „Mein Standort“ auf der Karte zu aktivieren.
Im folgenden Beispiel wird eine einfache Verwendung der Ebene „Mein Standort“ veranschaulicht:
Java
// Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.google.maps.example; import android.annotation.SuppressLint; import android.location.Location; import android.os.Bundle; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.OnMapReadyCallback; import com.google.android.gms.maps.SupportMapFragment; class MyLocationLayerActivity extends AppCompatActivity implements GoogleMap.OnMyLocationButtonClickListener, GoogleMap.OnMyLocationClickListener, OnMapReadyCallback { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_my_location); SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map); mapFragment.getMapAsync(this); } @SuppressLint("MissingPermission") @Override public void onMapReady(GoogleMap map) { // TODO: Before enabling the My Location layer, you must request // location permission from the user. This sample does not include // a request for location permission. map.setMyLocationEnabled(true); map.setOnMyLocationButtonClickListener(this); map.setOnMyLocationClickListener(this); } @Override public void onMyLocationClick(@NonNull Location location) { Toast.makeText(this, "Current location:\n" + location, Toast.LENGTH_LONG) .show(); } @Override public boolean onMyLocationButtonClick() { Toast.makeText(this, "MyLocation button clicked", Toast.LENGTH_SHORT) .show(); // Return false so that we don't consume the event and the default behavior still occurs // (the camera animates to the user's current position). return false; } }
Kotlin
// Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.google.maps.example.kotlin import android.annotation.SuppressLint import android.location.Location import android.os.Bundle import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import com.google.android.gms.maps.GoogleMap import com.google.android.gms.maps.GoogleMap.OnMyLocationButtonClickListener import com.google.android.gms.maps.GoogleMap.OnMyLocationClickListener import com.google.android.gms.maps.OnMapReadyCallback import com.google.android.gms.maps.SupportMapFragment import com.google.maps.example.R internal class MyLocationLayerActivity : AppCompatActivity(), OnMyLocationButtonClickListener, OnMyLocationClickListener, OnMapReadyCallback { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_my_location) val mapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment mapFragment.getMapAsync(this) } @SuppressLint("MissingPermission") override fun onMapReady(map: GoogleMap) { // TODO: Before enabling the My Location layer, you must request // location permission from the user. This sample does not include // a request for location permission. map.isMyLocationEnabled = true map.setOnMyLocationButtonClickListener(this) map.setOnMyLocationClickListener(this) } override fun onMyLocationClick(location: Location) { Toast.makeText(this, "Current location:\n$location", Toast.LENGTH_LONG) .show() } override fun onMyLocationButtonClick(): Boolean { Toast.makeText(this, "MyLocation button clicked", Toast.LENGTH_SHORT) .show() // Return false so that we don't consume the event and the default behavior still occurs // (the camera animates to the user's current position). return false } }
Ist die Ebene „Mein Standort“ aktiviert, wird rechts oben auf der Karte die Schaltfläche „Mein Standort“ angezeigt. Wenn ein Nutzer auf die Schaltfläche klickt, richtet die Kamera die Karte auf den aktuellen Standort des Geräts aus, sofern bekannt. Der Standort wird auf der Karte durch einen kleinen blauen Punkt gekennzeichnet, wenn das Gerät sich nicht bewegt, oder durch einen Navigationspfeil, wenn das Gerät in Bewegung ist.
Im folgenden Screenshot ist die Schaltfläche „Mein Standort“ oben rechts und der blaue Punkt „Mein Standort“ in der Mitte der Karte zu sehen:
Wenn die Schaltfläche „Mein Standort“ nicht erscheinen soll, kannst du dies durch Aufrufen von UiSettings.setMyLocationButtonEnabled(false)
verhindern.
Deine App kann auf folgende Ereignisse reagieren:
- Wenn der Nutzer auf die Schaltfläche „Mein Standort“ klickt, erhält deine App einen
onMyLocationButtonClick()
-Callback vomGoogleMap.OnMyLocationButtonClickListener
. - Klickt der Nutzer auf den blauen Punkt „Mein Standort“, erhält deine App einen
onMyLocationClick()
-Callback vomGoogleMap.OnMyLocationClickListener
.
Aus unseren Nutzungsbedingungen
Datenschutz gewährleisten
und Nutzer informieren
Informiere die Nutzer immer darüber, wie du ihre Daten verwendest. Es darf nicht möglich sein, einzelne Nutzer zu identifizieren. Hole die Einwilligung der Nutzer ein, bevor du ihren Standort verwendest. Außerdem müssen die Nutzer jederzeit die Möglichkeit haben, diese Einwilligung zu widerrufen.

Standort-API der Google Play-Dienste
Die Standort-API der Google Play-Dienste ist die bevorzugte Methode, um die Standorterkennung in eine Android-App einzubinden. Ihre Funktionen ermöglichen dir Folgendes:
- Bestimmen des Gerätestandorts
- Beobachten von Standortänderungen
- Bestimmen des Verkehrsmittels bei einem bewegten Gerät
- Erstellen und Beobachten vordefinierter Regionen, sogenannter Geofences
Mithilfe von Standort-APIs kannst du ganz leicht energieeffiziente Apps mit Standorterkennung erstellen. Wie das Maps SDK for Android wird die Location API als Teil des Google Play Services SDK bereitgestellt. Weitere Informationen zur Location API findest du im Android-Schulungskurs zur Location API oder in der Location API-Referenz. Codebeispiele sind ebenfalls im Google Play Services SDK enthalten.