• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1page.title=Creating and Monitoring Geofences
2
3trainingnavtop=true
4@jd:body
5
6
7<div id="tb-wrapper">
8<div id="tb">
9
10<h2>This lesson teaches you to</h2>
11<ol>
12    <li><a href="#RequestGeofences">Set up for Geofence Monitoring</a></li>
13    <li><a href="#CreateAdd">Create and Add Geofences</a></li>
14    <li><a href="#HandleGeofenceTransitions">Handle Geofence Transitions</a></li>
15    <li><a href="#StopGeofenceMonitoring">Stop Geofence Monitoring</a></li>
16    <li><a href="#BestPractices">Use Best Practices for Geofencing</a></li>
17    <li><a href="#Troubleshooting">Troubleshoot the Geofence Entrance Event</a></li>
18</ol>
19
20<h2>You should also read</h2>
21<ul>
22    <li>
23        <a href="{@docRoot}google/play-services/setup.html">Setup Google Play Services SDK</a>
24    </li>
25</ul>
26
27<h2>Try it out</h2>
28
29   <ul>
30      <li>
31        <a href="https://github.com/googlesamples/android-play-location/tree/master/Geofencing"
32        class="external-link">Geofencing</a>
33      </li>
34    </ul>
35
36</div>
37</div>
38<p>
39    Geofencing combines awareness of the user's current location with awareness of the user's
40    proximity to locations that may be of interest. To mark a
41    location of interest, you specify its latitude and longitude. To adjust the proximity for the
42    location, you add a radius. The latitude, longitude, and radius define a geofence, creating a
43    circular area, or fence, around the location of interest.
44</p>
45<p>
46    You can have multiple active geofences, with a limit of 100 per device user. For each geofence,
47    you can ask Location Services to send you entrance and exit events, or you can specify a
48    duration within the geofence area to wait, or <em>dwell</em>, before triggering an event. You
49    can limit the duration of any geofence by specifying an expiration duration in milliseconds.
50    After the geofence expires, Location Services automatically removes it.
51</p>
52
53<img src="{@docRoot}images/training/geofence@2x.png"
54srcset="{@docRoot}images/training/geofence.png 1x, {@docRoot}images/training/geofence@2x.png 2x" alt=""
55  width="400" height="400"/>
56<p>
57    This lesson shows you how to add and remove geofences, and then listen for geofence transitions
58    using an {@link android.app.IntentService}.</p>
59
60<p>We recommend upgrading existing apps to use the
61<a href="{@docRoot}reference/com/google/android/gms/location/LocationServices.html">
62LocationServices</a> class, which contains the
63<a href="{@docRoot}reference/com/google/android/gms/location/GeofencingApi.html">
64GeofencingApi</a> interface. The
65<a href="{@docRoot}reference/com/google/android/gms/location/LocationServices.html">
66LocationServices</a> class replaces the
67<a href="{@docRoot}reference/com/google/android/gms/location/LocationClient.html">
68LocationClient</a> (deprecated).</p>
69
70<h2 id="RequestGeofences">Set up for Geofence Monitoring</h2>
71<p>
72    The first step in requesting geofence monitoring is to request the necessary permission.
73    To use geofencing, your app must request
74    {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION}. To request this
75    permission, add the following element as a child element of the
76<code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code>
77    element in your app manifest:
78</p>
79<pre>
80&lt;uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/&gt;
81</pre>
82
83<p>
84    If you want to use an {@link android.app.IntentService} to listen for geofence transitions,
85    add an element specifying the service name. This element must be
86    a child of the <code><a href="{@docRoot}guide/topics/manifest/application-element.html">
87    &lt;application&gt;</a></code> element:
88</p>
89
90<pre>
91&lt;application
92   android:allowBackup=&quot;true&quot;&gt;
93   ...
94   &lt;service android:name=".GeofenceTransitionsIntentService"/&gt;
95&lt;application/&gt;
96</pre>
97
98<p>To access the location APIs, you need to create an instance of the
99  Google Play services API client. To learn how to connect your client, see
100  <a href="{@docRoot}training/location/retrieve-current.html#play-services">Connect
101  to Google Play Services</a>.</p>
102
103<h2 id="CreateAdd">Create and Add Geofences</h2>
104
105<p>Your app needs to create and add geofences using the location API's builder class for
106 creating Geofence objects, and the convenience class for adding them. Also, to handle the
107 intents sent from Location Services when geofence transitions occur, you can define a
108 {@link android.app.PendingIntent} as shown in this section.
109</p>
110
111<p class="note"><strong>Note:</strong> 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.</p>
112
113<h3>Create geofence objects</h3>
114
115<p>
116    First, use <code><a href="{@docRoot}reference/com/google/android/gms/location/Geofence.Builder.html">
117    Geofence.Builder</a></code> to create a geofence, setting the desired radius, duration, and
118    transition types for the geofence. For example, to populate a list object named
119    {@code mGeofenceList}:
120    </p>
121
122<pre>
123mGeofenceList.add(new Geofence.Builder()
124    // Set the request ID of the geofence. This is a string to identify this
125    // geofence.
126    .setRequestId(entry.getKey())
127
128    .setCircularRegion(
129            entry.getValue().latitude,
130            entry.getValue().longitude,
131            Constants.GEOFENCE_RADIUS_IN_METERS
132    )
133    .setExpirationDuration(Constants.GEOFENCE_EXPIRATION_IN_MILLISECONDS)
134    .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER |
135            Geofence.GEOFENCE_TRANSITION_EXIT)
136    .build());
137</pre>
138
139<p>This example pulls data from a constants file. In actual practice, apps might
140    dynamically create geofences based on the user's location.</p>
141
142<h3>Specify geofences and initial triggers</h3>
143
144<p>
145    The following snippet uses the <code><a href="{@docRoot}reference/com/google/android/gms/location/GeofencingRequest.html">
146    GeofencingRequest</a></code> class
147    and its nested <code><a href="{@docRoot}reference/com/google/android/gms/location/GeofencingRequest.Builder.html">
148    GeofencingRequestBuilder</a></code> class to
149    specify the geofences to monitor and to set how related geofence events are triggered:
150</p>
151<pre>
152private GeofencingRequest getGeofencingRequest() {
153    GeofencingRequest.Builder builder = new GeofencingRequest.Builder();
154    builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER);
155    builder.addGeofences(mGeofenceList);
156    return builder.build();
157}
158</pre>
159
160<p>
161    This example shows the use of two geofence triggers. The <code>
162<a href="{@docRoot}reference/com/google/android/gms/location/Geofence.html#GEOFENCE_TRANSITION_ENTER">
163    GEOFENCE_TRANSITION_ENTER</a></code>
164    transition triggers when a device enters a geofence, and the <code>
165<a href="{@docRoot}reference/com/google/android/gms/location/Geofence.html#GEOFENCE_TRANSITION_EXIT">
166    GEOFENCE_TRANSITION_EXIT</a></code>
167    transition triggers when a device exits a geofence. Specifying
168    <code>
169<a href="{@docRoot}reference/com/google/android/gms/location/GeofencingRequest.html#INITIAL_TRIGGER_ENTER">
170        INITIAL_TRIGGER_ENTER</a></code> tells Location services that
171    <code>
172<a href="{@docRoot}reference/com/google/android/gms/location/Geofence.html#GEOFENCE_TRANSITION_ENTER">
173        GEOFENCE_TRANSITION_ENTER</a></code>
174    should be triggered if the the device is already inside the geofence.</p>
175</p>
176
177<p>In many cases, it may be preferable to use instead <code>
178<a href="{@docRoot}reference/com/google/android/gms/location/GeofencingRequest.html#INITIAL_TRIGGER_DWELL">
179    INITIAL_TRIGGER_DWELL</a></code>,
180    which triggers events only when the user stops for a defined duration within a geofence.
181    This approach can help reduce "alert spam" resulting from large numbers notifications when a
182    device briefly enters and exits geofences. Another strategy for getting best results from your
183    geofences is to set a minimum radius of 100 meters. This helps account for the location accuracy
184    of typical Wi-Fi networks, and also helps reduce device power consumption.
185</p>
186
187<h3>Define an Intent for geofence transitions</h3>
188<p>
189    The {@link android.content.Intent} sent from Location Services can trigger various actions in
190    your app, but you should <i>not</i> have it start an activity or fragment, because components
191    should only become visible in response to a user action. In many cases, an
192    {@link android.app.IntentService} is a good way to handle the intent. An
193    {@link android.app.IntentService} can post a notification, do long-running background work,
194    send intents to other services, or send a broadcast intent. The following snippet shows how
195    to define a {@link android.app.PendingIntent} that starts an {@link android.app.IntentService}:
196</p>
197<pre>
198public class MainActivity extends FragmentActivity {
199    ...
200    private PendingIntent getGeofencePendingIntent() {
201        // Reuse the PendingIntent if we already have it.
202        if (mGeofencePendingIntent != null) {
203            return mGeofencePendingIntent;
204        }
205        Intent intent = new Intent(this, GeofenceTransitionsIntentService.class);
206        // We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when
207        // calling addGeofences() and removeGeofences().
208        return PendingIntent.getService(this, 0, intent, PendingIntent.
209                FLAG_UPDATE_CURRENT);
210    }
211</pre>
212
213<h3>Add geofences</h3>
214
215<p>
216    To add geofences, use the <code>
217<a href="{@docRoot}reference/com/google/android/gms/location/GeofencingApi.html#addGeofences(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.location.GeofencingRequest, android.app.PendingIntent)">{@code GeoencingApi.addGeofences()}</a></code> method.
218    Provide the Google API client, the <code>
219<a href="{@docRoot}reference/com/google/android/gms/location/GeofencingRequest">
220    GeofencingRequest</a></code> object, and the {@link android.app.PendingIntent}.
221    The following snippet, which processes the results in <code>
222<a href="{@docRoot}reference/com/google/android/gms/common/api/ResultCallback.html#onResult(R)">
223    onResult()</a></code>, assumes that the main activity implements <code>
224<a href="{@docRoot}reference/com/google/android/gms/common/api/ResultCallback.html">
225    ResultCallback</a></code>:
226</p>
227<pre>
228public class MainActivity extends FragmentActivity {
229    ...
230    LocationServices.GeofencingApi.addGeofences(
231                mGoogleApiClient,
232                getGeofencingRequest(),
233                getGeofencePendingIntent()
234        ).setResultCallback(this);
235</pre>
236
237
238<h2 id="HandleGeofenceTransitions">Handle Geofence Transitions</h2>
239<p>
240    When Location Services detects that the user has entered or exited a geofence, it
241    sends out the {@link android.content.Intent} contained in the {@link android.app.PendingIntent}
242    you included in the request to add geofences. This {@link android.content.Intent} is received
243    by a service like <code>GeofenceTransitionsIntentService</code>,
244    which obtains the geofencing event from the intent, determines the type of Geofence transition(s),
245    and determines which of the defined geofences was triggered. It then sends a notification as
246    the output.
247</p>
248<p>
249    The following snippet shows how to define an {@link android.app.IntentService} that posts a
250    notification when a geofence transition occurs. When the user clicks the notification, the
251    app's main activity appears:
252</p>
253<pre>
254public class GeofenceTransitionsIntentService extends IntentService {
255   ...
256    protected void onHandleIntent(Intent intent) {
257        GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
258        if (geofencingEvent.hasError()) {
259            String errorMessage = GeofenceErrorMessages.getErrorString(this,
260                    geofencingEvent.getErrorCode());
261            Log.e(TAG, errorMessage);
262            return;
263        }
264
265        // Get the transition type.
266        int geofenceTransition = geofencingEvent.getGeofenceTransition();
267
268        // Test that the reported transition was of interest.
269        if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER ||
270                geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) {
271
272            // Get the geofences that were triggered. A single event can trigger
273            // multiple geofences.
274            List<Geofence> triggeringGeofences = geofencingEvent.getTriggeringGeofences();
275
276            // Get the transition details as a String.
277            String geofenceTransitionDetails = getGeofenceTransitionDetails(
278                    this,
279                    geofenceTransition,
280                    triggeringGeofences
281            );
282
283            // Send notification and log the transition details.
284            sendNotification(geofenceTransitionDetails);
285            Log.i(TAG, geofenceTransitionDetails);
286        } else {
287            // Log the error.
288            Log.e(TAG, getString(R.string.geofence_transition_invalid_type,
289                    geofenceTransition));
290        }
291    }
292</pre>
293
294<p>After detecting the transition event via the {@link android.app.PendingIntent},
295    this {@link android.app.IntentService} gets the geofence transition type and tests whether
296    it is one of the events the app uses to trigger notifications -- either
297    <code><a href="{@docRoot}reference/com/google/android/gms/location/Geofence.html#GEOFENCE_TRANSITION_ENTER">GEOFENCE_TRANSITION_ENTER</a></code>
298     or <code><a href="{@docRoot}reference/com/google/android/gms/location/Geofence.html#GEOFENCE_TRANSITION_EXIT">GEOFENCE_TRANSITION_EXIT</a></code>
299    in this case. The service then sends a notification and logs the transition details.</p>
300<!--
301    Remove Geofences
302 -->
303<h2 id="StopGeofenceMonitoring">Stop Geofence Monitoring</h2>
304
305<p>Stopping geofence monitoring when it is no longer needed or desired can help save battery
306    power and CPU cycles on the device. You can stop geofence monitoring
307    in the main activity used to add and remove geofences; removing a geofence stops it
308    immediately. The API provides methods to
309    remove geofences either by request IDs, or by removing geofences associated with a given
310    {@link android.app.PendingIntent}.
311</p>
312<p>
313    The following snippet removes geofences by {@link android.app.PendingIntent}, stopping all
314    further notification when the device enters or exits previously added geofences:
315</p>
316<pre>
317LocationServices.GeofencingApi.removeGeofences(
318            mGoogleApiClient,
319            // This is the same pending intent that was used in addGeofences().
320            getGeofencePendingIntent()
321    ).setResultCallback(this); // Result processed in onResult().
322}
323</pre>
324
325<p>
326    You can combine geofencing with other location-aware features, such as periodic location updates.
327    For more information, see the other lessons in this class.
328</p>
329
330<h2 id="BestPractices">Use Best Practices for Geofencing</h2>
331
332<p>This section outlines recommendations for using geofencing with the location
333APIs for Android.</p>
334
335<h3>
336  Reduce power consumption
337</h3>
338
339<p>
340  You can use the following techniques to optimize power consumption in your
341  apps that use geofencing:
342</p>
343
344<ul>
345  <li>
346    <p>
347      Set the <a href=
348      "https://developers.google.com/android/reference/com/google/android/gms/location/Geofence.Builder.html#setNotificationResponsiveness(int)">
349      notification responsiveness</a> to a higher value. Doing so improves
350      power consumption by increasing the latency of geofence alerts. For
351      example, if you set a responsiveness value of five minutes your app only
352      checks for an entrance or exit alert once every five minutes. Setting
353      lower values does not necessarily mean that users will be notified
354      within that time period (for example, if you set a value of 5 seconds it
355      may take a bit longer than that to receive the alert).
356    </p>
357  </li>
358
359  <li>
360    <p>
361      Use a larger geofence radius for locations where a user spends a
362      significant amount of time, such as home or work. While a larger radius
363      doesn't directly reduce power consumption, it reduces the frequency at
364      which the app checks for entrance or exit, effectively lowering overall
365      power consumption.
366    </p>
367  </li>
368</ul>
369
370<h3>Choose the optimal radius for your geofence</h3>
371<p>For best results, the minimium radius of the geofence should be set between 100 - 150 meters.
372When Wi-Fi is available location accuracy is usually between 20 - 50 meters. When indoor
373location is available, the accuracy range can be as small as 5 meters. Unless you know indoor
374location is available inside the geofence, assume that Wi-Fi location accuracy is about
37550 meters.</p>
376
377<p>When Wi-Fi location is not available (for example, when you are driving in rural areas) the
378location accuracy degrades. The accuracy range can be as large as several hundred meters to
379several kilometers. In cases like this, you should create geofences using a larger radius.</p>
380
381<h3>Use the dwell transition type to reduce alert spam</h3>
382
383<p>If you receive a large number of alerts when driving briefly past a geofence, the best way to
384reduce the alerts is to use a transition type of <code>
385<a href="{@docRoot}reference/com/google/android/gms/location/Geofence.html#GEOFENCE_TRANSITION_DWELL">
386GEOFENCE_TRANSITION_DWELL</a></code> instead of <code>
387<a href="{@docRoot}reference/com/google/android/gms/location/Geofence.html#GEOFENCE_TRANSITION_ENTER">
388GEOFENCE_TRANSITION_ENTER</a></code>. This way, the dwelling alert is sent only when the user stops
389inside a geofence for a given period of time. You can choose the duration by setting a
390<a href="{@docRoot}reference/com/google/android/gms/location/Geofence.Builder.html#setLoiteringDelay(int)">
391loitering delay</a>.</p>
392
393<h3>Re-register geofences only when required</h3>
394
395<p>Registered geofences are kept in the <code>com.google.process.location</code> process owned by
396the <code>com.google.android.gms</code> package.
397The app doesn’t need to do anything to handle the following events, because the system
398restores geofences after these events:</p>
399<ul>
400<li>Google Play services is upgraded.</li>
401<li>Google Play services is killed and restarted by the system due resource restriction.</li>
402<li>The location process crashes.</li>
403</ul>
404<p>The app must re-register geofences if they're still needed after the following events, since
405the system cannot recover the geofences in the following cases:</p>
406
407<ul>
408<li>The device is rebooted. The app should listen for the device's boot complete action, and then re-
409register the geofences required.</li>
410<li>The app is uninstalled and re-installed.</li>
411<li>The app's data is cleared.</li>
412<li>Google Play services data is cleared.</li>
413<li>The app has received a <code><a href="{@docRoot}reference/com/google/android/gms/location/LocationStatusCodes.html#GEOFENCE_NOT_AVAILABLE">GEOFENCE_NOT_AVAILABLE</a></code>
414alert. This typically happens
415after NLP (Android's Network Location Provider) is disabled.</li>
416</ul>
417
418<h2 id="Troubleshooting">Troubleshoot the Geofence Entrance Event</h2>
419
420<p>If geofences are not being triggered when the device enters a geofence
421(the <code><a href="{@docRoot}reference/com/google/android/gms/location/Geofence.html#GEOFENCE_TRANSITION_ENTER">
422GEOFENCE_TRANSITION_ENTER</a></code> alert isn’t triggered), first ensure that your geofences are
423registered properly as described in this guide.</p>
424
425<p>Here are some possible reasons for alerts not working as expected:</p>
426
427<ul>
428<li><strong>Accurate location is not available inside your geofence or your geofence is too
429small.</strong> On most devices, the geofence service uses only network location for geofence
430triggering. The service uses this approach because network location consumes much less
431power, it takes less time to get discrete locations, and most importantly it’s available indoors.
432Starting with Google Play services 3.2, the geofence service calculates the overlapping ratio of
433the location circle and the geofence circle and only generates the entrance alert when the ratio
434is at least 85% for a bigger geofence or 75% for a smaller geofence. For an exit alert, the ratio
435threshold used is 15% or 25%. Any ratio between these thresholds makes the geofence service mark
436the geofence state as <code>INSIDE_LOW_CONFIDENCE</code> or <code>OUTSIDE_LOW_CONFIDENCE</code> and
437no alert is sent.</li>
438<li><strong>Wi-Fi is turned off on the device.</strong> Having Wi-Fi on can significantly improve
439the location accuracy, so if Wi-Fi is turned off, your application might never get geofence alerts
440depending on several settings including the radius of the geofence, the device model, or the
441Android version. Starting from Android 4.3 (API level 18), we added the capability of “Wi-Fi scan
442only mode” which allows users to disable Wi-Fi but still get good network location. It’s good
443practice to prompt the user and provide a shortcut for the user to enable Wi-Fi or Wi-Fi scan only
444mode if both of them are disabled. Use <a href="{@docRoot}reference/com/google/android/gms/location/SettingsApi">
445SettingsApi</a> to ensure that the device's system settings are properly configured for optimal
446location detection.</li>
447<li><strong>There is no reliable network connectivity inside your geofence.</strong> If there is
448no reliable data connection, alerts might not be generated. This is because the geofence service
449depends on the network location provider which in turn requires a data connection.</li>
450<li><strong>Alerts can be late.</strong> The geofence service does not continuously query for
451location, so expect some latency when receiving alerts. Usually the latency is less than 2
452minutes, even less when the device has been moving. If the device has been stationary for a
453significant period of time, the latency may increase (up to 6 minutes).</li>
454</ul>
455