Skip to content

Most visited

Recently visited


Creating and Monitoring Geofences

Geofencing combines awareness of the user's current location with awareness of the user's proximity to locations that may be of interest. To mark a location of interest, you specify its latitude and longitude. To adjust the proximity for the location, you add a radius. The latitude, longitude, and radius define a geofence, creating a circular area, or fence, around the location of interest.

You can have multiple active geofences, with a limit of 100 per device user. For each geofence, you can ask Location Services to send you entrance and exit events, or you can specify a duration within the geofence area to wait, or dwell, before triggering an event. You can limit the duration of any geofence by specifying an expiration duration in milliseconds. After the geofence expires, Location Services automatically removes it.

This lesson shows you how to add and remove geofences, and then listen for geofence transitions using an IntentService.

Set up for Geofence Monitoring

The first step in requesting geofence monitoring is to request the necessary permission. To use geofencing, your app must request ACCESS_FINE_LOCATION. To request this permission, add the following element as a child element of the <manifest> element in your app manifest:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

If you want to use an IntentService to listen for geofence transitions, add an element specifying the service name. This element must be a child of the <application> element:

   <service android:name=".GeofenceTransitionsIntentService"/>

To access the location APIs, you need to create an instance of the Geofencing client. To learn how to connect your client:

private GeofencingClient mGeofencingClient;

// ...

mGeofencingClient = LocationServices.getGeofencingClient(this);

Create and Add Geofences

Your app needs to create and add geofences using the location API's builder class for creating Geofence objects, and the convenience class for adding them. Also, to handle the intents sent from Location Services when geofence transitions occur, you can define a PendingIntent as shown in this section.

Note: On single-user devices, there is a limit of 100 geofences per app. For multi-user devices, the limit is 100 geofences per app per device user.

Create geofence objects

First, use Geofence.Builder to create a geofence, setting the desired radius, duration, and transition types for the geofence. For example, to populate a list object named mGeofenceList:

