So arbeiten Sie mit Geofences auf Android

Ortsbezogene Ressourcen ermöglichen es Ihrer Anwendung, mit der physischen Welt zu interagieren, und sie sind ideal für eine stärkere Einbindung der Benutzer. Obwohl viele mobile Apps sie verwenden, ist das Thema dieses Lernprogramms eine oft übersehene Funktion, Geofencing.

Ein Geofence ist ein virtueller Umkreis, der in einem realen geografischen Gebiet liegt. Durch die Kombination einer Benutzerposition mit einem Geofence-Perimeter kann ermittelt werden, ob sich der Benutzer innerhalb oder außerhalb des Geofence befindet oder sogar, ob er den Bereich verlässt oder betritt.

Stellen Sie sich eine Uni-App vor, die Ihnen sagen kann, welche Kollegen und Professoren sich derzeit auf dem Campus befinden. Oder eine App für ein Einkaufszentrum, die Stammkunden belohnt. Es gibt viele andere interessante Möglichkeiten, die Sie erkunden können.

In diesem Lernprogramm erfahren Sie, wie Sie Geofences unter Android verwenden, indem Sie eine Anwendung erstellen, die dem Benutzer eine Benachrichtigung anzeigt, wenn er ein Geofence betritt oder beendet. Dies ist hilfreich, wenn Sie bereits über Google Play-Dienste, die Google Maps-Android-API oder IntentService. Wenn Sie dies nicht tun, können Sie immer noch mitverfolgen, aber nach dem Lesen dieses Lernprogramms möchten Sie vielleicht etwas zu diesen Themen suchen.

1. Geofences auf Android

Unter Android gibt es mehrere Möglichkeiten, mit Geofences zu arbeiten. Sie können sogar eine eigene Implementierung erstellen, um mit Geofences zu arbeiten. Die Verwendung von Google ist jedoch einfacher GeofencingApi.

Diese APIs sind Teil von Google Ort APIs. Es enthält Geofence, GeofencingRequest, GeofenceApiGeofencingEvent, und GeofenceStatusCodes. In diesem Lernprogramm verwenden wir diese Klassen, um Geofences zu erstellen und mit ihnen zu arbeiten.

Geofence-Schnittstelle

Geofence ist eine Schnittstelle, die einen geografischen Bereich darstellt, der überwacht werden sollte. Es wird mit dem erstellt Geofence.Builder. Während der Erstellung legen Sie den überwachten Bereich, das Ablaufdatum, die Reaktionszeit, einen Bezeichner und die Art der Übergänge fest, nach denen Geofence gesucht werden soll.

Um den Stromverbrauch auf ein Minimum zu beschränken, wird empfohlen, in den meisten Situationen einen Geofence mit einem Radius von mindestens 100 Metern zu verwenden. Wenn sich Geofences auf dem Land befinden, sollten Sie den Radius auf 500 Meter oder mehr erhöhen, um sicherzustellen, dass die Geofences wirksam sind.

Geofence geofence = new Geofence.Builder () .setRequestId (GEOFENCE_REQ_ID) // Geofence-ID .setCircularRegion (LATITUDE, LONGITUDE, RADIUS) // Definiert den Zaunbereich .setExpirationDuration (DURANTION) // Ablaufdatum .setTransitionTypes (Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT) .build ();

Geofence-Übergänge

  • GEOFENCE_TRANSITION_DWELL zeigt an, dass der Benutzer den Bereich betreten hat und einige Zeit dort verbracht hat. Es ist nützlich, mehrere Warnmeldungen zu vermeiden, wenn der Benutzer den Bereich zu schnell betritt und verlässt. Sie können die Verweildauer mit dem konfigurieren setLoiteringDelay Parameter.
  • GEOFENCE_TRANSITION_ENTER gibt an, wann der Benutzer den überwachten Bereich betritt.
  • GEOFENCE_TRANSITION_EXIT  gibt an, wann der Benutzer die Region verlässt.

GeofenceRequest

Das GeofencingRequest Klasse empfängt die Geofences, die überwacht werden sollen. Sie können eine Instanz erstellen, indem Sie eine Baumeister, vorbei ein Geofence oder ein Liste, und die Art der Benachrichtigung, die ausgelöst werden soll, wenn die Geofence (s) erstellt werden.

