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> 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. 372 When Wi-Fi is available location accuracy is usually between 20 - 50 meters. When indoor 373 location is available, the accuracy range can be as small as 5 meters. Unless you know indoor 374 location is available inside the geofence, assume that Wi-Fi location accuracy is about 375 50 meters.</p> 376 377 <p>When Wi-Fi location is not available (for example, when you are driving in rural areas) the 378 location accuracy degrades. The accuracy range can be as large as several hundred meters to 379 several 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 384 reduce 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"> 386 GEOFENCE_TRANSITION_DWELL</a></code> instead of <code> 387 <a href="{@docRoot}reference/com/google/android/gms/location/Geofence.html#GEOFENCE_TRANSITION_ENTER"> 388 GEOFENCE_TRANSITION_ENTER</a></code>. This way, the dwelling alert is sent only when the user stops 389 inside 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)"> 391 loitering 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 396 the <code>com.google.android.gms</code> package. 397 The app doesnt need to do anything to handle the following events, because the system 398 restores 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 405 the 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- 409 register 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> 414 alert. This typically happens 415 after 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"> 422 GEOFENCE_TRANSITION_ENTER</a></code> alert isnt triggered), first ensure that your geofences are 423 registered 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 429 small.</strong> On most devices, the geofence service uses only network location for geofence 430 triggering. The service uses this approach because network location consumes much less 431 power, it takes less time to get discrete locations, and most importantly its available indoors. 432 Starting with Google Play services 3.2, the geofence service calculates the overlapping ratio of 433 the location circle and the geofence circle and only generates the entrance alert when the ratio 434 is at least 85% for a bigger geofence or 75% for a smaller geofence. For an exit alert, the ratio 435 threshold used is 15% or 25%. Any ratio between these thresholds makes the geofence service mark 436 the geofence state as <code>INSIDE_LOW_CONFIDENCE</code> or <code>OUTSIDE_LOW_CONFIDENCE</code> and 437 no alert is sent.</li> 438 <li><strong>Wi-Fi is turned off on the device.</strong> Having Wi-Fi on can significantly improve 439 the location accuracy, so if Wi-Fi is turned off, your application might never get geofence alerts 440 depending on several settings including the radius of the geofence, the device model, or the 441 Android version. Starting from Android 4.3 (API level 18), we added the capability of Wi-Fi scan 442 only mode which allows users to disable Wi-Fi but still get good network location. Its good 443 practice to prompt the user and provide a shortcut for the user to enable Wi-Fi or Wi-Fi scan only 444 mode if both of them are disabled. Use <a href="{@docRoot}reference/com/google/android/gms/location/SettingsApi"> 445 SettingsApi</a> to ensure that the device's system settings are properly configured for optimal 446 location detection.</li> 447 <li><strong>There is no reliable network connectivity inside your geofence.</strong> If there is 448 no reliable data connection, alerts might not be generated. This is because the geofence service 449 depends 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 451 location, so expect some latency when receiving alerts. Usually the latency is less than 2 452 minutes, even less when the device has been moving. If the device has been stationary for a 453 significant period of time, the latency may increase (up to 6 minutes).</li> 454 </ul> 455