Hoe te werken met geofences op Android

Locatiebewuste bronnen stellen uw toepassing in staat om te communiceren met de fysieke wereld en ze zijn ideaal om de betrokkenheid van gebruikers te vergroten. Hoewel veel mobiele apps deze gebruiken, is het onderwerp van deze zelfstudie een functie die vaak over het hoofd wordt gezien, geofencing.

Een geofence is een virtuele perimeterreeks op een echt geografisch gebied. Door een gebruikerspositie te combineren met een geofence-perimeter, is het mogelijk om te weten of de gebruiker zich binnen of buiten de geofence bevindt of zelfs als hij het gebied verlaat of binnengaat.

Stel je een universitaire app voor die je kan vertellen welke collega's en professoren momenteel op de campus zitten. Of een app voor een winkelcentrum dat vaste klanten beloont. Er zijn veel andere interessante mogelijkheden die je kunt verkennen.

In deze zelfstudie leert u hoe u geofences op Android kunt gebruiken door een toepassing te maken die de gebruiker een melding geeft wanneer deze een geofence invoert of verlaat. Het helpt als u eerdere kennis hebt van Google Play-services, de Google Maps Android API of IntentService. Als u dat niet doet, kunt u nog steeds meegaan, maar wilt u misschien wat onderzoek doen naar deze onderwerpen na het lezen van deze tutorial.

1. Geofences op Android

Op Android zijn er verschillende manieren om met geofences te werken. U kunt zelfs uw eigen implementatie maken om met geofences te werken, maar het is gemakkelijker om Google's te gebruiken GeofencingApi.

Deze API's maken deel uit van Google's Plaats API's. Het bevat geofence, GeofencingRequest, GeofenceApiGeofencingEvent, en GeofenceStatusCodes. In deze zelfstudie gebruiken we deze klassen om geofences te maken en ermee te werken.

Geofence-interface

geofence is een interface die een geografisch gebied vertegenwoordigt dat moet worden gecontroleerd. Het is gemaakt met behulp van de Geofence.Builder. Tijdens het maken van deze instelling stelt u de bewaakte regio in, de vervaldatum van de geofence, het reactievermogen, een ID en de soort overgangen waarnaar deze moet zoeken.

Om het stroomverbruik tot een minimum te beperken, wordt het aanbevolen om voor de meeste situaties een geofence met een straal van minimaal 100 meter te gebruiken. Als geofences zich op het platteland bevinden, moet u de straal tot 500 meter of hoger vergroten om te zorgen dat de geofences effectief zijn.

Geofence geofence = nieuwe Geofence.Builder () .setRequestId (GEOFENCE_REQ_ID) // Geofence ID .setCircularRegion (LATITUDE, LONGITUDE, RADIUS) // definiërend omheiningsgebied .setExpirationDuration (DURANTION) // vervaldatum // Overgangstypes waarnaar het moet zoeken .setTransitionTypes (Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT) .build ();

Geofence-overgangen

  • GEOFENCE_TRANSITION_DWELL geeft aan dat de gebruiker het gebied is binnengegaan en daar enige tijd heeft doorgebracht. Het is handig om meerdere waarschuwingen te vermijden wanneer de gebruiker het gebied te snel invoert en verlaat. U kunt de verblijftijd configureren met behulp van de setLoiteringDelay parameter.
  • GEOFENCE_TRANSITION_ENTER geeft aan wanneer de gebruiker het bewaakte gebied binnengaat.
  • GEOFENCE_TRANSITION_EXIT  geeft aan wanneer de gebruiker de regio verlaat.

GeofenceRequest

De GeofencingRequest klasse ontvangt de geofences die moeten worden gecontroleerd. U kunt een exemplaar maken met behulp van a Bouwer, passeren van een geofence of a Lijst, en het soort melding dat moet worden geactiveerd wanneer de geofence (s) wordt gemaakt.

GeofencingRequest request = new GeofencingRequest.Builder () // Melding die moet worden geactiveerd wanneer de Geofence wordt gemaakt .setInitialTrigger (GeofencingRequest.INITIAL_TRIGGER_ENTER) .addGeofence (geofence) // voeg een Geofence. Build () toe;

