Comment travailler avec Geofences sur Android

Les ressources sensibles à l'emplacement permettent à votre application d'interagir avec le monde physique et sont idéales pour accroître l'engagement de l'utilisateur. Bien que de nombreuses applications mobiles les utilisent, le sujet de ce didacticiel est une fonctionnalité qui est souvent négligée..

Une clôture géographique est un périmètre virtuel situé sur une zone géographique réelle. En combinant une position d'utilisateur avec un périmètre de barrière virtuelle, il est possible de savoir si l'utilisateur se trouve à l'intérieur ou à l'extérieur de la barrière virtuelle ou même s'il sort ou entre dans la zone..

Imaginez une application universitaire qui puisse vous dire quels collègues et professeurs se trouvent actuellement sur le campus. Ou une application pour un centre commercial qui récompense les clients réguliers. Il y a beaucoup d'autres possibilités intéressantes que vous pouvez explorer.

Dans ce didacticiel, vous apprendrez à utiliser geofences sur Android en créant une application qui affiche une notification à l'utilisateur lorsqu'il entre ou quitte une geofence. Si vous avez une connaissance préalable des services Google Play, de l'API Google Maps Android ou de IntentService. Si vous ne le faites pas, vous pouvez continuer, mais vous voudrez peut-être faire des recherches sur ces sujets après avoir lu ce tutoriel..

1. Geofences sur Android

Sur Android, il existe plusieurs façons de travailler avec geofences. Vous pouvez même créer votre propre implémentation pour travailler avec geofences, mais il est plus facile d'utiliser celui de Google. GeofencingApi.

Cette API fait partie de Google Emplacement Apis. Il comprend Geofence, GeofencingRequest, GeofenceApiGeofencingEvent, et GeofenceStatusCodes. Dans ce tutoriel, nous utilisons ces classes pour créer et travailler avec geofences.

Interface Geofence

Geofence est une interface qui représente une zone géographique à surveiller. Il est créé en utilisant le Geofence.Builder. Lors de sa création, vous définissez la région surveillée, la date d'expiration de la barrière virtuelle, sa réactivité, un identificateur et le type de transitions qu'il devrait rechercher..

Pour réduire au maximum la consommation électrique, il est recommandé d’utiliser une clôture géographique d’un rayon d’au moins 100 mètres dans la plupart des situations. Si les clôtures géographiques sont situées à la campagne, vous devez augmenter le rayon à 500 mètres ou plus pour vous assurer que les clôtures sont efficaces..

Geofence geofence = new Geofence.Builder () .setRequestId (GEOFENCE_REQ_ID) // ID Geofence .setCircularRegion (LATITUDE, LONGITUDE, RADIUS) // définition de la région de clôture .setExpirationDuration (DURANTION) // date d'expiration // types de transition qu'il convient de rechercher .setTransitionTypes (Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT) .build ();

Geofence Transitions

  • GEOFENCE_TRANSITION_DWELL indique que l'utilisateur est entré dans la zone et y a passé du temps. Il est utile d'éviter les alertes multiples lorsque l'utilisateur entre et quitte la zone trop rapidement. Vous pouvez configurer le temps de séjour à l’aide des touches setLoiteringDelay paramètre.
  • GEOFENCE_TRANSITION_ENTER indique quand l'utilisateur entre dans la région surveillée.
  • GEOFENCE_TRANSITION_EXIT  indique quand l'utilisateur quitte la région.

GeofenceRequest

le GeofencingRequest classe reçoit les geofences qui devraient être surveillés. Vous pouvez créer une instance en utilisant un Constructeur, en passant un Geofence ou un liste, et le type de notification à déclencher lorsque la / les barrière (s) géographique (s) est (sont) créée (s).

GeofencingRequest request = new GeofencingRequest.Builder () // Notification à déclencher lors de la création de la Geofence .setInitialTrigger (GeofencingRequest.INITIAL_TRIGGER_ENTER) .addGeofence (geofence) // ajouter un Geofence .build ();

GeofencingApi

