Optimize location use for real-world scenarios

This section describes some typical location-gathering scenarios, along with recommendations for optimal use of the geofencing and fused location provider APIs.

User visible or foreground updates

Example: A mapping app that needs frequent, accurate updates with very low latency. All updates happen in the foreground: the user starts an activity, consumes location data, and then stops the activity after a short time.

Use the setPriority() method with a value of PRIORITY_HIGH_ACCURACY or PRIORITY_BALANCED_POWER_ACCURACY.

The interval specified in the setInterval() method depends on the use case: for real time scenarios, set the value to few seconds; otherwise, limit to a few minutes (approximately two minutes or greater is recommended to minimize battery usage).

Know the location of the device

Example: A weather app wants to know the device's location.

Use the getLastLocation() method, which returns the most recently available location (which in rare cases may be null). This method provides a straightforward way of getting location and doesn't incur costs associated with actively requesting location updates. Use in conjunction with the isLocationAvailable() method, which returns true when the location returned by getLastLocation() is reasonably up-to-date.

Start updates when a user is at a specific location

Example: Requesting updates when a user is within a certain distance of work, home, or another location.

Use geofencing in conjunction with fused location provider updates. Request updates when the app receives a geofence entrance trigger, and remove updates when the app receives a geofence exit trigger. This ensures that the app gets more granular location updates only when the user has entered a defined area.

The typical workflow for this scenario could involve surfacing a notification upon the geofence enter transition, and launching an activity which contains code to request updates when the user taps the notification.

Start updates based on the user's activity state

Example: Requesting updates only when the user is driving or riding a bike.

Use the Activity Recognition API in conjunction with fused location provider updates. Request updates when the targeted activity is detected, and remove updates when the user stops performing that activity.

The typical workflow for this use case could involve surfacing a notification for the detected activity, and launching an activity which contains code to request updates when the user taps the notification.

Long running background location updates tied to geographical areas

Example: The user wants to be notified when the device is within proximity of a retailer.

This is an excellent use case for geofencing. Because the use case almost certainly involves background location, use the addGeofences(GeofencingRequest, PendingIntent) method.

You should set the following configuration options:

  • If you're tracking dwell transitions, use the setLoiteringDelay() method passing a value of approximately five minutes or less.

  • Use the setNotificationResponsiveness(), passing a value of approximately five minutes. However, consider using a value of approximately ten minutes if your app can manage the extra delay in responsiveness.

An app may only register a maximum of 100 geofences at a time. In a use case where an app wants to track a large number of retailer options, the app may want to register large geofence (at the city level) and dynamically register smaller geofences (for locations within the city) for stores within the larger geofence. When a user enters a large geofence, add smaller geofences; when the user exits the larger geofence, remove the smaller geofences and re-register geofences for a new area.

Long running background location updates without a visible app component

Example: An app that passively tracks location

Use the setPriority() method with the PRIORITY_NO_POWER option if possible because it incurs almost no battery drain. If using PRIORITY_NO_POWER isn't possible, use PRIORITY_BALANCED_POWER_ACCURACY or PRIORITY_LOW_POWER, but avoid using PRIORITY_HIGH_ACCURACY for sustained background work because this option substantially drains battery.

If you need more location data, use passive location by calling the setFastestInterval() method passing a smaller value than what you pass to setInterval(). When combined with the PRIORITY_NO_POWER option, passive location can opportunistically deliver location computed by other apps at no extra cost.

Moderate frequency by adding some latency, using the setMaxWaitTime() method. For example, if you use the setinterval() method with a value of approximately 10 minutes, you should consider calling setMaxWaitTime() with a value between 30 to 60 minutes. Using these options, location is computed for your app approximately every 10 minutes, but the app is only woken up every 30 to 60 minutes with some location data available as a batch update. This approach trades latency for more data available and better battery performance.

Frequent high accuracy updates while the user interacts with other apps

Example: A navigation or fitness app that continues to work when the user either turns off the screen or opens a different app.

Use a foreground service. If expensive work is potentially going to be done by your app on behalf of the user, making the user aware of that work is a recommended best practice. A foreground service requires a persistent notification. For more information, see Notifications Overview.