When a Dungeons & Dragons player creates a character, they distribute points to attributes including strength, dexterity, and wisdom.
These choices involve tradeoffs. With a limited number of points to distribute, a higher strength score may mean a lower wisdom score, and vice versa. The right balance may differ depending on the campaign.
Building with location services also requires choices that involve tradeoffs. But instead of trading off strength, dexterity, and wisdom, a developer must trade off accuracy, frequency, and battery efficiency instead.
Why is that? iOS and Android location services use a combination of GPS, wi-fi scanning, and cell tower triangulation to determine a device's location.
If I request a higher accuracy (e.g., kCLLocationAccuracyBest
on iOS or PRIORITY_HIGH_ACCURACY
on Android), location services may switch to GPS, draining more battery.
Or, if I request a higher frequency (e.g., an interval
of 30 seconds instead of 60 seconds on Android), location services will power up more often, again draining more battery.
A "perfect" location services implementation (perfect accuracy, real-time updates, and zero battery drain) is unfortunately not possible. Instead, a developer must choose a balance of accuracy, frequency, and efficiency that makes sense depending on use case.
Fortunately, Radar SDK v3 introduces new tracking options and presets to help you choose the right balance of accuracy, frequency, and efficiency for your use case.
Presets include:
EFFICIENT
, with a low frequency of location updates and lowest battery usage. On Android, avoids Android vitals bad behavior thresholds.RESPONSIVE
, with a medium frequency of location updates and low battery usage.CONTINUOUS
, with a high frequency of location updates and higher battery usage.If we were distributing points to accuracy, frequency, and efficiency, the presets might look like this:
The CONTINUOUS
preset is suitable for on-demand use cases (e.g., delivery tracking) and some consumer use cases (e.g., order ahead).
The EFFICIENT
and RESPONSIVE
presets are suitable for most consumer use cases.
You might also toggle between presets.
For example, an on-demand app may start CONTINUOUS
tracking when a delivery starts, then stop tracking when the delivery is complete:
// delivery started
Radar.startTracking(RadarTrackingOptions.continuous)
...
// called on every location update
func didUpdateLocation(_ location: CLLocation, user: RadarUser) {
if !isDeliveryInProgress {
Radar.stopTracking()
}
}
Or, a travel app may start RESPONSIVE
tracking during a trip, then toggle to EFFICIENT
tracking when the trip is complete:
// trip started
Radar.startTracking(RadarTrackingOptions.responsive)
...
// called on every location update
func didUpdateLocation(_ location: CLLocation, user: RadarUser) {
if !isOnTrip {
Radar.startTracking(RadarTrackingOptions.efficient)
}
}
Finally, a shopping app may start CONTINUOUS
tracking while inside of a mall
geofence, then toggle to EFFICIENT
tracking outside of a mall:
Radar.startTracking(RadarTrackingOptions.efficient)
...
// called on every location update
func didUpdateLocation(_ location: CLLocation, user: RadarUser) {
let isAtMall = user?.geofences?.contains { geofence in
geofence.tag == "mall"
} ?? false
if isAtMall {
Radar.startTracking(RadarTrackingOptions.continuous)
} else {
Radar.startTracking(RadarTrackingOptions.efficient)
}
}
Though we recommend using presets for most use cases, you can modify them.
The SDK has two states: stopped and moving. stopDuration
and stopDistance
determine whether a location update is considered stopped, and the other options determine tracking behavior depending on state. Frequency, accuracy, and other options are configurable:
// presets
Radar.startTracking(RadarTrackingOptions.efficient)
Radar.startTracking(RadarTrackingOptions.responsive)
Radar.startTracking(RadarTrackingOptions.continuous)
// custom
let trackingOptions = RadarTrackingOptions.continuous
trackingOptions.desiredMovingUpdateInterval = 60
trackingOptions.desiredStoppedUpdateInterval = 180
trackingOptions.desiredAccuracy = .high
trackingOptions.stopDuration = 50
trackingOptions.stopDistance = 30
trackingOptions.stopTrackingAfter = date
trackingOptions.sync = .all
Radar.startTracking(trackingOptions)
Just keep in mind the tradeoffs above!
Radar can't help you with D&D character creation, but we can help you build amazing location-aware app experiences.
New to Radar? Sign up, then check out the SDK documentation to get started.
Want to stay in the loop about location services best practices? Subscribe to the newsletter below.
Happy coding!
See what Radar’s location and geofencingsolutions can do for your business.