le GeofencingApi La classe est le point d'entrée de toutes les interactions avec l'API Google Geofencing. Cela fait partie de la Emplacement API et cela dépend d'un GoogleApiClient travailler. Vous utiliserez le GeofencingApi ajouter et supprimer des geofences.

Pour ajouter une barrière géographique, vous appelez le addGeofence () méthode. Il surveille la zone donnée en utilisant les paramètres passés au GeofencingRequest et tire un En attente d'intention lorsqu'une transition de barrière virtuelle, entrant ou sortant de la zone, a lieu.

En attente de résultat addGeofences (client GoogleApiClient, GeofencingRequest geofencingRequest, PendingIntent waitingIntent)

Pour enlever la barrière virtuelle, vous appelez removeGeofences (). Vous pouvez soit supprimer la barrière géographique en utilisant son identifiant de requête ou son intention en attente..

En attente de résultat removeGeofences (client GoogleApiClient, Liste geofenceRequestIds)
 En attente de résultat removeGeofences (client GoogleApiClient, PendingIntent waitingIntent)

2. Créer une application Geofencing

Dans ce didacticiel, nous créons une application simple qui surveille l’emplacement de l’utilisateur et publie une notification lorsque celui-ci entre ou quitte une zone géo clôturée. L'application est composée d'un seul Activité Et un IntentService. Nous examinons aussi rapidement Google Map, GoogleApiClient, et FusedLocationProviderApi, et nous explorons quelques mises en garde de l’API geofence.

Étape 1: Configuration du projet

GeofencingApi fait partie de Google Play Services. Pour y accéder, vous devez configurer correctement votre environnement de développement et créer une instance du GoogleApiClient. Créer un nouveau projet avec un blanc Activité, éditer le projet build.gradle comme indiqué ci-dessous et synchronisez votre projet.

Étape 2: autorisations

Nous devons définir les autorisations appropriées pour créer et utiliser geofences. Ajoutez l'autorisation suivante au manifeste du projet:

À partir d'Android 6.0, l'application demande une autorisation au moment de l'exécution et non pendant l'installation. Nous abordons cela plus tard dans le tutoriel.

Étape 3: Création de la mise en page

Le projet consiste en une mise en page, la MainActity disposition. Il contient la latitude et la longitude actuelles de l'appareil, ainsi qu'un Google Map fragment qui affiche les geofences et la position de l'utilisateur.

Puisque activity_main.xml est assez simple, je veux me concentrer uniquement sur MapFragment élément. Vous pouvez jeter un oeil à la mise en page complète dans les fichiers source de ce tutoriel.

 

Étape 4: Clé de l'API Google Maps

Puisque nous utilisons un MapFragment, nous devons configurer et initialiser un Google Map exemple. Tout d'abord, vous devez obtenir une clé API. Une fois que vous avez une clé API, ajoutez-la au manifeste du projet..

Commençons par le Google Map exemple. Mettre en place GoogleMap.OnMapReadyCallbackGoogleMap.OnMapClickListener, et GoogleMap.OnMarkerClickListener dans le Activité classe et initialise la carte.

Classe publique MainActivity étend AppCompatActivity implémente OnMapReadyCallback, GoogleMap.OnMapClickListener, GoogleMap.OnMarkerClickListener private statique final String TAG = MainActivity.class.getSimpleName (); private TextView textLat, textLong; carte privée MapFragment mapFragment; carte Google Map privée; @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); // initialise GoogleMaps initGMaps ();  // Initialisation de la void privée de GoogleMaps initGMaps () mapFragment = (MapFragment) getFragmentManager (). FindFragmentById (R.id.map); mapFragment.getMapAsync (this);  // Callback appelé lorsque Map est prêt @Override public void onMapReady (GoogleMap googleMap) Log.d (TAG, "onMapReady ()"); map = googleMap; map.setOnMapClickListener (this); map.setOnMarkerClickListener (this);  // Callback appelé lorsque Map est touché @Override public void onMapClick (LatLng latLng) Log.d (TAG, "onMapClick (" + latLng + ")");  // Rappel appelé lorsque le marqueur est touché @Override public boolean onMarkerClick (marqueur) Log.d (TAG, "onMarkerClickListener:" + marker.getPosition ()); retourne faux; 