GeofencingRequest request = new GeofencingRequest.Builder () // Benachrichtigung beim Auslösen des Geofence .setInitialTrigger (GeofencingRequest.INITIAL_TRIGGER_ENTER) .addGeofence (Geofence) // füge Geofence .build () hinzu;

GeofencingApi

Das GeofencingApi class ist der Einstiegspunkt für alle Interaktionen mit der Geofencing-API von Google. Es ist Teil der Ort APIs und es hängt von einem GoogleApiClient arbeiten. Sie werden das verwenden GeofencingApi Geofences hinzufügen und entfernen.

Um einen Geofence hinzuzufügen, rufen Sie die addGeofence () Methode. Er überwacht den angegebenen Bereich mit den an den übergebenen Einstellungen GeofencingRequest und schießt ein PendingIntent wenn ein Geofence-Übergang stattfindet, der den Bereich betritt oder verlässt.

PendingResult addGeofences (GoogleApiClient-Client, GeofencingRequest GeofencingRequest, PendingIntent pendingIntent)

Um den Geofence zu entfernen, rufen Sie an removeGeofences (). Sie können den Geofence entweder mit seiner Anforderungs-ID oder seiner ausstehenden Absicht entfernen.

PendingResult removeGeofences (GoogleApiClient-Client, Liste geofenceRequestIds)
 PendingResult removeGeofences (GoogleApiClient-Client, PendingIntent pendingIntent)

2. Erstellen einer Geofencing-App

In diesem Lernprogramm erstellen wir eine einfache Anwendung, die den Benutzerstandort überwacht und eine Benachrichtigung bereitstellt, wenn der Benutzer einen geofenced Bereich betritt oder diesen verlässt. Die App besteht nur aus einem Aktivität und ein IntentService. Wir werfen auch einen kurzen Blick darauf Google Karte, GoogleApiClient, und FusedLocationProviderApi, und wir untersuchen einige Vorbehalte der Geofence-API.

Schritt 1: Projekt einrichten

GeofencingApi ist Teil der Google Play Services. Um darauf zuzugreifen, müssen Sie Ihre Entwicklungsumgebung richtig einrichten und eine Instanz von erstellen GoogleApiClient. Erstellen Sie ein neues Projekt mit einem Leerzeichen Aktivität, Bearbeiten Sie das Projekt build.gradle Datei wie unten gezeigt, und synchronisieren Sie Ihr Projekt.

Schritt 2: Berechtigungen

Wir müssen die richtigen Berechtigungen zum Erstellen und Verwenden von Geofences festlegen. Fügen Sie dem Manifest des Projekts die folgende Berechtigung hinzu:

Ab Android 6.0 fragt die App zur Laufzeit und nicht während der Installation nach Erlaubnis. Wir sprechen dies später im Tutorial an.

Schritt 3: Layout erstellen

Das Projekt besteht aus einem Layout, dem MainActity Layout. Es enthält den aktuellen Breiten- und Längengrad des Geräts und a Google Karte Fragment, das die Geofences und die Position des Benutzers anzeigt.

Schon seit activity_main.xml ist ziemlich unkompliziert, ich möchte mich nur auf das konzentrieren MapFragment Element. In den Quelldateien dieses Tutorials können Sie das vollständige Layout betrachten.

 

Schritt 4: Google Maps-API-Schlüssel

Da verwenden wir eine MapFragment, Wir müssen a einrichten und initialisieren Google Karte Beispiel. Zunächst benötigen Sie einen API-Schlüssel. Wenn Sie einen API-Schlüssel haben, fügen Sie ihn dem Manifest des Projekts hinzu.

Beginnen wir mit dem Google Karte Beispiel. Implementieren GoogleMap.OnMapReadyCallbackGoogleMap.OnMapClickListener, und GoogleMap.OnMarkerClickListener in dem Aktivität klassifizieren und die Karte initialisieren.

