Location aware resources allow your application to interact with the physical world and they are ideal for increasing user engagement. Although many mobile apps use them, the topic of this tutorial is a feature that is often overlooked, geofencing.

A geofence is a virtual perimeter set on a real geographic area. Combining a user position with a geofence perimeter, it is possible to know if the user is inside or outside the geofence or even if he is exiting or entering the area.

Imagine a university app that can tell you which colleagues and professors are currently on campus. Or an app for a mall that rewards regular customers. There are many other interesting possibilities that you can explore.

In this tutorial, you learn how to use geofences on Android by creating an application that shows the user a notification when they enter or exit a geofence. It helps if you have previous knowledge of Google Play Services, the Google Maps Android API, or IntentService . If you don't, then you can still follow along, but you may want to do some research about these topics after reading this tutorial.

1. Geofences on Android

On Android, there are several ways to work with geofences. You could even create your own implementation to work with geofences, but it is easier to use Google's GeofencingApi .

This APIs is part of Google's Location APIs. It includes Geofence , GeofencingRequest , GeofenceApi , GeofencingEvent , and GeofenceStatusCodes . In this tutorial, we use these classes to create and work with geofences.

Geofence Interface

Geofence is an interface that represents a geographical area that should be monitored. It is created by using the Geofence.Builder . During its creation, you set the monitored region, the geofence's expiration date, responsiveness, an identifier, and the kind of transitions that it should be looking for.

To keep power consumption to a minimum, it is recommended to use a geofence with a radius of at least 100 meters for most situations. If geofences are located in the countryside, you should increase the radius to 500 meters or higher to make sure the geofences are effective.

Geofence Transitions

GEOFENCE_TRANSITION_DWELL indicates that the user entered the area and spent some time there. It is useful to avoid multiple alerts when the user is entering and exiting the area too fast. You can configure the dwelling time using the setLoiteringDelay parameter.

indicates that the user entered the area and spent some time there. It is useful to avoid multiple alerts when the user is entering and exiting the area too fast. You can configure the dwelling time using the parameter. GEOFENCE_TRANSITION_ENTER indicates when the user enters the monitored region.

indicates when the user enters the monitored region. GEOFENCE_TRANSITION_EXIT indicates when the user exits the region.



GeofenceRequest

The GeofencingRequest class receives the geofences that should be monitored. You can create an instance by using a Builder , passing a Geofence or a List<Geofence> , and the kind of notification to trigger when the geofence(s) is created.

GeofencingApi

The GeofencingApi class is the entry point for all interactions with Google's geofencing API. It is part of the Location APIs and it depends on a GoogleApiClient to work. You will use the GeofencingApi to add and remove geofences.

To add a geofence, you call the addGeofence() method. It monitors the given area using the settings passed to the GeofencingRequest and shoots a PendingIntent when a geofence transition, entering or exiting the area, takes place.

To remove the geofence, you call removeGeofences() . You can either remove the geofence using its request identifier or its pending intent.

2. Creating a Geofencing App

In this tutorial, we create a simple application that monitors the user location and posts a notification when the user enters or exits a geofenced area. The app consists of only one Activity and an IntentService . We also take a quick look at GoogleMap , GoogleApiClient , and FusedLocationProviderApi , and we explore some caveats of the geofence API.

Step 1: Project Setup

GeofencingApi is part of Google Play Services. To access it, you need to correctly set up your development environment and create an instance of the GoogleApiClient . Create a new project with a blank Activity , edit the project's build.gradle file as shown below, and synchronize your project.

Step 2: Permissions



We need to set the correct permissions to create and use geofences. Add the following permission to the project's manifest:

Starting with Android 6.0, the app asks for permission at run time and not during the installation. We address this later in the tutorial.



Step 3: Creating the Layout



The project consists of one layout, the MainActity layout. It contains the device's current latitude and longitude, and a GoogleMap fragment that displays the geofences and the user's position.

Since activity_main.xml is pretty straightforward, I want to concentrate only on the MapFragment element. You can take a look at the completed layout in the source files of this tutorial.

Step 4: Google Maps API Key

Since we are using a MapFragment , we need to set up and initialize a GoogleMap instance. First, you need to obtain an API key. Once you have an API key, add it to the project's manifest.

Let's begin with the GoogleMap instance. Implement GoogleMap.OnMapReadyCallback , GoogleMap.OnMapClickListener , and GoogleMap.OnMarkerClickListener in the Activity class and initialize the map.

Step 5: GoogleApiClient



To use the GeofencingApi interface, we need a GoogleApiClient entry point. Let's implement a GoogleApiClient.ConnectionCallbacks and a GoogleApiClient.OnConnectionFailedListener in the Activity as shown below.

Step 6: FusedLocationProviderApi



We also need to access the user's current location. The FusedLocationProviderApi interface gives us this information and allows a great level of control of the location request. This is very important, considering that location requests have a direct effect over the device's battery consumption.

Now, let's implement a LocationListener . Check if the user gave the application the appropriate permissions by creating the Location request and display their the current location on the screen.

It is important to address that the LocationRequest created above isn't optimized for a production environment. The UPDATE_INTERVAL is too short and would consume too much battery power. A more realistic configuration for production could be:

Step 7: GoogleMap Markers

Our Activity needs two different markers. A locationMarker uses the latitude and longitude given by the FusedLocationProviderApi to inform the device's current location. A geoFenceMarker is the target for the geofence creation as it uses the last touch given on the map to retrieve its position.



Step 8: Creating a Geofence

At last, it is time to create a geofence. We use the geoFenceMarker as the center point for the geofence.

Next, we create the GeofencingRequest object.

We use a PendingIntent object to call a IntentService that will handle the GeofenceEvent . We create the GeofenceTrasitionService.class later.

We also draw the geofence on the map as a visual reference.

The startGeofence() method is responsible for starting the geofencing process in the MainActivity class.

Step 9: Geofence Transition Service



We can now finally create the GeofenceTrasitionService.class mentioned earlier. This class extends IntentService and is responsible for handling the GeofencingEvent . First, we get this event from the received intent.

We then check if the kind of geofencing transition that took place is of interest to us. If it is, we retrieve a list of the triggered geofences and create a notification with the appropriate actions.



I have also implemented a few helper methods to make the implementation of the class easier to understand.

3. Testing

Testing on a Virtual Device

It is much simpler to test geofencing on a virtual device. There are several ways to do this. In Android Studio, open a virtual device and click the more options button in the bottom right.

In the Location tab on the left, enter the coordinates for the location.

I prefer to use telnet commands to control the virtual device. To use this, you need to connect to the device from the command line using the following command:

The device port is shown in the virtual device window. The device port is usually equal to 5554.

It is possible that you need to authorize this connection using your auth_token , but the command line shows you where it is located. Navigate to that location and copy the token and type, auth [YOUR_AUTH_TOKEN] .



You can now set the location of the device by running the following command:

Conclusion

Geofencing may be a great addition to your app as it can considerably increase user engagement. There are lots of possibilities to explore and you could even create a sophisticated experience using indoor beacons, such as the Estimote. With indoor beacons, you know exactly where the user has passed in, for example, a shopping mall.



Adding Geofencing to a project is simple, but we need to keep power consumption in mind at all times. This means that we need to carefully choose the size of the geofence and the update rate because both directly impact power consumption of your application.

Testing is therefore very important to get a realistic idea of the power consumption of your application. Also consider giving users the option to disable geofencing altogether if they don't want or need this feature.