GeofencingApi

De GeofencingApi class is het toegangspunt voor alle interacties met de geofencing-API van Google. Het maakt deel uit van de Plaats API's en dit is afhankelijk van een GoogleApiClient werken. Je gebruikt de GeofencingApi om geofences toe te voegen en te verwijderen.

Om een ​​geofence toe te voegen, roept u de addGeofence () methode. Het controleert het gegeven gebied met behulp van de instellingen die zijn doorgegeven aan de GeofencingRequest en schiet a PendingIntent wanneer een geofenstransitie plaatsvindt die het gebied binnengaat of verlaat.

PendingResult addGeofences (GoogleApiClient client, GeofencingRequest geofencingRequest, PendingIntent pendingIntent)

Om de geofence te verwijderen, belt u removeGeofences (). U kunt de geofence verwijderen met behulp van de identificatiecode van het verzoek of de intentie ervan.

PendingResult removeGeofences (GoogleApiClient-client, Lijst geofenceRequestIds)
 PendingResult removeGeofences (GoogleApiClient client, PendingIntent pendingIntent)

2. Een Geofencing-app maken

In deze zelfstudie maken we een eenvoudige toepassing die de gebruikerslocatie bewaakt en een melding plaatst wanneer de gebruiker een geofenced gebied binnengaat of verlaat. De app bestaat uit slechts één Activiteit en een IntentService. We nemen ook snel een kijkje GoogleMap, GoogleApiClient, en FusedLocationProviderApi, en we verkennen een aantal kanttekeningen bij de geofence API.

Stap 1: Projectinstellingen

GeofencingApi maakt deel uit van Google Play-services. Om toegang te krijgen, moet u uw ontwikkelomgeving correct instellen en een exemplaar van de GoogleApiClient. Maak een nieuw project met een blanco Activiteit, bewerk de projecten build.gradle bestand zoals hieronder weergegeven en synchroniseer uw project.

Stap 2: Rechten

We moeten de juiste machtigingen instellen voor het maken en gebruiken van geofences. Voeg de volgende rechten toe aan het manifest van het project:

Vanaf Android 6.0 vraagt ​​de app om toestemming tijdens runtime en niet tijdens de installatie. We pakken dit later in de tutorial aan.

Stap 3: De lay-out maken

Het project bestaat uit één lay-out, de MainActity lay-out. Het bevat de huidige lengte- en breedtegraad van het apparaat en een GoogleMap fragment dat de geofences en de positie van de gebruiker weergeeft.

Sinds activity_main.xml is vrij eenvoudig, ik wil me alleen concentreren op de MapFragment element. U kunt de voltooide lay-out in de bronbestanden van deze zelfstudie bekijken.

 

Stap 4: Google Maps API Key

Omdat we een gebruiken MapFragment, we moeten a instellen en initialiseren GoogleMap aanleg. Eerst moet u een API-sleutel verkrijgen. Zodra u een API-sleutel hebt, voegt u deze toe aan het manifest van het project.

Laten we beginnen met de GoogleMap aanleg. uitvoeren GoogleMap.OnMapReadyCallbackGoogleMap.OnMapClickListener, en GoogleMap.OnMarkerClickListener in de Activiteit class en initialiseer de kaart.

public class MainActivity breidt AppCompatActivity implementeert OnMapReadyCallback, GoogleMap.OnMapClickListener, GoogleMap.OnMarkerClickListener private static final String TAG = MainActivity.class.getSimpleName (); privé TextView textLat, textLong; privé MapFragment mapFragment; privé GoogleMap-kaart; @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); // initialize GoogleMaps initGMaps ();  // Initialiseer GoogleMaps private void initGMaps () mapFragment = (MapFragment) getFragmentManager (). FindFragmentById (R.id.map); mapFragment.getMapAsync (deze);  // Callback wordt aangeroepen wanneer Map gereed is @Override public void onMapReady (GoogleMap googleMap) Log.d (TAG, "onMapReady ()"); map = googleMap; map.setOnMapClickListener (deze); map.setOnMarkerClickListener (deze);  // Terugbellen genoemd wanneer kaart wordt aangeraakt @Override public void onMapClick (LatLng latLng) Log.d (TAG, "onMapClick (" + latLng + ")");  // Terugbellen genoemd wanneer Markering wordt aangeraakt @Override public boolean onMarkerClick (Marker marker) Log.d (TAG, "onMarkerClickListener:" + marker.getPosition ()); return false; 

