Beim Geofencing wird die Kenntnis des aktuellen Standorts des Nutzers mit der Erkennung der Nähe des Nutzers zu interessanten Orten kombiniert. Wenn Sie einen interessanten Ort markieren möchten, geben Sie dessen Breiten- und Längengrad an. Wenn Sie die Entfernung für den Standort anpassen möchten, fügen Sie einen Umkreis hinzu. Mit Breiten-, Längengrad und Radius wird ein Geofence definiert. Dabei wird ein kreisförmiger Bereich um den betreffenden Ort herum erstellt.
Sie können mehrere aktive Geofences haben. Pro App und Gerätenutzer sind maximal 100 Geofences möglich. Für jeden Geofence können Sie die Standortdienste bitten, Ihnen Ein- und Ausstiegsereignisse zu senden, oder Sie können eine Dauer innerhalb des Geofence-Bereichs angeben, die gewartet werden soll (Verweildauer), bevor ein Ereignis ausgelöst wird. Sie können die Dauer eines Geofence begrenzen, indem Sie eine Ablaufdauer in Millisekunden angeben. Nach Ablauf des Geofence wird er von den Ortungsdiensten automatisch entfernt.
In dieser Lektion erfahren Sie, wie Sie Geofences hinzufügen und entfernen und anschließend mit BroadcastReceiver
auf Geofence-Übergänge warten.
Geofence-Monitoring einrichten
Der erste Schritt beim Anfordern des Geofence-Monitoring besteht darin, die erforderlichen Berechtigungen anzufordern. Damit Sie Geofencing verwenden können, muss Ihre App Folgendes anfordern:
-
ACCESS_FINE_LOCATION
-
ACCESS_BACKGROUND_LOCATION
wenn deine App auf Android 10 (API-Level 29) oder höher ausgerichtet ist
Weitere Informationen findest du in der Anleitung zum Anfordern von Berechtigungen zur Standortermittlung.
Wenn Sie ein BroadcastReceiver
verwenden möchten, um Geofence-Übergänge zu beobachten, fügen Sie ein Element hinzu, das den Dienstnamen angibt. Dieses Element muss dem Element
<application>
untergeordnet sein:
<application android:allowBackup="true"> ... <receiver android:name=".GeofenceBroadcastReceiver"/> <application/>
Um auf die Standort-APIs zugreifen zu können, müssen Sie eine Instanz des Geofencing-Clients erstellen. So stellen Sie eine Verbindung zu Ihrem Kunden her:
Kotlin
lateinit var geofencingClient: GeofencingClient override fun onCreate(savedInstanceState: Bundle?) { // ... geofencingClient = LocationServices.getGeofencingClient(this) }
Java
private GeofencingClient geofencingClient; @Override public void onCreate(Bundle savedInstanceState) { // ... geofencingClient = LocationServices.getGeofencingClient(this); }
Geofences erstellen und hinzufügen
Ihre App muss Geofences mithilfe der Builder-Klasse der Location API zum Erstellen von Geofence-Objekten und der Convenience-Klasse zum Hinzufügen von Geofences erstellen und hinzufügen. Um die Intents zu verarbeiten, die von den Standortdiensten bei Geofence-Übergängen gesendet werden, kannst du ein PendingIntent
definieren, wie in diesem Abschnitt gezeigt.
Hinweis:Auf Einzelnutzergeräten gilt ein Limit von 100 Geofences pro App. Bei Geräten mit mehreren Nutzern liegt das Limit bei 100 Geofences pro App und Gerätenutzer.
Geofence-Objekte erstellen
Erstellen Sie zuerst mit
Geofence.Builder
einen Geofence. Legen Sie dabei den gewünschten Radius, die Dauer und die Übergangstypen für den Geofence fest. So füllen Sie beispielsweise ein Listenobjekt aus:
Kotlin
geofenceList.add(Geofence.Builder() // Set the request ID of the geofence. This is a string to identify this // geofence. .setRequestId(entry.key) // Set the circular region of this geofence. .setCircularRegion( entry.value.latitude, entry.value.longitude, Constants.GEOFENCE_RADIUS_IN_METERS ) // Set the expiration duration of the geofence. This geofence gets automatically // removed after this period of time. .setExpirationDuration(Constants.GEOFENCE_EXPIRATION_IN_MILLISECONDS) // Set the transition types of interest. Alerts are only generated for these // transition. We track entry and exit transitions in this sample. .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER or Geofence.GEOFENCE_TRANSITION_EXIT) // Create the geofence. .build())
Java
geofenceList.add(new Geofence.Builder() // Set the request ID of the geofence. This is a string to identify this // geofence. .setRequestId(entry.getKey()) .setCircularRegion( entry.getValue().latitude, entry.getValue().longitude, Constants.GEOFENCE_RADIUS_IN_METERS ) .setExpirationDuration(Constants.GEOFENCE_EXPIRATION_IN_MILLISECONDS) .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT) .build());
In diesem Beispiel werden Daten aus einer Konstantendatei abgerufen. In der Praxis könnten Apps dynamisch Geofences erstellen, die auf dem Standort des Nutzers basieren.
Geofences und anfängliche Trigger angeben
Im folgenden Snippet werden die Klasse
GeofencingRequest
und ihre verschachtelte
GeofencingRequestBuilder
-Klasse verwendet, um die zu überwachenden Geofences anzugeben und festzulegen, wie verwandte Geofence-Ereignisse ausgelöst werden:
Kotlin
private fun getGeofencingRequest(): GeofencingRequest { return GeofencingRequest.Builder().apply { setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER) addGeofences(geofenceList) }.build() }
Java
private GeofencingRequest getGeofencingRequest() { GeofencingRequest.Builder builder = new GeofencingRequest.Builder(); builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER); builder.addGeofences(geofenceList); return builder.build(); }
Dieses Beispiel zeigt die Verwendung von zwei Geofence-Triggern. Der Übergang
GEOFENCE_TRANSITION_ENTER
wird ausgelöst, wenn ein Gerät in einen Geofence fällt, und der Übergang
GEOFENCE_TRANSITION_EXIT
, wenn ein Gerät einen Geofence verlässt. Durch die Angabe von
INITIAL_TRIGGER_ENTER
wird für die Standortdienste festgelegt, dass
GEOFENCE_TRANSITION_ENTER
ausgelöst werden soll, wenn sich das Gerät bereits innerhalb des Geofence befindet.
In vielen Fällen ist die Verwendung von
INITIAL_TRIGGER_DWELL
besser geeignet, um Ereignisse nur dann auszulösen, wenn der Nutzer für eine festgelegte Dauer innerhalb eines Geofence anhält.
Dieser Ansatz kann dazu beitragen, „Spambenachrichtigungen“ zu reduzieren, die durch eine große Anzahl von Benachrichtigungen entstehen, wenn ein Gerät kurz in Geofences eintritt oder diesen verlässt. Eine weitere Strategie für optimale Ergebnisse aus Ihren Geofences besteht darin, einen Mindestradius von 100 Metern festzulegen. Dadurch wird die Standortgenauigkeit typischer WLANs berücksichtigt und der Stromverbrauch des Geräts reduziert.
Einen Broadcast-Empfänger für Geofence-Übergänge definieren
Ein Intent
, das von den Standortdiensten gesendet wird, kann verschiedene Aktionen in deiner App auslösen. Du solltest jedoch nicht zulassen, dass es eine Aktivität oder ein Fragment startet, da Komponenten nur als Reaktion auf eine Nutzeraktion sichtbar werden sollen. In vielen Fällen ist ein BroadcastReceiver
eine gute Möglichkeit, einen Geofence-Übergang zu verarbeiten. Ein BroadcastReceiver
erhält Updates, wenn ein Ereignis eintritt, z. B. ein Übergang in einen oder aus einem Geofence, und kann lang andauernde Hintergrundarbeiten beginnen.
Das folgende Snippet zeigt, wie ein PendingIntent
definiert wird, das einen BroadcastReceiver
startet:
Kotlin
class MainActivity : AppCompatActivity() { // ... private val geofencePendingIntent: PendingIntent by lazy { val intent = Intent(this, GeofenceBroadcastReceiver::class.java) // We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when calling // addGeofences() and removeGeofences(). PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT) } }
Java
public class MainActivity extends AppCompatActivity { // ... private PendingIntent getGeofencePendingIntent() { // Reuse the PendingIntent if we already have it. if (geofencePendingIntent != null) { return geofencePendingIntent; } Intent intent = new Intent(this, GeofenceBroadcastReceiver.class); // We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when // calling addGeofences() and removeGeofences(). geofencePendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent. FLAG_UPDATE_CURRENT); return geofencePendingIntent; }
Geofences hinzufügen
Verwenden Sie die Methode
, um Geofences hinzuzufügen.
Geben Sie das Objekt GeofencingClient.addGeofences()
GeofencingRequest
und PendingIntent
an.
Das folgende Snippet veranschaulicht die Verarbeitung der Ergebnisse:
Kotlin
geofencingClient?.addGeofences(getGeofencingRequest(), geofencePendingIntent)?.run { addOnSuccessListener { // Geofences added // ... } addOnFailureListener { // Failed to add geofences // ... } }
Java
geofencingClient.addGeofences(getGeofencingRequest(), getGeofencePendingIntent()) .addOnSuccessListener(this, new OnSuccessListener<Void>() { @Override public void onSuccess(Void aVoid) { // Geofences added // ... } }) .addOnFailureListener(this, new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { // Failed to add geofences // ... } });
Geofence-Übergänge verarbeiten
Wenn die Standortdienste erkennen, dass der Nutzer einen Geofence betreten oder verlassen hat, sendet er die Intent
in der PendingIntent
, die Sie in der Anfrage zum Hinzufügen von Geofences angegeben haben. Ein Broadcast-Empfänger wie GeofenceBroadcastReceiver
stellt fest, dass Intent
aufgerufen wurde, und kann dann das Geofencing-Ereignis vom Intent abrufen, den Typ der Geofence-Übergänge bestimmen und ermitteln, welche der definierten Geofences ausgelöst wurden. Der Broadcast-Empfänger kann eine App anweisen, im Hintergrund zu arbeiten, oder gegebenenfalls eine Benachrichtigung als Ausgabe zu senden.
Hinweis:Unter Android 8.0 (API-Level 26) und höher reagiert das Gerät alle paar Minuten auf Geofencing-Ereignisse, wenn eine App im Hintergrund ausgeführt wird, während ein Geofence überwacht wird. Informationen zum Anpassen Ihrer App an diese Antwortlimits finden Sie unter Limits für die Standortermittlung im Hintergrund.
Das folgende Snippet zeigt, wie ein BroadcastReceiver
definiert wird, das eine Benachrichtigung sendet, wenn ein Geofence-Übergang erfolgt. Wenn der Nutzer auf die Benachrichtigung klickt, wird die Hauptaktivität der App angezeigt:
Kotlin
class GeofenceBroadcastReceiver : BroadcastReceiver() { // ... override fun onReceive(context: Context?, intent: Intent?) { val geofencingEvent = GeofencingEvent.fromIntent(intent) if (geofencingEvent.hasError()) { val errorMessage = GeofenceStatusCodes .getStatusCodeString(geofencingEvent.errorCode) Log.e(TAG, errorMessage) return } // Get the transition type. val geofenceTransition = geofencingEvent.geofenceTransition // Test that the reported transition was of interest. if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER | geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) { // Get the geofences that were triggered. A single event can trigger // multiple geofences. val triggeringGeofences = geofencingEvent.triggeringGeofences // Get the transition details as a String. val geofenceTransitionDetails = getGeofenceTransitionDetails( this, geofenceTransition, triggeringGeofences ) // Send notification and log the transition details. sendNotification(geofenceTransitionDetails) Log.i(TAG, geofenceTransitionDetails) } else { // Log the error. Log.e(TAG, getString(R.string.geofence_transition_invalid_type, geofenceTransition)) } } }
Java
public class GeofenceBroadcastReceiver extends BroadcastReceiver { // ... protected void onReceive(Context context, Intent intent) { GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent); if (geofencingEvent.hasError()) { String errorMessage = GeofenceStatusCodes .getStatusCodeString(geofencingEvent.getErrorCode()); Log.e(TAG, errorMessage); return; } // Get the transition type. int geofenceTransition = geofencingEvent.getGeofenceTransition(); // Test that the reported transition was of interest. if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER || geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) { // Get the geofences that were triggered. A single event can trigger // multiple geofences. List<Geofence> triggeringGeofences = geofencingEvent.getTriggeringGeofences(); // Get the transition details as a String. String geofenceTransitionDetails = getGeofenceTransitionDetails( this, geofenceTransition, triggeringGeofences ); // Send notification and log the transition details. sendNotification(geofenceTransitionDetails); Log.i(TAG, geofenceTransitionDetails); } else { // Log the error. Log.e(TAG, getString(R.string.geofence_transition_invalid_type, geofenceTransition)); } } }
Nachdem das Übergangsereignis über PendingIntent
erkannt wurde, ruft das BroadcastReceiver
den Geofence-Übergangstyp ab und testet, ob dies eines der Ereignisse ist, das die App zum Auslösen von Benachrichtigungen verwendet – in diesem Fall entweder GEOFENCE_TRANSITION_ENTER
oder GEOFENCE_TRANSITION_EXIT
. Der Dienst sendet dann eine Benachrichtigung und protokolliert die Übergangsdetails.
Geofence-Monitoring beenden
Wenn Sie das Geofencing-Monitoring beenden, wenn es nicht mehr benötigt oder erwünscht ist, können Sie den Akku und die CPU-Zyklen des Geräts entlasten. Sie können das Geofencing-Monitoring in der Hauptaktivität beenden, die zum Hinzufügen und Entfernen von Geofences verwendet wird. Durch das Entfernen eines Geofences wird es sofort gestoppt. Die API bietet Methoden zum Entfernen von Geofences entweder über Anfrage-IDs oder durch Entfernen von Geofences, die mit einem bestimmten PendingIntent
verknüpft sind.
Mit dem folgenden Snippet werden Geofences nach PendingIntent
entfernt. Alle weiteren Benachrichtigungen werden gestoppt, wenn das Gerät zuvor hinzugefügte Geofences betritt oder verlässt:
Kotlin
geofencingClient?.removeGeofences(geofencePendingIntent)?.run { addOnSuccessListener { // Geofences removed // ... } addOnFailureListener { // Failed to remove geofences // ... } }
Java
geofencingClient.removeGeofences(getGeofencePendingIntent()) .addOnSuccessListener(this, new OnSuccessListener<Void>() { @Override public void onSuccess(Void aVoid) { // Geofences removed // ... } }) .addOnFailureListener(this, new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { // Failed to remove geofences // ... } });
Sie können Geofencing mit anderen standortbezogenen Funktionen kombinieren, z. B. mit regelmäßigen Standortupdates. Weitere Informationen finden Sie in den anderen Lektionen dieses Kurses.
Best Practices für Geofencing
In diesem Abschnitt finden Sie Empfehlungen für die Verwendung von Geofencing mit den Standort-APIs für Android.
Stromverbrauch reduzieren
Mit den folgenden Methoden können Sie den Stromverbrauch in Apps optimieren, in denen Geofencing eingesetzt wird:
Legen Sie für die Reaktionsfähigkeit von Benachrichtigungen einen höheren Wert fest. Dies verbessert den Stromverbrauch, indem die Latenz von Geofence-Benachrichtigungen erhöht wird. Wenn Sie beispielsweise einen Wert für die Reaktionsfähigkeit von fünf Minuten festlegen, prüft Ihre App nur alle fünf Minuten eine Ein- oder Ausstiegsmeldung. Niedrigere Werte bedeuten nicht unbedingt, dass die Nutzer innerhalb dieses Zeitraums benachrichtigt werden. Wenn Sie beispielsweise einen Wert von 5 Sekunden festlegen, kann es etwas länger dauern, bis die Benachrichtigung eingeht.
Verwenden Sie einen größeren Geofence-Radius für Orte, an denen ein Nutzer viel Zeit verbringt, z. B. zu Hause oder am Arbeitsplatz. Ein größerer Radius reduziert zwar den Stromverbrauch nicht direkt, reduziert jedoch die Häufigkeit, mit der die Anwendung den Ein- oder Ausgang prüft, wodurch der gesamte Stromverbrauch reduziert wird.
Den optimalen Radius für Ihren Geofence auswählen
Für optimale Ergebnisse sollte der Mindestradius des Geofence zwischen 100 und 150 Metern liegen. Wenn WLAN verfügbar ist, liegt die Standortgenauigkeit in der Regel zwischen 20 und 50 Metern. Wenn ein Standort in Gebäuden verfügbar ist, kann der Genauigkeitsbereich bis zu 5 Meter betragen. Sofern Sie nicht wissen, dass innerhalb des Geofence ein Standort in Gebäuden verfügbar ist, gehen Sie von einer Standortgenauigkeit von etwa 50 Metern aus.
Wenn die WLAN-Standortermittlung nicht verfügbar ist, z. B. wenn Sie in ländlichen Gegenden fahren, wird die Standortgenauigkeit verschlechtert. Der Genauigkeitsbereich kann mehrere hundert Meter bis mehrere Kilometer betragen. In solchen Fällen sollten Sie Geofences mit einem größeren Radius erstellen.
Nutzern erklären, warum Ihre App Geofencing verwendet
Da Ihre App bei Verwendung von Geofencing im Hintergrund auf die Standortermittlung zugreift, sollten Sie überlegen, welche Vorteile Ihre App für die Nutzer bietet. Erläutere klar, warum deine App diesen Zugriff benötigt, um das Verständnis und die Transparenz der Nutzer zu verbessern.
Weitere Informationen zu Best Practices in Bezug auf den Standortzugriff, einschließlich Geofencing, finden Sie auf der Seite Best Practices zum Datenschutz.
Verweildauertyp verwenden, um Spam in Benachrichtigungen zu reduzieren
Wenn Sie eine große Anzahl von Benachrichtigungen erhalten, wenn Sie kurz über einen Geofence fahren, sollten Sie den Übergangstyp
GEOFENCE_TRANSITION_DWELL
anstelle von
GEOFENCE_TRANSITION_ENTER
verwenden, um die Anzahl der Benachrichtigungen zu reduzieren. Auf diese Weise wird die Verweildauer nur dann gesendet, wenn der Nutzer für einen bestimmten Zeitraum in einem Geofence anhält. Sie können die Dauer durch Festlegen einer
Verzögerungsverzögerung auswählen.
Geofences nur bei Bedarf neu registrieren
Registrierte Geofences werden im com.google.process.location
-Prozess des Pakets com.google.android.gms
gespeichert.
Die App muss zur Verarbeitung der folgenden Ereignisse nichts tun, da das System Geofences nach diesen Ereignissen wiederherstellt:
- Die Google Play-Dienste werden aktualisiert.
- Google Play-Dienste werden vom System aufgrund von Ressourcenbeschränkungen beendet und neu gestartet.
- Die Standortermittlung stürzt ab.
Die App muss Geofences noch einmal registrieren, wenn sie nach den folgenden Ereignissen noch benötigt werden, da das System die Geofences in den folgenden Fällen nicht wiederherstellen kann:
- Das Gerät wird neu gestartet. Die App sollte auf die Aktion für den Abschluss des Bootvorgangs des Geräts warten und dann die erforderlichen Geofences noch einmal registrieren.
- Die App wird deinstalliert und neu installiert.
- Die Daten der App werden gelöscht.
- Daten der Google Play-Dienste werden gelöscht.
- Die App hat die Benachrichtigung
GEOFENCE_NOT_AVAILABLE
erhalten. Dies geschieht in der Regel, nachdem NLP (Network Location Provider, Android-Netzwerkanbieter) deaktiviert wurde.
Fehler beim Geofence-Eingangsereignis beheben
Wenn keine Geofencings ausgelöst werden, wenn das Gerät in einen Geofence eintritt (die Benachrichtigung
GEOFENCE_TRANSITION_ENTER
wird nicht ausgelöst), prüfen Sie zuerst, ob Ihre Geofences wie in dieser Anleitung beschrieben richtig registriert sind.
Hier sind einige mögliche Gründe dafür, dass Benachrichtigungen nicht wie erwartet funktionieren:
- Der genaue Standort ist innerhalb Ihres Geofence nicht verfügbar oder Ihr Geofence ist zu klein. Auf den meisten Geräten verwendet der Geofence-Dienst nur den Netzwerkstandort, um Geofence auszulösen. Der Dienst verwendet diesen Ansatz, da der Netzwerkstandort viel weniger Strom verbraucht, weniger Zeit für das Abrufen einzelner Standorte benötigt und vor allem in Innenräumen verfügbar ist.
WLAN auf dem Gerät ist deaktiviert. Bei aktiviertem WLAN kann die Standortgenauigkeit erheblich verbessert werden. Wenn WLAN deaktiviert ist, erhält Ihre App möglicherweise nie Geofence-Benachrichtigungen. Dies hängt von verschiedenen Einstellungen ab, z. B. vom Radius des Geofence, vom Gerätemodell oder von der Android-Version. Ab Android 4.3 (API-Level 18) haben wir die Möglichkeit des „Nur WLAN-Scanmodus“ hinzugefügt, mit dem Nutzer das WLAN deaktivieren und trotzdem eine gute Netzwerkverbindung erhalten können. Es empfiehlt sich, den Nutzer aufzufordern und ihm eine Tastenkombination anzubieten, mit der er den WLAN- oder den WLAN-Scanmodus aktivieren kann, wenn beide deaktiviert sind. Mit SettingsClient sorgen Sie dafür, dass die Systemeinstellungen des Geräts für eine optimale Standorterkennung richtig konfiguriert sind.
Hinweis : Wenn deine App auf Android 10 (API-Level 29) oder höher ausgerichtet ist, kannst du
WifiManager.setEnabled()
nur dann direkt aufrufen, wenn deine App eine System-App oder ein Device Policy Controller (DPC) ist. Verwenden Sie stattdessen Einstellungen.- Innerhalb Ihres Geofence gibt es keine zuverlässige Netzwerkverbindung. Wenn keine zuverlässige Datenverbindung vorhanden ist, werden möglicherweise keine Benachrichtigungen generiert. Dies liegt daran, dass der Geofence-Dienst vom Netzwerkstandortanbieter abhängt, der wiederum eine Datenverbindung benötigt.
- Benachrichtigungen können auch zu spät eingehen. Der Geofence-Dienst fragt nicht kontinuierlich den Standort ab. Daher sollten Sie beim Empfang von Benachrichtigungen mit einer gewissen Latenz rechnen. Normalerweise beträgt die Latenz weniger als 2 Minuten, sogar weniger, wenn das Gerät in Bewegung ist. Wenn Limits für die Standortermittlung im Hintergrund gelten, beträgt die Latenz im Durchschnitt 2 bis 3 Minuten. Wenn das Gerät längere Zeit nicht bewegt wurde, kann sich die Latenz erhöhen (bis zu 6 Minuten).
Weitere Informationen
Weitere Informationen zum Geofencing finden Sie in den folgenden Materialien:
Produktproben
Beispiel-App zum Erstellen und Überwachen von Geofences