public class MainActivity erweitert AppCompatActivity implementiert OnMapReadyCallback, GoogleMap.OnMapClickListener, GoogleMap.OnMarkerClickListener privates statisches Zeichenfolge TAG = MainActivity.class.getSimpleName (); private TextView textLat, textLong; private MapFragment-MapFragment; private GoogleMap-Karte; @Override protected void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.activity_main); textLat = (TextView) findViewById (R.id.lat); textLong = (TextView) findViewById (R.id.lon); // GoogleMaps initialisieren initGMaps ();  // Privates void von GoogleMaps initialisieren initGMaps () mapFragment = (MapFragment) getFragmentManager (). FindFragmentById (R.id.map); mapFragment.getMapAsync (this);  // Rückruf aufgerufen, wenn Map bereit ist @Override public void onMapReady (GoogleMap googleMap) Log.d (TAG, "onMapReady ()"); map = googleMap; map.setOnMapClickListener (this); map.setOnMarkerClickListener (this);  // Callback aufgerufen, wenn Map berührt wird @Override public void onMapClick (LatLng latLng) Log.d (TAG, "onMapClick (" + latLng + ")");  // Callback aufgerufen, wenn Marker berührt wird @Override public boolean onMarkerClick (Markierungsmarkierung) Log.d (TAG, "onMarkerClickListener:" + marker.getPosition ()); falsch zurückgeben; 

Schritt 5: GoogleApiClient

Um die GeofencingApi Schnittstelle brauchen wir eine GoogleApiClient Einstiegspunkt. Lassen Sie uns ein implementieren GoogleApiClient.ConnectionCallbacks und ein GoogleApiClient.OnConnectionFailedListener in dem Aktivität Wie nachfolgend dargestellt.

Öffentliche Klasse MainActivity erweitert AppCompatActivity implementiert GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, OnMapReadyCallback, GoogleMap.OnMapClickListener, GoogleMap.OnMarkerClickListener //… private GoogleApiClachTool. @Override protected void onCreate (Bundle savedInstanceState) //… // GoogleApiClient erstellen createGoogleApi ();  // Erstellen Sie den privaten void der GoogleApiClient-Instanz. CreateGoogleApi () Log.d (TAG, "createGoogleApi ()"); if (googleApiClient == null) googleApiClient = new GoogleApiClient.Builder (this) .addConnectionCallbacks (this) .addOnConnectionFailedListener (this) .addApi (LocationServices.API) .build ();  @Override protected void onStart () super.onStart (); // Beim Start der Aktivität GoogleApiClient-Verbindung aufrufen googleApiClient.connect ();  @Override protected void onStop () super.onStop (); // GoogleApiClient beim Stoppen der Aktivität trennen googleApiClient.disconnect ();  // GoogleApiClient.ConnectionCallbacks verbunden @Override public void onConnected (@Nullable Bundle-Paket) Log.i (TAG, "onConnected ()");  // GoogleApiClient.ConnectionCallbacks ausgesetzt @Override public void onConnectionSuspended (int i) Log.w (TAG, "onConnectionSuspended ()");  // GoogleApiClient.OnConnectionFailedListener fail @Override public void onConnectionFailed (@NonNull ConnectionResult connectionResult) Log.w (TAG, "onConnectionFailed ()");  

Schritt 6: FusedLocationProviderApi

Wir müssen auch auf den aktuellen Standort des Benutzers zugreifen. Das FusedLocationProviderApi Die Schnittstelle gibt uns diese Informationen und ermöglicht eine große Kontrolle der Standortanfrage. Dies ist sehr wichtig, da die Standortanforderungen einen direkten Einfluss auf den Batterieverbrauch des Geräts haben.

Lassen Sie uns nun ein implementieren LocationListener. Prüfen Sie, ob der Benutzer der Anwendung die entsprechenden Berechtigungen erteilt hat, indem Sie das erstellen Ort Fordern Sie den aktuellen Standort an und zeigen Sie ihn an.