Stap 5: GoogleApiClient

Om de te gebruiken GeofencingApi interface, we hebben een GoogleApiClient ingangspunt. Laten we een implementeren GoogleApiClient.ConnectionCallbacks en een GoogleApiClient.OnConnectionFailedListener in de Activiteit zoals hieronder getoond.

public class MainActivity breidt AppCompatActivity implementeert GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, OnMapReadyCallback, GoogleMap.OnMapClickListener, GoogleMap.OnMarkerClickListener // ... private GoogleApiClient googleApiClient; @Override protected void onCreate (Bundle savedInstanceState) // ... // create GoogleApiClient createGoogleApi ();  // Create GoogleApiClient-instantie private void 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 (); // Bel GoogleApiClient-verbinding bij het starten van de activiteit googleApiClient.connect ();  @Override beschermde ongeldig onStop () super.onStop (); // Koppel GoogleApiClient los bij het stoppen van Activiteit googleApiClient.disconnect ();  // GoogleApiClient.ConnectionCallbacks connected @Override public void onConnected (@Nullable Bundle-bundel) Log.i (TAG, "onConnected ()");  // GoogleApiClient.ConnectionCallbacks suspended @Override public void onConnectionSuspended (int i) Log.w (TAG, "onConnectionSuspended ()");  // GoogleApiClient.OnConnectionFailedListener failed @Override public void onConnectionFailed (@NonNull ConnectionResult connectionResult) Log.w (TAG, "onConnectionFailed ()");  

Stap 6: FusedLocationProviderApi

We moeten ook toegang krijgen tot de huidige locatie van de gebruiker. De FusedLocationProviderApi interface geeft ons deze informatie en zorgt voor een grote mate van controle over het locatieverzoek. Dit is erg belangrijk, aangezien locatieverzoeken een direct effect hebben op het batterijverbruik van het apparaat.

Laten we nu een implementeren LocationListener. Controleer of de gebruiker de juiste machtigingen heeft gegeven door de Plaats vraag en toon hun huidige locatie op het scherm.

openbare klasse MainActivity breidt AppCompat uitActivity implementeert // ... LocationListener private Location lastLocation; // ... // GoogleApiClient.ConnectionCallbacks connected @Override public void onConnected (@Nullable Bundle-bundel) Log.i (TAG, "onConnected ()"); getLastKnownLocation ();  // Krijg laatst bekende locatie private 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, "Nog geen locatie opgehaald"); startLocationUpdates ();  else askPermission ();  private LocationRequest locationRequest; // Gedefinieerd in mili seconden. // Dit getal is extreem laag en mag alleen worden gebruikt voor het debuggen van private finale int int UPDATE_INTERVAL = 1000; private finale int FASTEST_INTERVAL = 900; // Startlocatie Updates 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 (Location location) Log.d (TAG, "onLocationChanged [" + location + "]"); lastLocation = locatie; writeActualLocation (locatie);  // Schrijf locatiecoördinaten op UI private void writeActualLocation (locatie locatie) textLat.setText ("Lat:" + location.getLatitude ()); textLong.setText ("Long:" + location.getLongitude ());  private void writeLastLocation () writeActualLocation (lastLocation);  // Controleer of u toegang hebt tot Location private boolean checkPermission () Log.d (TAG, "checkPermission ()"); // Vraag toestemming als het nog niet is toegekend (ContextCompat.checkSelfPermission (this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED);  // vraagt ​​om toestemming private void askPermission () Log.d (TAG, "askPermission ()"); ActivityCompat.requestPermissions (this, new String [] Manifest.permission.ACCESS_FINE_LOCATION, REQ_PERMISSION);  // Verifieer het antwoord van de gebruiker van de gevraagde toestemming @Override public void onRequestPermissionsResult (int requestCode, @NonNull String [] permissies, @NonNull int [] grantResults) Log.d (TAG, "onRequestPermissionsResult ()"); super.onRequestPermissionsResult (requestCode, permissions, grantResults); switch (requestCode) case REQ_PERMISSION: if (grantResults.length> 0 && grantResults [0] == PackageManager.PERMISSION_GRANTED) // Toegestane toestemming getLastKnownLocation ();  else // Toestemming geweigerd permissionsDenied ();  pauze;  // App kan niet werken zonder de machtigingen private void permissionsDenied () Log.w (TAG, "permissionsDenied ()"); 

