Standortdaten

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

Kotlin

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.annotation.SuppressLint
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.
     */
    @SuppressLint("MissingPermission")
    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) {
          super.onRequestPermissionsResult(requestCode, permissions, grantResults)
          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:

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.

Weitere Informationen

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.