public class MainActivity erweitert AppCompatActivity-Implementierungen //… LocationListener private Location lastLocation; //… // GoogleApiClient.ConnectionCallbacks connected @Override public void onConnected (@Nullable Bundle-Paket) Log.i (TAG, "onConnected ()"); getLastKnownLocation ();  // Liefert den letzten bekannten Speicherort privat void getLastKnownLocation () Log.d (TAG, "getLastKnownLocation ()"); if (checkPermission ()) lastLocation = LocationServices.FusedLocationApi.getLastLocation (googleApiClient); if (lastLocation! = null) Log.i (TAG, "LasKnown location") + "Long:" + lastLocation.getLongitude () + "| Lat:" + lastLocation.getLatitude ()); writeLastLocation (); startLocationUpdates ();  else Log.w (TAG, "Noch kein Standort abgerufen"); startLocationUpdates ();  else askPermission ();  private LocationRequest LocationRequest; // Definiert in Millisekunden. // Diese Zahl ist extrem niedrig und sollte nur für das private Debugging verwendet werden int int UPDATE_INTERVAL = 1000; private final int FASTEST_INTERVAL = 900; // Startort aktualisiert private void startLocationUpdates () Log.i (TAG, "startLocationUpdates ()"); locationRequest = LocationRequest.create () .setPriority (LocationRequest.PRIORITY_HIGH_ACCURACY) .setInterval (UPDATE_INTERVAL) .setFastestInterval (FASTEST_INTERVAL); if (checkPermission ()) LocationServices.FusedLocationApi.requestLocationUpdates (googleApiClient, locationRequest, this);  @Override public void onLocationChanged (Speicherort) Log.d (TAG, "onLocationChanged [" + location + "]"); lastLocation = Standort; writeActualLocation (location);  // Schreibe Ortskoordinaten in die private void writeActualLocation (Location location) textLat.setText ("Lat:" + location.getLatitude ()); textLong.setText ("Long:" + location.getLongitude ());  private void writeLastLocation () writeActualLocation (lastLocation);  // Auf Zugriffsberechtigung prüfen Location private boolean checkPermission () Log.d (TAG, "checkPermission ()"); // Bitte um Erlaubnis, falls sie noch nicht erteilt wurde return (ContextCompat.checkSelfPermission (this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED);  // fragt nach der Erlaubnis private void askPermission () Log.d (TAG, "askPermission ()"); ActivityCompat.requestPermissions (dieser neue String [] Manifest.permission.ACCESS_FINE_LOCATION, REQ_PERMISSION);  // Benutzerantwort der angeforderten Berechtigung überprüfen @Override public void onRequestPermissionsResult (int requestCode, @NonNull String [] -Berechtigungen, @NonNull int [] grantResults) Log.d (TAG, "onRequestPermissionsResult ()"); super.onRequestPermissionsResult (requestCode, Berechtigungen, GrantResults); switch (requestCode) case REQ_PERMISSION: if (grantResults.length> 0 && grantResults [0] == PackageManager.PERMISSION_GRANTED) // Berechtigung erteilt getLastKnownLocation ();  else // Berechtigung verweigert permissionsDenied ();  brechen;  // Die App kann nicht ohne die Berechtigungen private void funktionieren permissionsDenied () Log.w (TAG, "permissionsDenied ()"); 

Es ist wichtig, dass das angesprochen wird LocationRequest Oben erstellt wurde nicht für eine Produktionsumgebung optimiert. Das UPDATEINTERVALL ist zu kurz und würde zu viel Batteriestrom verbrauchen. Eine realistischere Konfiguration für die Produktion könnte sein:

private final int UPDATE_INTERVAL = 3 * 60 * 1000; // 3 Minuten privates Finale int FASTEST_INTERVAL = 30 * 1000; // 30 Sek. Privat void startLocationUpdates () Log.i (TAG, "startLocationUpdates ()"); locationRequest = LocationRequest.create () .setPriority (LocationRequest.PRIORITY_HIGH_ACCURACY) .setInterval (UPDATE_INTERVAL) .setFastestInterval (FASTEST_INTERVAL); if (checkPermission ()) LocationServices.FusedLocationApi.requestLocationUpdates (googleApiClient, locationRequest, this); 

Schritt 7: GoogleMap-Markierungen

Unsere Aktivität benötigt zwei verschiedene Marker. EIN locationMarker verwendet den Breitengrad und den Längengrad, die vom angegeben werden FusedLocationProviderApi um den aktuellen Standort des Geräts zu informieren. EIN GeoFenceMarker ist das Ziel für die Geofence-Erstellung, da bei der letzten Berührung der Karte die Position abgerufen wird.

