1 page.title=Creating and Monitoring Geofences 2 3 trainingnavtop=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" 54 srcset="{@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"> 62 LocationServices</a> class, which contains the 63 <a href="{@docRoot}reference/com/google/android/gms/location/GeofencingApi.html"> 64 GeofencingApi</a> interface. The 65 <a href="{@docRoot}reference/com/google/android/gms/location/LocationServices.html"> 66 LocationServices</a> class replaces the 67 <a href="{@docRoot}reference/com/google/android/gms/location/LocationClient.html"> 68 LocationClient</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"><manifest></a></code> 77 element in your app manifest: 78 </p> 79 <pre> 80 <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> 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 <application></a></code> element: 88 </p> 89 90 <pre> 91 <application 92 android:allowBackup="true"> 93 ... 94 <service android:name=".GeofenceTransitionsIntentService"/> 95 <application/> 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> 123 mGeofenceList.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> 152 private 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> 198 public 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> 228 public 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> 254 public 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> 317 LocationServices.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 333 APIs for Android.</p> 334 335 <h3>Reduce power consumption</h3> 336 337 <p>You can use the following techniques to optimize power consumption in your apps that use geofencing:</p> 338 339 <ul> 340 <li><p>Set the <a href="{@docRoot}android/reference/com/google/android/gms/location/Geofence.Builder.html#setNotificationResponsiveness(int)"> 341 notification responsiveness</a> to a higher value. Doing so improves power consumption by 342 increasing the latency of geofence alerts. For example, if you set a responsiveness value of five 343 minutes your app only checks for an entrance or exit alert once every five minutes. 344 Setting lower values does not necessarily mean that users will be notified within that time period 345 (for example, if you set a value of 5 seconds it may take a bit longer than that to receive the 346 alert).</p></li> 347 <li><p>Use a larger geofence radius for locations where a user spends a significant amount of time, 348 such as home or work. While a larger radius doesn't directly reduce power consumption, it reduces 349 the frequency at which the app checks for entrance or exit, effectively lowering overall power 350 consumption.</p></li> 351 </ul> 352 353 <h3>Choose the optimal radius for your geofence</h3> 354 <p>For best results, the minimium radius of the geofence should be set between 100 - 150 meters. 355 When Wi-Fi is available location accuracy is usually between 20 - 50 meters. When indoor 356 location is available, the accuracy range can be as small as 5 meters. Unless you know indoor 357 location is available inside the geofence, assume that Wi-Fi location accuracy is about 358 50 meters.</p> 359 360 <p>When Wi-Fi location is not available (for example, when you are driving in rural areas) the 361 location accuracy degrades. The accuracy range can be as large as several hundred meters to 362 several kilometers. In cases like this, you should create geofences using a larger radius.</p> 363 364 <h3>Use the dwell transition type to reduce alert spam</h3> 365 366 <p>If you receive a large number of alerts when driving briefly past a geofence, the best way to 367 reduce the alerts is to use a transition type of <code> 368 <a href="{@docRoot}reference/com/google/android/gms/location/Geofence.html#GEOFENCE_TRANSITION_DWELL"> 369 GEOFENCE_TRANSITION_DWELL</a></code> instead of <code> 370 <a href="{@docRoot}reference/com/google/android/gms/location/Geofence.html#GEOFENCE_TRANSITION_ENTER"> 371 GEOFENCE_TRANSITION_ENTER</a></code>. This way, the dwelling alert is sent only when the user stops 372 inside a geofence for a given period of time. You can choose the duration by setting a 373 <a href="{@docRoot}reference/com/google/android/gms/location/Geofence.Builder.html#setLoiteringDelay(int)"> 374 loitering delay</a>.</p> 375 376 <h3>Re-register geofences only when required</h3> 377 378 <p>Registered geofences are kept in the <code>com.google.process.location</code> process owned by 379 the <code>com.google.android.gms</code> package. 380 The app doesnt need to do anything to handle the following events, because the system 381 restores geofences after these events:</p> 382 <ul> 383 <li>Google Play services is upgraded.</li> 384 <li>Google Play services is killed and restarted by the system due resource restriction.</li> 385 <li>The location process crashes.</li> 386 </ul> 387 <p>The app must re-register geofences if they're still needed after the following events, since 388 the system cannot recover the geofences in the following cases:</p> 389 390 <ul> 391 <li>The device is rebooted. The app should listen for the device's boot complete action, and then re- 392 register the geofences required.</li> 393 <li>The app is uninstalled and re-installed.</li> 394 <li>The app's data is cleared.</li> 395 <li>Google Play services data is cleared.</li> 396 <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> 397 alert. This typically happens 398 after NLP (Android's Network Location Provider) is disabled.</li> 399 </ul> 400 401 <h2 id="Troubleshooting">Troubleshoot the Geofence Entrance Event</h2> 402 403 <p>If geofences are not being triggered when the device enters a geofence 404 (the <code><a href="{@docRoot}reference/com/google/android/gms/location/Geofence.html#GEOFENCE_TRANSITION_ENTER"> 405 GEOFENCE_TRANSITION_ENTER</a></code> alert isnt triggered), first ensure that your geofences are 406 registered properly as described in this guide.</p> 407 408 <p>Here are some possible reasons for alerts not working as expected:</p> 409 410 <ul> 411 <li><strong>Accurate location is not available inside your geofence or your geofence is too 412 small.</strong> On most devices, the geofence service uses only network location for geofence 413 triggering. The service uses this approach because network location consumes much less 414 power, it takes less time to get discrete locations, and most importantly its available indoors. 415 Starting with Google Play services 3.2, the geofence service calculates the overlapping ratio of 416 the location circle and the geofence circle and only generates the entrance alert when the ratio 417 is at least 85% for a bigger geofence or 75% for a smaller geofence. For an exit alert, the ratio 418 threshold used is 15% or 25%. Any ratio between these thresholds makes the geofence service mark 419 the geofence state as <code>INSIDE_LOW_CONFIDENCE</code> or <code>OUTSIDE_LOW_CONFIDENCE</code> and 420 no alert is sent.</li> 421 <li><strong>Wi-Fi is turned off on the device.</strong> Having Wi-Fi on can significantly improve 422 the location accuracy, so if Wi-Fi is turned off, your application might never get geofence alerts 423 depending on several settings including the radius of the geofence, the device model, or the 424 Android version. Starting from Android 4.3 (API level 18), we added the capability of Wi-Fi scan 425 only mode which allows users to disable Wi-Fi but still get good network location. Its good 426 practice to prompt the user and provide a shortcut for the user to enable Wi-Fi or Wi-Fi scan only 427 mode if both of them are disabled. Use <a href="{@docRoot}reference/com/google/android/gms/location/SettingsApi"> 428 SettingsApi</a> to ensure that the device's system settings are properly configured for optimal 429 location detection.</li> 430 <li><strong>There is no reliable network connectivity inside your geofence.</strong> If there is 431 no reliable data connection, alerts might not be generated. This is because the geofence service 432 depends on the network location provider which in turn requires a data connection.</li> 433 <li><strong>Alerts can be late.</strong> The geofence service does not continuously query for 434 location, so expect some latency when receiving alerts. Usually the latency is less than 2 435 minutes, even less when the device has been moving. If the device has been stationary for a 436 significant period of time, the latency may increase (up to 6 minutes).</li> 437 </ul> 438