Het is belangrijk om dat aan te pakken LocationRequest hierboven gemaakt is niet geoptimaliseerd voor een productieomgeving. De BIJWERKINGSONDERBREKING is te kort en zou te veel batterijvermogen verbruiken. Een meer realistische configuratie voor productie zou kunnen zijn:

privé finale int. UPDATE_INTERVAL = 3 * 60 * 1000; // 3 minuten private final int FASTEST_INTERVAL = 30 * 1000; // 30 secs privé 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); 

Stap 7: GoogleMap Markers

Onze Activiteit heeft twee verschillende markeringen nodig. EEN locationMarker gebruikt de breedtegraad en lengtegraad gegeven door de FusedLocationProviderApi om de huidige locatie van het apparaat te informeren. EEN geoFenceMarker is het doelwit voor de geofencecreatie omdat het de laatste aanraking gebruikt die op de kaart wordt gegeven om zijn positie op te halen.

@Override public void onMapClick (LatLng latLng) Log.d (TAG, "onMapClick (" + latLng + ")"); markerForGeofence (lengte- en breedtegraad);  private void writeActualLocation (Location location) // ... markerLocation (new LatLng (location.getLatitude (), location.getLongitude ()));  private Marker locationMarker; // Maak een Location Marker private void markerLocation (LatLng latLng) Log.i (TAG, "markerLocation (" + latLng + ")"); String title = latLng.latitude + "," + latLng.longitude; MarkerOptions markerOptions = new MarkerOptions () .position (latLng) .title (titel); if (map! = null) // Verwijder de voorste markering als (locationMarker! = null) locationMarker.remove (); locationMarker = map.addMarker (markerOptions); zwevende zoomlens = 14f; CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom (latLng, zoom); map.animateCamera (cameraUpdate);  private Marker geoFenceMarker; // Maak een markering voor de geofencecreatie private void markerForGeofence (LatLng latLng) Log.i (TAG, "markerForGeofence (" + latLng + ")"); String title = latLng.latitude + "," + latLng.longitude; // Definieer markeeropties MarkerOptions markerOptions = new MarkerOptions () .position (latLng) .icon (BitmapDescriptorFactory.defaultMarker (BitmapDescriptorFactory.HUE_ORANGE)) .title (titel); if (map! = null) // laatste geoFenceMarker verwijderen als (geoFenceMarker! = null) geoFenceMarker.remove (); geoFenceMarker = map.addMarker (markerOptions); 

Stap 8: Een geofence maken

Eindelijk is het tijd om een ​​geofence te creëren. Wij gebruiken de geoFenceMarker als het middelpunt voor de geofence.

privé statische finale lang GEO_DURATION = 60 * 60 * 1000; private static final String GEOFENCE_REQ_ID = "Mijn geofence"; privé statische laatste vlotter GEOFENCE_RADIUS = 500.0f; // in meters // Maak een Geofence private Geofence createGeofence (LatLng LatLng, Float Radius) Log.d (TAG, "createGeofence"); retourneer nieuwe Geofence.Builder () .setRequestId (GEOFENCE_REQ_ID) .setCircularRegion (latLng.latitude, latLng.longitude, radius) .setExpirationDuration (GEO_DURATION) .setTransitionTypes (Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT) .build (); 

Vervolgens maken we de GeofencingRequest voorwerp.

// Maak een Geofence Request private GeofencingRequest createGeofenceRequest (Geofence geofence) Log.d (TAG, "createGeofenceRequest"); retourneer nieuwe GeofencingRequest.Builder () .setInitialTrigger (GeofencingRequest.INITIAL_TRIGGER_ENTER) .addGeofence (geofence) .build (); 