@Override public void onMapClick (LatLng latLng) Log.d (TAG, "onMapClick (" + latLng + ")"); markerForGeofence (latLng);  private void writeActualLocation (location location) //… markerLocation (new LatLng (location.getLatitude (), location.getLongitude ()));  private Marker locationMarker; // Erzeuge einen privaten Marker für eine Positionsmarkierung markerLocation (LatLng latLng) Log.i (TAG, "markerLocation (" + latLng + ")"); String title = latLng.latitude + "," + latLng.longitude; MarkerOptions markerOptions = new MarkerOptions () .position (latLng) .title (title); if (map! = null) // Entferne die vordere Markierung if (locationMarker! = null) locationMarker.remove (); locationMarker = map.addMarker (markerOptions); Float Zoom = 14f; CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom (latLng, Zoom); map.animateCamera (cameraUpdate);  private Marker geoFenceMarker; // Erzeuge eine Markierung für den privaten void der Geofence-Erstellung markerForGeofence (LatLng latLng) Log.i (TAG, "markerForGeofence (" + latLng + ")"); String title = latLng.latitude + "," + latLng.longitude; // Markeroptionen definieren MarkerOptions markerOptions = new MarkerOptions () .position (latLng) .icon (BitmapDescriptorFactory.defaultMarker (BitmapDescriptorFactory.HUE_ORANGE)) .title (title); if (map! = null) // Entferne den letzten geoFenceMarker. if (geoFenceMarker! = null) geoFenceMarker.remove (); geoFenceMarker = map.addMarker (markerOptions); 

Schritt 8: Geofence erstellen

Endlich ist es Zeit, einen Geofence zu schaffen. Wir nehmen das GeoFenceMarker als Mittelpunkt für den Geofence.

private statische Schlusslänge GEO_DURATION = 60 * 60 * 1000; private static final String GEOFENCE_REQ_ID = "Mein Geofence"; privater statischer endgültiger Float GEOFENCE_RADIUS = 500.0f; // in Metern // Geofence private Geofence erstellen createGeofence (LatLng latLng, Float-Radius) Log.d (TAG, "createGeofence"); Rückgabewert für Geofake.Builder () .setRequestId (GEOFENCE_REQ_ID) .achCircularRegion (latLng.latitude, latLng.longitude, radius). 

Als nächstes erstellen wir die GeofencingRequest Objekt.

// Geofence-Anfrage erstellen private GeofencingRequest createGeofenceRequest (Geofence Geofence) Log.d (TAG, "createGeofenceRequest"); return new GeofencingRequest.Builder () .setInitialTrigger (GeofencingRequest.INITIAL_TRIGGER_ENTER) .addGeofence (Geofence) .build (); 

Wir benutzen ein PendingIntent Objekt zum Aufruf von a IntentService das wird das erledigen GeofenceEvent. Wir schaffen das GeofenceTrasitionService.class später.

privat ausstehendIntent geoFencePendingIntent; private final int GEOFENCE_REQ_CODE = 0; private PendingIntent createGeofencePendingIntent () Log.d (TAG, "createGeofencePendingIntent"); if (geoFencePendingIntent! = null) Rückgabe geoFencePendingIntent; Intent Intent = New Intent (dies GeofenceTrasitionService.class); return PendingIntent.getService (dieser GEOFENCE_REQ_CODE, Intent, PendingIntent.FLAG_UPDATE_CURRENT);  // Fügen Sie das erstellte GeofenceRequest der Überwachungsliste des Geräts hinzu. Private void addGeofence (GeofencingRequest-Anforderung) Log.d (TAG, "addGeofence"); if (checkPermission ()) LocationServices.GeofencingApi.addGeofences (googleApiClient, request, createGeofencePendingIntent ()) .setResultCallback (this); 

Wir zeichnen auch den Geofence auf der Karte als visuelle Referenz.

@Override public void onResult (@NonNull-Statusstatus) Log.i (TAG, "onResult:" + -Status); if (status.isSuccess ()) drawGeofence ();  else // informiere über fail // Geofence-Kreis in GoogleMap zeichnen private Circle geoFenceLimits; private void drawGeofence () Log.d (TAG, "drawGeofence ()"); if (geoFenceLimits! = null) geoFenceLimits.remove (); CircleOptions circleOptions = new CircleOptions () .center (geoFenceMarker.getPosition ()) .strokeColor (Color.argb (50, 70,70,70)) .fillColor (Color.argb (100, 150, 150, 150)) .radius (GEOFENCE_RADIUS); geoFenceLimits = map.addCircle (circleOptions); 

