Geofences on Android with GoogleApiClient

In this tutorial you’ll learn how to leverage GoogleApiClient to add geofences to an Android app, as well as post notifications when a geofence is crossed. By Joe Howard.

Leave a rating/review
Save for later
Share

Let your device answer pesky questions from the back seat! :]

AWTY-GC-250

Road trip! Summer is almost here, and for families the world over, that means hopping in the car and heading to a favorite vacation spot. For long trips, the inevitable “Are we there yet?” questions will ring forth from the kids in the back seat.

Wouldn’t it be great to give them an easy means to know definitively one way or another? Geofences can do just that! And may in fact lead to more peace and tranquility for the whole family. :]

“What’s a geofence?” I hear you ask – it’s nothing more than a virtual perimeter around a specified geographic location, which can be monitored and used to trigger events when its boundaries are crossed.

In this tutorial, you’ll build an Android app named “AWTY?” which uses GoogleApiClient, a component of Google Play Services, to add geofences. Your users will be able to enter a name, location, and size for a desired geofence. When entering the geofence, your users will get an Android notification of a geofence crossing.

Note: If you are new to Android development and have any questions about the starter project or using Android Studio, it may help to check out some of the tutorials on Android development found on this site.

Getting Started

Download the starter project for this tutorial. This project was created using Android Studio 1.2.

Fire up Android Studio, and choose either Open an existing Android Studio project or File\Open…, then navigate to and select the downloaded project folder. Once the project is open, you may need to select View\Tool Windows\Project to see the project files in the Project pane.

There are seven source code files in the starter project; take a moment to familiarize yourself with them:

  • AddGeofenceFragment.java: a DialogFragment used to create a geofence.
  • AllGeofencesActivity.java: an ActionBarActivity that displays a single fragment.
  • AllGeofencesAdapter.java: a RecyclerView adapter that transforms geofences to instances of CardView.
  • AllGeofencesFragment.java: a Fragment that displays geofences in a RecyclerView.
  • AreWeThereIntentService.java: an IntentService that will send a notification to the user when they enter a geofence.
  • Constants.java: a class to hold some static constants.
  • NamedGeofence.java: a model class that will be used to serialize the geofences.

The view-related classes have ViewHolder inner classes containing the associated views. Each of the res subfolders has a number of other resource files that define colors, strings, dimensions, and styles; res/layout has files for each of the activity and fragment classes. Finally, the listitem_geofence.xml layout file defines the CardView that will be used to display geofences.

The following build settings have been specified in build.gradle, and you should make sure you have the corresponding Android SDK packages installed:

  • minSdkVersion: 16
  • compileSdkversion: 22
  • targetSdkVersion: 22
  • buildToolsVersion: 22.0.1

Finally, note the dependencies for the starter project defined in build.gradle; the app includes the CardView and RecyclerView classes from the Android Support Library along with two third-party libraries: Gson, for serializing objects to JSON, and FAB, a library used to display a floating action button.

Note: If you are unsure how to check which SDKs you have installed, or how to install an SDK, then please review the tutorials I linked to above.

AWTY-kid

Running the Starter Project

Time to run up your app to see how it looks in its current state. Testing geofences on a physical device is best, but if need be, you can run the app on the Android emulator. Doing so requires an emulator setup with Google Play Services installed.

To create a new emulator that will work with Google Play Services, choose Tools\Android\AVD Manager from the Android Studio menu. Next choose the Create Virtual Device… button in the lower left:

AWTY-AVD

Select the Nexus 5, and choose Next:

AWTY-AVDHardware

On the next screen, choose an API Level of 22 as this is the latest version at time of writing. For the best emulator performance, use an ABI of x86 or x86_64 if you have HAXM installed. If you don’t have HAXM, choose armebi-v7a for the ABI. Also, to use geofences in the emulator you must choose a target with Google APIs to ensure that Google Play Services are available:

AWTY-AVDTarget

Note: For more information on using an emulator with HAXM, check out this Intel document on HAXM.

Once you’ve selected your system image, click Finish in the lower right:

AWTY-AVDFinish

To test your new emulator, go back to the AVD Manager and hit play on the emulator you just created:

AWTY-AVDPlay

Press Ctrl-R or click the run button in the Android Studio toolbar to ensure the starter app builds and runs successfully:

AWTY-EmptyState

Now that you’ve successfully launched the starter project, you can begin building out the full app. Time to start tracking your users…no, not really. Promise you’ll never, ever do that! :]

Working with GoogleApiClient

With the December 2014 release of Google Play Services 6.5, geofences are now created using GoogleApiClient. The Location package is one of the dependencies listed in build.gradle:

dependencies {
  compile fileTree(dir: 'libs', include: ['*.jar'])
  compile 'com.android.support:appcompat-v7:22.0.0'
  compile 'com.android.support:cardview-v7:22.0.0'
  compile 'com.android.support:recyclerview-v7:22.0.0'

  compile 'com.google.code.gson:gson:2.3'
  compile 'com.github.shell-software:fab:1.0.5'

  compile 'com.google.android.gms:play-services-location:6.5.87'
}

While there are versions of Google Play Services higher than 6.5.87, this is a version that most of your users’ devices should have.

If you’ve never installed Google Play Services, go to Tools\Android\SDK Manager to open the Android SDK Manager and install the requisite library:

AWTY-GooglePlayServices

Creating Geofence Objects

The NamedGeofence class stores geofence data in primitives, but you will also use it to create Geofence objects.

Add the following public method to the class:

public Geofence geofence() {
  id = UUID.randomUUID().toString();
  return new Geofence.Builder()
    .setRequestId(id)
    .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER)
    .setCircularRegion(latitude, longitude, radius)
    .setExpirationDuration(Geofence.NEVER_EXPIRE)
    .build();
}

The above method uses the Builder pattern to instantiate a new geofence object. You first create a unique id for the geofence and then build a geofence based on the values in NamedGeofence. The geofence type is specified as GEOFENCE_TRANSITION_ENTER, and the geofence is set to never expire.

Note: Beyond the basic properties of location (in terms of latitude and longitude) and size (usually given as a radius), geofences can have a fixed lifespan, or stay active with no expiration.

Geofences can be defined as entry, which triggers when the user enters the fence; exit, when the user leaves the fence; dwell, where the user stays inside the fence for a certain length of time period, or even a combination of these three.

In this tutorial, you’ll stick with creating entry geofences.

Now that you have a way to create Geofence objects, it’s time to create a companion controller class.

Contributors

Over 300 content creators. Join our team.