mGeofenceList.add(new Geofence.Builder()
    // Set the request ID of the geofence. This is a string to identify this
    // geofence.

    .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER |

This example pulls data from a constants file. In actual practice, apps might dynamically create geofences based on the user's location.

Specify geofences and initial triggers

The following snippet uses the GeofencingRequest class and its nested GeofencingRequestBuilder class to specify the geofences to monitor and to set how related geofence events are triggered:

private GeofencingRequest getGeofencingRequest() {
    GeofencingRequest.Builder builder = new GeofencingRequest.Builder();

This example shows the use of two geofence triggers. The GEOFENCE_TRANSITION_ENTER transition triggers when a device enters a geofence, and the GEOFENCE_TRANSITION_EXIT transition triggers when a device exits a geofence. Specifying INITIAL_TRIGGER_ENTER tells Location services that GEOFENCE_TRANSITION_ENTER should be triggered if the the device is already inside the geofence.

In many cases, it may be preferable to use instead INITIAL_TRIGGER_DWELL, which triggers events only when the user stops for a defined duration within a geofence. This approach can help reduce "alert spam" resulting from large numbers notifications when a device briefly enters and exits geofences. Another strategy for getting best results from your geofences is to set a minimum radius of 100 meters. This helps account for the location accuracy of typical Wi-Fi networks, and also helps reduce device power consumption.

Define an Intent for geofence transitions

The Intent sent from Location Services can trigger various actions in your app, but you should not have it start an activity or fragment, because components should only become visible in response to a user action. In many cases, an IntentService is a good way to handle the intent. An IntentService can post a notification, do long-running background work, send intents to other services, or send a broadcast intent. The following snippet shows how to define a PendingIntent that starts an IntentService:

public class MainActivity extends AppCompatActivity {

    // ...

    private PendingIntent getGeofencePendingIntent() {
        // Reuse the PendingIntent if we already have it.
        if (mGeofencePendingIntent != null) {
            return mGeofencePendingIntent;
        Intent intent = new Intent(this, GeofenceTransitionsIntentService.class);
        // We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when
        // calling addGeofences() and removeGeofences().
        mGeofencePendingIntent = PendingIntent.getService(this, 0, intent, PendingIntent.
        return mGeofencePendingIntent;

Add geofences

To add geofences, use the GeofencingClient.addGeofences() method. Provide the GeofencingRequest object, and the PendingIntent. The following snippet demonstrates processing the results:

mGeofencingClient.addGeofences(getGeofencingRequest(), getGeofencePendingIntent())
        .addOnSuccessListener(this, new OnSuccessListener<Void>() {
            public void onSuccess(Void aVoid) {
                // Geofences added
                // ...
        .addOnFailureListener(this, new OnFailureListener() {
            public void onFailure(@NonNull Exception e) {
                // Failed to add geofences
                // ...

Handle Geofence Transitions

When Location Services detects that the user has entered or exited a geofence, it sends out the Intent contained in the PendingIntent you included in the request to add geofences. This Intent is received by a service like GeofenceTransitionsIntentService, which obtains the geofencing event from the intent, determines the type of Geofence transition(s), and determines which of the defined geofences was triggered. It then sends a notification as the output.

Note: On Android 8.0 (API level 26) and higher, if an app is running in the background while monitoring a geofence, then the device responds to geofencing events every couple of minutes. To learn how to adapt your app to these response limits, see Background Location Limits.

The following snippet shows how to define an IntentService that posts a notification when a geofence transition occurs. When the user clicks the notification, the app's main activity appears:

public class GeofenceTransitionsIntentService extends IntentService {
    // ...
    protected void onHandleIntent(Intent intent) {
        GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
        if (geofencingEvent.hasError()) {
            String errorMessage = GeofenceErrorMessages.getErrorString(this,
            Log.e(TAG, errorMessage);

        // Get the transition type.
        int geofenceTransition = geofencingEvent.getGeofenceTransition();

        // Test that the reported transition was of interest.
        if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER ||
                geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) {

            // Get the geofences that were triggered. A single event can trigger
            // multiple geofences.
            List<Geofence> triggeringGeofences = geofencingEvent.getTriggeringGeofences();

            // Get the transition details as a String.
            String geofenceTransitionDetails = getGeofenceTransitionDetails(

            // Send notification and log the transition details.
            Log.i(TAG, geofenceTransitionDetails);
        } else {
            // Log the error.
            Log.e(TAG, getString(R.string.geofence_transition_invalid_type,

After detecting the transition event via the PendingIntent, this IntentService gets the geofence transition type and tests whether it is one of the events the app uses to trigger notifications -- either GEOFENCE_TRANSITION_ENTER or GEOFENCE_TRANSITION_EXIT in this case. The service then sends a notification and logs the transition details.

Stop Geofence Monitoring

Stopping geofence monitoring when it is no longer needed or desired can help save battery power and CPU cycles on the device. You can stop geofence monitoring in the main activity used to add and remove geofences; removing a geofence stops it immediately. The API provides methods to remove geofences either by request IDs, or by removing geofences associated with a given PendingIntent.

The following snippet removes geofences by PendingIntent, stopping all further notification when the device enters or exits previously added geofences:

        .addOnSuccessListener(this, new OnSuccessListener<Void>() {
            public void onSuccess(Void aVoid) {
                // Geofences removed
                // ...
        .addOnFailureListener(this, new OnFailureListener() {
            public void onFailure(@NonNull Exception e) {
                // Failed to remove geofences
                // ...

You can combine geofencing with other location-aware features, such as periodic location updates. For more information, see the other lessons in this class.

Use Best Practices for Geofencing

This section outlines recommendations for using geofencing with the location APIs for Android.

Reduce power consumption

You can use the following techniques to optimize power consumption in your apps that use geofencing:

Choose the optimal radius for your geofence

For best results, the minimium radius of the geofence should be set between 100 - 150 meters. When Wi-Fi is available location accuracy is usually between 20 - 50 meters. When indoor location is available, the accuracy range can be as small as 5 meters. Unless you know indoor location is available inside the geofence, assume that Wi-Fi location accuracy is about 50 meters.

When Wi-Fi location is not available (for example, when you are driving in rural areas) the location accuracy degrades. The accuracy range can be as large as several hundred meters to several kilometers. In cases like this, you should create geofences using a larger radius.

Use the dwell transition type to reduce alert spam

If you receive a large number of alerts when driving briefly past a geofence, the best way to reduce the alerts is to use a transition type of GEOFENCE_TRANSITION_DWELL instead of GEOFENCE_TRANSITION_ENTER. This way, the dwelling alert is sent only when the user stops inside a geofence for a given period of time. You can choose the duration by setting a loitering delay.

Re-register geofences only when required

Registered geofences are kept in the process owned by the package. The app doesn’t need to do anything to handle the following events, because the system restores geofences after these events:

The app must re-register geofences if they're still needed after the following events, since the system cannot recover the geofences in the following cases:

Troubleshoot the Geofence Entrance Event

If geofences are not being triggered when the device enters a geofence (the GEOFENCE_TRANSITION_ENTER alert isn’t triggered), first ensure that your geofences are registered properly as described in this guide.

Here are some possible reasons for alerts not working as expected:

This site uses cookies to store your preferences for site-specific language and display options.

Get the latest Android developer news and tips that will help you find success on Google Play.

* Required Fields


Browse this site in ?

You requested a page in , but your language preference for this site is .

Would you like to change your language preference and browse this site in ? If you want to change your language preference later, use the language menu at the bottom of each page.

This class requires API level or higher

This doc is hidden because your selected API level for the documentation is . You can change the documentation API level with the selector above the left navigation.

For more information about specifying the API level your app requires, read Supporting Different Platform Versions.

Take a short survey?
Help us improve the Android developer experience.
(Sep 2017 survey)