Das startGeofence () Die Methode ist dafür verantwortlich, dass der Geofencing-Prozess im gestartet wird Hauptaktivität Klasse.

 @Override public boolean onOptionsItemSelected (MenuItem-Element) switch (item.getItemId ()) case R.id.geofence: startGeofence (); wahr zurückgeben;  return super.onOptionsItemSelected (item);  // Geofence-Erstellungsprozess starten private void startGeofence () Log.i (TAG, "startGeofence ()"); if (geoFenceMarker! = null) Geofence geofence = createGeofence (geoFenceMarker.getPosition (), GEOFENCE_RADIUS); GeofencingRequest geofenceRequest = createGeofenceRequest (Geofence); addGeofence (geofenceRequest);  else Log.e (TAG, "Geofence-Marker ist Null"); 

Schritt 9: Geofence Transition Service

Wir können jetzt endlich das erstellen GeofenceTrasitionService.class zuvor erwähnt. Diese Klasse erweitert sich IntentService und ist verantwortlich für den Umgang mit dem GeofencingEvent. Zuerst erhalten wir dieses Ereignis von der erhaltenen Absicht.

GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent (intent);

Wir prüfen dann, ob die Art des Geofencing-Übergangs für uns von Interesse ist. Ist dies der Fall, rufen wir eine Liste der ausgelösten Geofences ab und erstellen eine Benachrichtigung mit den entsprechenden Aktionen.

// GeofenceTrasition abrufen int geoFenceTransition = geofencingEvent.getGeofenceTransition (); // Prüfen Sie, ob der Übergangstyp if (geoFenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER || geoFenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) // Ruft die ausgelöste Geofence-Liste ab triggeringGeofences = geofencingEvent.getTriggeringGeofences (); // Eine detaillierte Nachricht mit erhaltenem Geofences erstellen String geofenceTransitionDetails = getGeofenceTrasitionDetails (geoFenceTransition, triggeringGeofences); // Benachrichtigungsdetails als String senden sendNotification (geofenceTransitionDetails); 

Ich habe auch einige Hilfsmethoden implementiert, um die Implementierung der Klasse verständlicher zu machen.

public class GeofenceTrasitionService erweitert IntentService privates statisches Zeichenfolge TAG = GeofenceTrasitionService.class.getSimpleName (); public static final int GEOFENCE_NOTIFICATION_ID = 0; public GeofenceTrasitionService () super (TAG);  @Override protected void onHandleIntent (Absichtsabsicht) // Geofencing-Absicht abrufen GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent (intent); // Fehlerbehandlung if (geofencingEvent.hasError ()) String errorMsg = getErrorString (geofencingEvent.getErrorCode ()); Log.e (TAG, errorMsg); Rückkehr;  // GeofenceTrasition abrufen int geoFenceTransition = geofencingEvent.getGeofenceTransition (); // Prüfen Sie, ob der Übergangstyp if (geoFenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER || geoFenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) // Ruft die ausgelöste Geofence-Liste ab triggeringGeofences = geofencingEvent.getTriggeringGeofences (); // Eine detaillierte Nachricht mit erhaltenem Geofences erstellen String geofenceTransitionDetails = getGeofenceTrasitionDetails (geoFenceTransition, triggeringGeofences); // Benachrichtigungsdetails als String senden sendNotification (geofenceTransitionDetails);  // Erstellen Sie eine Detailnachricht mit dem von Geofences erhaltenen privaten String getGeofenceTrasitionDetails (int geoFenceTransition, List triggeringGeofences) // Holen Sie sich die ID jeder durch Geofence ausgelösten ArrayList triggeringGeofencesList = neue ArrayList <> (); for (Geofence geofence: triggeringGeofences) triggeringGeofencesList.add (geofence.getRequestId ());  Zeichenfolgenstatus = null; if (geoFenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER) status = "Eingabe"; else if (geoFenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) status = "Beenden"; return status + TextUtils.join (",", triggeringGeofencesList);  // Senden Sie eine Benachrichtigung privat void sendNotification (String msg) Log.i (TAG, "sendNotification:" + msg); // beabsichtigt, den Hauptaktivitätszweck zu starten notificationIntent = MainActivity.makeNotificationIntent (getApplicationContext (), msg); TaskStackBuilder stackBuilder = TaskStackBuilder.create (this); stackBuilder.addParentStack (MainActivity.class); stackBuilder.addNextIntent (notificationIntent); PendingIntent notificationPendingIntent = stackBuilder.getPendingIntent (0, PendingIntent.FLAG_UPDATE_CURRENT); // Benachrichtigung erstellen und senden NotificationManager notificatioMng = (NotificationManager) getSystemService (Context.NOTIFICATION_SERVICE); notificatioMng.notify (GEOFENCE_NOTIFICATION_ID, createNotification (msg, notificationPendingIntent));  // Eine private Benachrichtigung erstellen Notification createNotification (String msg, PendingIntent notificationPendingIntent) NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder (this); notificationBuilder .setSmallIcon (R.drawable.ic_action_location) .setColor (Color.RED) .setContentTitle (msg) .setContentText ("Geofence Notification!") .setContentIntent (notificationPendingIntent) ) .setAutoCancel (true); return notificationBuilder.build ();  // Fehler behandeln private statische Zeichenfolge getErrorString (int errorCode) switch (errorCode) case GeofenceStatusCodes.GEOFENCE_NOT_AVAILABLE: return "GeoFence nicht verfügbar"; case GeofenceStatusCodes.GEOFENCE_TOO_MANY_GEOFENCES: return "Zu viele GeoFences"; case GeofenceStatusCodes.GEOFENCE_TOO_MANY_PENDING_INTENTS: return "Zu viele ausstehende Absichten"; Standard: Rückgabe "Unbekannter Fehler."; 