We gebruiken een PendingIntent object om te bellen naar a IntentService dat zal omgaan met de GeofenceEvent. We maken de GeofenceTrasitionService.class later.

private PendingIntent geoFencePendingIntent; privé-finale int GEOFENCE_REQ_CODE = 0; private PendingIntent createGeofencePendingIntent () Log.d (TAG, "createGeofencePendingIntent"); if (geoFencePendingIntent! = null) retourneert geoFencePendingIntent; Intent intent = new Intent (this, GeofenceTrasitionService.class); return PendingIntent.getService (dit, GEOFENCE_REQ_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT);  // Voeg de gemaakte GeofenceRequest toe aan de bewakingslijst van het apparaat private void addGeofence (verzoek GeofencingRequest) Log.d (TAG, "addGeofence"); if (checkPermission ()) LocationServices.GeofencingApi.addGeofences (googleApiClient, request, createGeofencePendingIntent ()) .setResultCallback (this); 

We tekenen de geofence ook op de kaart als visuele referentie.

@Override public void onResult (@NonNull Status-status) Log.i (TAG, "onResult:" + status); if (status.isSuccess ()) drawGeofence ();  else // inform over mislukken // Teken Geofence-cirkel op GoogleMap 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); 

De startGeofence () methode is verantwoordelijk voor het starten van het geofencingproces in de Hoofdactiviteit klasse.

 @Override public boolean onOptionsItemSelected (MenuItem item) switch (item.getItemId ()) case R.id.geofence: startGeofence (); geef waar terug;  retourneer super.onOptionsItemSelected (item);  // Start het maken van Geofence-processen 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 is null"); 

Stap 9: Geofence Transition Service

We kunnen nu eindelijk de GeofenceTrasitionService.class eerder vermeld. Deze klasse breidt zich uit IntentService en is verantwoordelijk voor het gebruik van de GeofencingEvent. Eerst krijgen we deze gebeurtenis van de ontvangen intentie.

GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent (intent);

We gaan vervolgens na of het soort geofencing-transitie dat plaatsvond interessant voor ons is. Als dit het geval is, halen we een lijst met de geactiveerde geofences op en maken we een melding met de juiste acties.

// Ophalen GeofenceTrasition int geoFenceTransition = geofencingEvent.getGeofenceTransition (); // Controleer of het overgangstype if (geoFenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER || geoFenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) // De geofence ontvangt die is geactiveerd Lijst triggeringGeofences = geofencingEvent.getTriggeringGeofences (); // Maak een detailbericht met Geofences ontvangen String geofenceTransitionDetails = getGeofenceTrasitionDetails (geoFenceTransition, triggeringGeofences); // Stuur berichtdetails als String sendNotification (geofenceTransitionDetails); 

Ik heb ook een aantal hulpmethoden geïmplementeerd om de implementatie van de klas begrijpelijker te maken.