Étape 5: GoogleApiClient

Pour utiliser le GeofencingApi interface, nous avons besoin d'un GoogleApiClient point d'accès. Mettons en œuvre un GoogleApiClient.ConnectionCallbacks et un GoogleApiClient.OnConnectionFailedListener dans le Activité comme indiqué ci-dessous.

La classe publique MainActivity s'étend AppCompatActivity implémente GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, OnMapReadyCallback, GoogleMap.OnMapClickListener, GoogleMap.OnMarkerClickListener // private GoogleAjout @Override protected void onCreate (Ensemble, savedInstanceState) //… // create GoogleApiClient createGoogleApi ();  // Créer une instance privée de GoogleApiClient 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 (); // Appelez la connexion GoogleApiClient lors du démarrage de l'activité googleApiClient.connect ();  @Override protected void onStop () super.onStop (); // Déconnectez GoogleApiClient lors de l'arrêt de l'activité googleApiClient.disconnect ();  // GoogleApiClient.ConnectionCallbacks connected @Override public void onConnected (ensemble d'ensembles @Nullable) Log.i (TAG, "onConnected ()");  // GoogleApiClient.ConnectionCallbacks suspendus @Override public void onConnectionSuspended (int i) Log.w (TAG, "onConnectionSuspended ()");  // GoogleApiClient.OnConnectionFailedListener fail @Override public void onConnectionFailed (@NonNull ConnectionResult connectionResult) Log.w (TAG, "onConnectionFailed ()");  

Étape 6: FusedLocationProviderApi

Nous devons également accéder à l'emplacement actuel de l'utilisateur. le FusedLocationProviderApi L’interface nous donne ces informations et permet un grand niveau de contrôle de la demande de localisation. Ceci est très important, étant donné que les demandes d'emplacement ont un effet direct sur la consommation de la batterie de l'appareil..

Maintenant, implémentons un LocationListener. Vérifiez si l'utilisateur a accordé à l'application les autorisations appropriées en créant le Emplacement demande et affiche leur position actuelle sur l'écran.

Classe publique MainActivity étend AppCompatActivity implémente //… LocationListener private Location lastLocation; //… // GoogleApiClient.ConnectionCallbacks connected @Override public void onConnected (ensemble d'ensembles @Nullable) Log.i (TAG, "onConnected ()"); getLastKnownLocation ();  // Obtenir le dernier emplacement connu privé privé 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, "Aucun emplacement encore récupéré"); startLocationUpdates ();  else askPermission ();  private LocationRequest locationRequest; // Défini en millisecondes. // Ce nombre est extrêmement faible et ne doit être utilisé que pour le débogage privé final int UPDATE_INTERVAL = 1000; int finale finale FASTEST_INTERVAL = 900; // Emplacement de départ Met à jour le fichier void privé 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 (emplacement) Log.d (TAG, "onLocationChanged [" + emplacement + "]"); lastLocation = location; writeActualLocation (location);  // Écrire les coordonnées de l'emplacement sur l'interface utilisateur privée void writeActualLocation (Emplacement de l'emplacement) textLat.setText ("Lat:" + location.getLatitude ()); textLong.setText ("Long:" + location.getLongitude ());  void privé writeLastLocation () writeActualLocation (lastLocation);  // Vérifier l'autorisation d'accéder à l'emplacement privé booléen checkPermission () Log.d (TAG, "checkPermission ()"); // Demande la permission s'il n'a pas encore été accordé return (ContextCompat.checkSelfPermission (this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED);  // Demande l'autorisation privée void askPermission () Log.d (TAG, "askPermission ()"); ActivityCompat.requestPermissions (this, nouvelle chaîne [] Manifest.permission.ACCESS_FINE_LOCATION, REQ_PERMISSION);  // Vérifier la réponse de l'utilisateur à l'autorisation demandée @Override public void onRequestPermissionsResult (int requestCode, permissions @NonNull String [], @NonNull int [] grantResults) Log.d (TAG, "onRequestPermissionsResult ()"); super.onRequestPermissionsResult (requestCode, autorisations, grantResults); switch (requestCode) case REQ_PERMISSION: if (grantResults.length> 0 && grantResults [0] == PackageManager.PERMISSION_GRANTED) // Autorisation accordée à getLastKnownLocation ();  else // Autorisation refusée permissionsDenied ();  Pause;  // L'application ne peut pas fonctionner sans les autorisations privées void permissionsDenied () Log.w (TAG, "permissionsDenied ()"); 