3. Testen

Testen auf einem virtuellen Gerät

Es ist viel einfacher, Geofencing auf einem virtuellen Gerät zu testen. Dafür gibt es mehrere Möglichkeiten. Öffnen Sie in Android Studio ein virtuelles Gerät und klicken Sie unten rechts auf die Schaltfläche Weitere Optionen.

In dem Ort Auf der linken Seite geben Sie die Koordinaten für den Standort ein.

Ich bevorzuge es zu benutzen Telnet Befehle zur Steuerung des virtuellen Geräts. Um dies zu verwenden, müssen Sie von der Befehlszeile aus mit dem folgenden Befehl eine Verbindung zum Gerät herstellen:

telnet localhost [DEVICE_PORT]

Der Geräteport wird im virtuellen Gerätefenster angezeigt. Der Geräteport ist normalerweise gleich 5554.

Es ist möglich, dass Sie diese Verbindung mit Ihrem autorisieren müssen auth_token, aber die Befehlszeile zeigt Ihnen, wo es sich befindet. Navigieren Sie zu diesem Speicherort und kopieren Sie das Token und den Typ, auth [YOUR_AUTH_TOKEN].

Sie können jetzt den Standort des Geräts festlegen, indem Sie den folgenden Befehl ausführen:

geo fix [LATITUDE] [LONGITUDE]

Fazit

Geofencing kann eine großartige Ergänzung zu Ihrer App sein, da dies die Benutzerbindung erheblich erhöhen kann. Es gibt viele Möglichkeiten zum Erkunden, und Sie können mit Indoor-Beacons wie beispielsweise Estimote sogar ein anspruchsvolles Erlebnis erstellen. Mit Indoor-Beacons wissen Sie genau, wo der Benutzer beispielsweise ein Einkaufszentrum betreten hat.

Das Hinzufügen von Geofencing zu einem Projekt ist einfach, aber wir müssen den Energieverbrauch jederzeit im Auge behalten. Dies bedeutet, dass wir die Größe des Geofence und die Aktualisierungsrate sorgfältig auswählen müssen, da sich beide direkt auf den Stromverbrauch Ihrer Anwendung auswirken.

Das Testen ist daher sehr wichtig, um eine realistische Vorstellung vom Energieverbrauch Ihrer Anwendung zu erhalten. Erwägen Sie auch die Möglichkeit, Benutzern die Option zum vollständigen Deaktivieren von Geofencing zu geben, wenn sie diese Funktion nicht wünschen oder benötigen.