📜 ⬆️ ⬇️

Work with geofences (geofences) in Android. Update

Some time ago I was assigned the task of determining the change of the user's location on the map. According to the results of the experiment in the article , Google Services Geofences is perfectly suited for this purpose, in terms of definition accuracy and energy efficiency.


image


How to work with Geofences is described in detail in a single Russian-language example on the use of Location APIs in an article on Habré, but 2 years have passed since then, and the information is very outdated.


The author’s example on github , unfortunately, didn’t even compile, so I decided to start it under the latest versions of libraries. To my surprise, there are many changes in the API between com.google.android.gms:play-services:4.0.30 and com.google.android.gms:play-services:8.4.0 ! Actually, they will be discussed further in the article.


Code

Updated github example (at the time of writing, the author of the original example did not accept the pull request).


So what are the differences?


To begin with, it is desirable to get acquainted with the original .


In the concept itself, nothing has changed, only the responsible classes have changed.
So, instead of LocationClient we have api.GoogleApiClient , callbacks from GooglePlayServicesClient also moved to api.GoogleApiClient , instead of new LocationClient(this, this, this) a convenient builder appeared:


  new GoogleApiClient.Builder(this) .addApi(LocationServices.API) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this) .build(); 

An important difference is that mGoogleApiClient is not directly mGoogleApiClient in adding and deleting mGoogleApiClient , but through LocationServices.GeofencingApi .


  GeofencingRequest build = ... LocationServices.GeofencingApi.addGeofences(mGoogleApiClient, builder.build(), getPendingIntent()) .setResultCallback(new ResultCallback<Status>() { @Override public void onResult(@NonNull Status status) { if (status.isSuccess()) { String msg = "Geofences added: " + status.getStatusMessage(); Log.e("GEO", msg); Toast.makeText(GeofencingService.this, msg, Toast.LENGTH_SHORT) .show(); } GeofencingService.this.onResult(status); } }); 

The first parameter has also changed: instead of the list of geozones, the GeofencingRequest is passed, which can be obtained through a special builder:


  GeofencingRequest.Builder builder = new GeofencingRequest.Builder(); builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER); builder.addGeofences(mGeofenceListsToAdd); GeofencingRequest build = builder.build(); 

One of the features of the new builder is control over the geofence behavior at the moment of addition. For example, in the comments to the original article asked about the possibility of triggering Exit geofence for the case when the device is outside the zone at the time of its installation. Now you can do this by passing the GeofencingRequest.INITIAL_TRIGGER_EXIT flag via the setInitialTrigger (int initialTrigger) method setInitialTrigger (int initialTrigger) , by default GeofencingRequest.INITIAL_TRIGGER_ENTER and GeofencingRequest.INITIAL_TRIGGER_DWELL flags. Flags can be combined with each other.


In addition, the last callback parameter was removed, now LocationServices.GeofencingApi.addGeofences returns the PendingResult , with which you can block a stream, wait for a result or get a response asynchronously using the callback method setResultCallback(..) . In any case, the result will be the status of the add / delete geofence operation. This callback replaces OnAddGeofencesResultListener or onRemoveGeofencesByRequestIdsResult from the original article.


You can remove unnecessary geofences through the methods:


  LocationServices.GeofencingApi.removeGeofences(mGoogleApiClient, /*PendingIntent   id */) 

Changes to ReceiveTransitionsIntentService


If earlier, the processing of trigger triggering results on the geofence used static methods from the LocationClient class, which required the incoming Intent as a parameter, now GeofencingEvent , which has methods of the same name, does the same work. You can get it as follows:


 GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent); 

The creation of geofences themselves remains unchanged and takes place through Geofence.Builder .


Another of the innovations is that after the triggering of the trigger, the geofence is automatically removed, so we do not need to remove them anymore!


Also in the example code, I added another button that puts a geofence with a trigger to exit it.


A few tips on working with geofences



References:



')

Source: https://habr.com/ru/post/282129/


All Articles