Il est important de s’adresser au LocationRequest créé ci-dessus n'est pas optimisé pour un environnement de production. le INTERVALLE DE MISE À JOUR est trop court et consomme trop de batterie. Une configuration plus réaliste pour la production pourrait être:

int final final UPDATE_INTERVAL = 3 * 60 * 1000; // 3 minutes privé final int FASTEST_INTERVAL = 30 * 1000; // 30 secondes privées 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); 

Étape 7: Marqueurs GoogleMap

Notre Activité a besoin de deux marqueurs différents. UNE locationMarker utilise la latitude et la longitude données par le FusedLocationProviderApi pour indiquer l'emplacement actuel de l'appareil. UNE geoFenceMarker est la cible pour la création de la barrière virtuelle car il utilise la dernière touche donnée sur la carte pour récupérer sa position.

@Override public void onMapClick (LatLng latLng) Log.d (TAG, "onMapClick (" + latLng + ")"); marqueurForGeofence (latLng);  private void writeActualLocation (Emplacement d'emplacement) //… markerLocation (new LatLng (location.getLatitude (), location.getLongitude ()));  private Marker locationMarker; // Créer un marqueur de position private void markerLocation (LatLng latLng) Log.i (TAG, "markerLocation (" + latLng + ")"); Titre de la chaîne = latLng.latitude + "," + latLng.longitude; MarkerOptions markerOptions = new MarkerOptions () .position (latLng) .title (title); if (map! = null) // Supprime le marqueur antérieur if (locationMarker! = null) locationMarker.remove (); locationMarker = map.addMarker (markerOptions); zoom flottant = 14f; CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom (latLng, zoom); map.animateCamera (cameraUpdate);  marque privée geoFenceMarker; // Créer un marqueur pour la création d'une geofence privée void markerForGeofence (LatLng latLng) Log.i (TAG, "markerForGeofence (" + latLng + ")"); Titre de la chaîne = latLng.latitude + "," + latLng.longitude; // Définition des options de marqueur MarkerOptions markerOptions = new MarkerOptions () .position (latLng) .icon (BitmapDescriptorFactory.defaultMarker (BitmapDescriptorFactory.HUE_ORANGE)) .title (title); if (map! = null) // Supprime le dernier geoFenceMarker if (geoFenceMarker! = null) geoFenceMarker.remove (); geoFenceMarker = map.addMarker (markerOptions); 

Étape 8: Création d'une barrière géologique

Enfin, il est temps de créer une clôture géographique. Nous utilisons le geoFenceMarker comme point central de la clôture.

finale statique privée longue GEO_DURATION = 60 * 60 * 1000; private static final String GEOFENCE_REQ_ID = "Ma Geofence"; float final statique privé GEOFENCE_RADIUS = 500.0f; // en mètres // Créer une Geofence privée Geofence createGeofence (LatLng latLng, float radius) Log.d (TAG, "createGeofence"); renvoient une nouvelle Geofence.Builder () .setRequestId (GEOFENCE_REQ_ID) .setCircularRegion (latLng.latitude, latLng.longitude, radius) .setExpirationDuration (GEO_DURATION) .setTransitionTypes (Geof.GEFENCE_TRANSITION_TRANSITION_General) 

Ensuite, nous créons le GeofencingRequest objet.

// Créer une requête Geofence privée GeofencingRequest createGeofenceRequest (Geofence geofence) Log.d (TAG, "createGeofenceRequest"); retourne une nouvelle GeofencingRequest.Builder () .setInitialTrigger (GeofencingRequest.INITIAL_TRIGGER_ENTER) .addGeofence (geofence) .build (); 

Nous utilisons un En attente d'intention objet à appeler un IntentService qui va gérer le GeofenceEvent. Nous créons le GeofenceTrasitionService.class plus tard.

private PendingIntent geoFencePendingIntent; int finale privée GEOFENCE_REQ_CODE = 0; private PendingIntent createGeofencePendingIntent () Log.d (TAG, "createGeofencePendingIntent"); if (geoFencePendingIntent! = null) renvoie geoFencePendingIntent; Intention d'intention = nouvelle intention (this, GeofenceTrasitionService.class); return PendingIntent.getService (ceci, GEOFENCE_REQ_CODE, intention, PendingIntent.FLAG_UPDATE_CURRENT);  // Ajouter le GeofenceRequest créé à la liste de contrôle du périphérique privé void addGeofence (demande GeofencingRequest) Log.d (TAG, "addGeofence"); if (checkPermission ()) LocationServices.GeofencingApi.addGeofences (googleApiClient, requête, createGeofencePendingIntent ()) .setResultCallback (this); 

Nous dessinons également la barrière géographique sur la carte comme référence visuelle.

@Override public void onResult (statut @NonNull Status) Log.i (TAG, "onResult:" + status); if (status.isSuccess ()) drawGeofence ();  else // informer sur l'échec // Dessiner un cercle Geofence sur un cercle privé GoogleMap 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); 

le startGeofence () Cette méthode est responsable du démarrage du processus de geofencing dans le Activité principale classe.

 @Override public boolean onOptionsItemSelected (élément MenuItem) switch (item.getItemId ()) case R.id.geofence: startGeofence (); retourne vrai;  return super.onOptionsItemSelected (item);  // Démarrer le processus de création Geofence 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, "Le marqueur Geofence est null"); 

Étape 9: Service de transition Geofence

Nous pouvons maintenant enfin créer le GeofenceTrasitionService.class mentionné plus tôt. Cette classe s'étend IntentService et est responsable de la gestion de la GeofencingEvent. Tout d'abord, nous obtenons cet événement de l'intention reçue.

GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent (intention);

Nous vérifions ensuite si le type de transition de geofencing qui a eu lieu nous intéresse. Si c'est le cas, nous récupérons une liste des clôtures géographiques déclenchées et créons une notification avec les actions appropriées.

// Récupérer GeofenceTrasition int geoFenceTransition = geofencingEvent.getGeofenceTransition (); // Vérifie si le type de transition if (geoFenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER || geoFenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) // Récupère la géofence déclenchée. triggeringGeofences = geofencingEvent.getTriggeringGeofences (); // Créer un message de détail avec les Geofences reçues. String geofenceTransitionDetails = getGeofenceTrasitionDetails (geoFenceTransition, triggeringGeofences); // Envoyer les détails de la notification sous forme de chaîne sendNotification (geofenceTransitionDetails); 

J'ai également implémenté quelques méthodes d'assistance pour rendre la mise en œuvre de la classe plus facile à comprendre..

La classe publique GeofenceTrasitionService étend IntentService private static final String TAG = GeofenceTrasitionService.class.getSimpleName (); public static final int GEOFENCE_NOTIFICATION_ID = 0; public GeofenceTrasitionService () super (TAG);  @Override protected void onHandleIntent (Intention Intention) // Récupère l'intention de Geofencing GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent (Intention); // Traitement des erreurs if (geofencingEvent.hasError ()) String errorMsg = getErrorString (geofencingEvent.getErrorCode ()); Log.e (TAG, errorMsg); revenir;  // Récupérer GeofenceTrasition int geoFenceTransition = geofencingEvent.getGeofenceTransition (); // Vérifie si le type de transition if (geoFenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER || geoFenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) // Récupère la géofence déclenchée. triggeringGeofences = geofencingEvent.getTriggeringGeofences (); // Créer un message de détail avec les Geofences reçues. String geofenceTransitionDetails = getGeofenceTrasitionDetails (geoFenceTransition, triggeringGeofences); // Envoyer les détails de la notification sous forme de chaîne sendNotification (geofenceTransitionDetails);  // Créer un message détaillé avec la chaîne privée reçue par Geofences getGeofenceTrasitionDetails (int geoFenceTransition, List triggeringGeofences) // récupère l'ID de chaque geofence déclenchée ArrayList triggeringGeofencesList = new ArrayList <> (); for (geofence geofence: triggeringGeofences) triggeringGeofencesList.add (geofence.getRequestId ());  String status = null; if (geoFenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER) status = "Entrée"; else if (geoFenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) status = "Exiting"; return status + TextUtils.join (",", triggeringGeofencesList);  // Envoyer une notification privée void sendNotification (String msg) Log.i (TAG, "sendNotification:" + msg); // intention de démarrer l'activité principale intention 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); // Création et envoi de Notification NotificationManager notificatioMng = (NotificationManager) getSystemService (Context.NOTIFICATION_SERVICE); notificatioMng.notify (GEOFENCE_NOTIFICATION_ID, createNotification (msg, notificationPendingIntent));  // Créer une notification privée 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 ("Notification Geofence!") .setContentIntent (notificationPendingIntent) .setDefaults (NotificationDeFistePoints de vente) ) .setAutoCancel (true); renvoyer notificationBuilder.build ();  // Traitement des erreurs private String statique getErrorString (int errorCode) switch (errorCode) case GeofenceStatusCodes.GEOFENCE_NOT_AVAILABLE: return "GeoFence not available"; case GeofenceStatusCodes.GEOFENCE_TOO_MANY_GEOFENCES: retourne "Trop de GeoFences"; case GeofenceStatusCodes.GEOFENCE_TOO_MANY_PENDING_INTENTS: retourne "Trop d'intentions en attente"; défaut: retourne "Erreur inconnue." 

3. Test

Test sur un périphérique virtuel

Il est beaucoup plus simple de tester le geofencing sur un périphérique virtuel. Il y a plusieurs moyens de le faire. Dans Android Studio, ouvrez un périphérique virtuel et cliquez sur le bouton Plus d'options en bas à droite..

dans le Emplacement onglet à gauche, entrez les coordonnées de l'emplacement.

Je préfère utiliser telnet commandes pour contrôler le périphérique virtuel. Pour utiliser cela, vous devez vous connecter au périphérique à partir de la ligne de commande à l'aide de la commande suivante:

telnet localhost [DEVICE_PORT]

Le port du périphérique est affiché dans la fenêtre du périphérique virtuel. Le port du périphérique est généralement égal à 5554.

Il est possible que vous deviez autoriser cette connexion en utilisant votre auth_token, mais la ligne de commande vous indique où il se trouve. Accédez à cet emplacement et copiez le jeton et tapez, auth [YOUR_AUTH_TOKEN].

Vous pouvez maintenant définir l'emplacement du périphérique en exécutant la commande suivante:

geo fix [LATITUDE] [LONGITUDE]

Conclusion

Le géofencing peut être un excellent ajout à votre application, car il peut considérablement augmenter la participation de l'utilisateur. Il existe de nombreuses possibilités à explorer et vous pouvez même créer une expérience sophistiquée en utilisant des balises intérieures, telles que la Estimote. Avec les balises d'intérieur, vous savez exactement où l'utilisateur est passé, par exemple un centre commercial.

L'ajout de Geofencing à un projet est simple, mais nous devons toujours garder à l'esprit la consommation d'énergie. Cela signifie que nous devons choisir avec soin la taille de la barrière géographique et le taux de mise à jour car ils ont tous deux un impact direct sur la consommation de votre application..

Le test est donc très important pour avoir une idée réaliste de la consommation d'énergie de votre application. Pensez également à donner aux utilisateurs la possibilité de désactiver complètement le geofencing s'ils ne veulent pas ou n'ont pas besoin de cette fonctionnalité..