public class GeofenceTrasitionService breidt IntentService uit private static final String TAG = GeofenceTrasitionService.class.getSimpleName (); public static final int GEOFENCE_NOTIFICATION_ID = 0; public GeofenceTrasitionService () super (TAG);  @Override protected void onHandleIntent (Intent opzet) // Haal de Geofencing intentie op GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent (opzet); // Fouten afhandelen als (geofencingEvent.hasError ()) String errorMsg = getErrorString (geofencingEvent.getErrorCode ()); Log.e (TAG, errorMsg); terug te keren;  // GeofenceTrasition ophalen in geoFenceTransition = geofencingEvent.getGeofenceTransition (); // Controleer of het overgangstype if (geoFenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER || geoFenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) // De geofence ontvangt die is geactiveerd Lijst triggeringGeofences = geofencingEvent.getTriggeringGeofences (); // Maak een detailbericht met Geofences ontvangen String geofenceTransitionDetails = getGeofenceTrasitionDetails (geoFenceTransition, triggeringGeofences); // Stuur berichtdetails als String sendNotification (geofenceTransitionDetails);  // Maak een detailbericht met Geofences ontvangen privé String getGeofenceTrasitionDetails (int geoFenceTransition, List triggeringGeofences) // krijg de ID van elke geofence-getriggerde ArrayList triggeringGeofencesList = new ArrayList <> (); for (Geofence geofence: triggeringGeofences) triggeringGeofencesList.add (geofence.getRequestId ());  Stringstatus = null; if (geoFenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER) status = "Entering"; else if (geoFenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) status = "Exiting"; retourstatus + TextUtils.join (",", triggeringGeofencesList);  // Stuur een melding private void sendNotification (String msg) Log.i (TAG, "sendNotification:" + msg); // Intentie om de hoofdintentie Activity IntentIntent = MainActivity.makeNotificationIntent (getApplicationContext (), msg) te starten; TaskStackBuilder stackBuilder = TaskStackBuilder.create (this); stackBuilder.addParentStack (MainActivity.class); stackBuilder.addNextIntent (notificationIntent); PendingIntent notificationPendingIntent = stackBuilder.getPendingIntent (0, PendingIntent.FLAG_UPDATE_CURRENT); // Notification Notification aanmaken en verzendenManager notificatioMng = (NotificationManager) getSystemService (Context.NOTIFICATION_SERVICE); notificatioMng.notify (GEOFENCE_NOTIFICATION_ID, createNotification (msg, notificationPendingIntent));  // Maak een melding privé 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) .setDefaults (Notification.DEFAULT_LIGHTS | Notification.DEFAULT_VIBRATE | Notification.DEFAULT_SOUND ) .setAutoCancel (waar); return notificationBuilder.build ();  // Omgaan met fouten private static String getErrorString (int errorCode) switch (errorCode) case GeofenceStatusCodes.GEOFENCE_NOT_AVAILABLE: return "GeoFence not available"; case GeofenceStatusCodes.GEOFENCE_TOO_MANY_GEOFENCES: return "Too many GeoFences"; case GeofenceStatusCodes.GEOFENCE_TOO_MANY_PENDING_INTENTS: return "Too many pending intents"; standaard: return "Unknown error."; 

3. Testen

Testen op een virtueel apparaat

Het is veel eenvoudiger om geofencing te testen op een virtueel apparaat. Er zijn verschillende manieren om dit te doen. Open in Android Studio een virtueel apparaat en klik rechtsonder op de knop met meer opties.

In de Plaats tab aan de linkerkant, voer de coördinaten voor de locatie in.

Ik geef de voorkeur om te gebruiken telnet opdrachten om het virtuele apparaat te besturen. Om dit te gebruiken, moet u vanaf de opdrachtregel met het apparaat verbinden met behulp van de volgende opdracht:

telnet localhost [DEVICE_PORT]

De apparaatpoort wordt weergegeven in het virtuele apparaatvenster. De apparaatpoort is meestal gelijk aan 5554.

Het is mogelijk dat u deze verbinding moet autoriseren met uw auth_token, maar de commandolijn laat zien waar het zich bevindt. Navigeer naar die locatie en kopieer het token en typ het, auth [YOUR_AUTH_TOKEN].

U kunt nu de locatie van het apparaat instellen door de volgende opdracht uit te voeren:

geo-fix [LATITUDE] [LONGITUDE]

Conclusie

Geofencing is misschien een geweldige toevoeging aan uw app omdat het de betrokkenheid van gebruikers aanzienlijk kan vergroten. Er zijn veel mogelijkheden om te verkennen en je kunt zelfs een verfijnde ervaring creëren met binnenbakens, zoals de Estimote. Met binnenbakens weet u precies waar de gebruiker is gepasseerd, bijvoorbeeld een winkelcentrum.

Het toevoegen van Geofencing aan een project is eenvoudig, maar we moeten te allen tijde rekening houden met het stroomverbruik. Dit betekent dat we zorgvuldig de grootte van de geofence en de updatetarief moeten kiezen, omdat ze beide rechtstreeks van invloed zijn op het energieverbruik van uw toepassing.

Testen is daarom erg belangrijk om een ​​realistisch beeld te krijgen van het stroomverbruik van uw applicatie. Overweeg ook om gebruikers de optie te geven om geofencing helemaal uit te schakelen als ze deze functie niet nodig hebben of nodig hebben.