Geofencing API Tutorial for Android
In this geofence tutorial, you’ll learn how to use Android’s Geofencing API to build an app with custom geofences. By Fernando Sproviero.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Geofencing API Tutorial for Android
20 mins
- Getting Started
- Obtaining a Google Maps API Key
- Building and Running the Starter Project
- Creating a Geofence
- Building the Geofence
- Building the Geofence Request
- Building the Geofence Pending Intent
- Checking for Errors
- Handling Transitions
- Creating the Transitions Intent Service
- Testing the Geofences
- Mocking the Location
- Creating a Reminder and Getting the Notification
- Removing a Geofence
- Best Practices
- Responsiveness
- Radius
- Dwell
- Re-registering Your Geofence
- Wi-Fi and Location Accuracy
- Where to Go From Here?
Geofences are a powerful tool in a developer’s arsenal of location tricks to use on Android. Geofences give devices the power to monitor a circular area in the world, and let the device inform you whenever it enters or exits that area.
This has enormous benefits for apps that want to leverage location as a trigger. A retail company could send a special notification to a customer near one of their stores with a special discount to tempt them in. A holiday resort could welcome its customers via its app whenever they enter the resort. With a limit of 100 geofences per device, the possibilities are nearly endless!
In this tutorial on geofencing, you’ll learn how to use Android’s geofencing API to build custom geofences in your very own app called Remind Me There. Let’s get to it!
Getting Started
The project you’ll work with, Remind Me There, is an app to create reminders based on geofences. You’ll set up custom geofences and messages; then, as you travel into a geofenced area, you’ll receive your custom message as a notification on your device.
Use the Download materials button at the top or bottom of this tutorial to download the starter project.
Once downloaded, open the starter project in Android Studio 3.2 or later.
Obtaining a Google Maps API Key
Because this app uses Google Maps, you’ll need to obtain an API key.
Feel free to leave the Project Name as is. You won’t need the name going forward. Leave the default value for Location. Select Create.
- Open Google Cloud Platform and create a new project.
Feel free to leave the Project Name as is. You won’t need the name going forward. Leave the default value for Location. Select Create.
- Select APIs & Services ▸ Library from the navigation menu.
- Select Maps SDK for Android.
- Click Enable, or Manage if already enabled.
- Click on Credentials, Credentials in the API Manager, Create credentials and then choose API key.
- Copy your API key value. In your project, open
debug/res/values/google_maps_api.xml
and replaceYOUR_KEY_HERE
with the copied value.
release/res/values/google_maps_api.xml
.
Building and Running the Starter Project
You can run the sample project on an Android device or emulator. For the emulator, you’ll need to make sure you have an emulator setup with Google APIs in order to show map information.
When you build and run the app, you’ll see the following screens:
Currently, tapping on the + button will let you create the reminder. However, the actual geofence is not yet being created. You’ll write code to create the geofence.
Review the project to get familiar with the files:
- MainActivity.kt: Shows the reminders in a map.
- NewReminderActivity.kt: This activity contains the code to create a new reminder, providing latitude/longitude, radius and a message to be shown in the notification.
- Reminder.kt: A model class used to store the reminder. It has an id, a latitude/longitude, a radius and a message. You’ll use this later to build a geofence.
- ReminderRepository.kt: This file saves the reminders that you create that will be shown in the MainActivity. You’ll also add code to create the geofences, here.
- BaseActivity.kt: This is the parent activity of MainActivity and NewReminderActivity. It provides common access to the ReminderRepository.
- ReminderApp.kt: When the app is launched, it creates the ReminderRepository.
- Utils.kt: Here, you’ll find a few generic functions useful for the app – for example, a function to hide the keyboard, show a notification, etc.
Using geofences requires the play-services-location library added to your project. To do that, open the build.gradle file for the app module and add the following dependency:
implementation 'com.google.android.gms:play-services-location:16.0.0'
Your app also requires the device location to know when to trigger a reminder. You do this by requesting the ACCESS_FINE_LOCATION permission.
This permission is set up in AndroidManifest.xml. It’s classified as a dangerous permission — that is, a permission that could potentially affect the user’s privacy. For Android 6 and later, it’s necessary to check and request this permission during runtime.
Because the starter project shows a map and the user location, the permission and runtime check were both already set up for you in AndroidMainfest.xml and MainActivity.kt.
Creating a Geofence
To manipulate geofences, you need to use the GeofencingClient, so open ReminderRepository.kt and add a new property:
private val geofencingClient = LocationServices.getGeofencingClient(context)
You’ll also need to import com.google.android.gms.location.LocationServices
.
If you look at the add()
method, you’ll see that, currently, it just saves the reminder to SharedPreferences. First, you’ll change this behavior to create the geofence, using the GeofencingClient. Then, only if the geofence creation is successful, you’ll save the reminder to SharedPreferences.
Change the add()
method to the following:
fun add(reminder: Reminder,
success: () -> Unit,
failure: (error: String) -> Unit) {
// 1
val geofence = buildGeofence(reminder)
if (geofence != null
&& ContextCompat.checkSelfPermission(
context,
Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
// 2
geofencingClient
.addGeofences(buildGeofencingRequest(geofence), geofencePendingIntent)
// 3
.addOnSuccessListener {
saveAll(getAll() + reminder)
success()
}
// 4
.addOnFailureListener {
failure("Error")
}
}
}
Use the hotkeys you learned above to import ContextCompat
and Manifest
. Don’t worry about the other errors. Those are methods that you’ll build, soon. Take a minute to have a look at what you have just added:
- You create the geofence model using the data from the reminder.
- You use the GeofencingClient to add the geofence that you’ve just built with a geofencing request and a pending intent. More on this later.
- If the geofence is added successfully, you save the reminder and call the
success
argument. - If there’s an error, you call the
failure
argument (without saving the reminder).
Building the Geofence
A geofence is defined by a latitude, a longitude and a radius. It’s a circular area at a specific location that an app can use to trigger particular behaviors when a device enters, exits or stays for a certain amount of time within geofence boundaries.
You’re going to build a geofence that behaves this way right now. To build your geofence, add the following method to ReminderRepository.kt:
private fun buildGeofence(reminder: Reminder): Geofence? {
val latitude = reminder.latLng?.latitude
val longitude = reminder.latLng?.longitude
val radius = reminder.radius
if (latitude != null && longitude != null && radius != null) {
return Geofence.Builder()
// 1
.setRequestId(reminder.id)
// 2
.setCircularRegion(
latitude,
longitude,
radius.toFloat()
)
// 3
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER)
// 4
.setExpirationDuration(Geofence.NEVER_EXPIRE)
.build()
}
return null
}
Take a look at the Geofence.Builder
code in your new method:
- RequestId: This id uniquely identifies the geofence within your app. You obtain this from the reminder model.
- latitude, longitude and radius: You also get these from the reminder model at the top of the new method.
-
TransitionType: To trigger an event when the user enters the geofence, use
GEOFENCE_TRANSITION_ENTER
. Other options areGEOFENCE_TRANSITION_EXIT
andGEOFENCE_TRANSITION_DWELL
. You can learn more about transition options here. -
ExpirationDuration: Use
NEVER_EXPIRE
so this geofence will exist until the user removes it. The other option is to enter a duration (ms) after which the geofence will expire.