Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Balanced mode for background GPS location #3085

Open
kloknibor opened this issue Jan 9, 2025 · 16 comments
Open

Balanced mode for background GPS location #3085

kloknibor opened this issue Jan 9, 2025 · 16 comments
Labels
enhancement New features, or improvements to existing features.

Comments

@kloknibor
Copy link
Contributor

What is the problem or limitation you are having?

Currently we are only supporting continuous retrieval of the GPS coordinates, draining the battery.

When we look into a tool like owntracks we see that also a more balanced mode for different platforms is available. I would be nice to implement these into our hardware platform

Describe the solution you'd like

Add a startMonitoring SignificantLocationChange and stopMonitoringSignificantLocationChanges function to toga hardware to the location function.

for ios/macos we have the following:
Apple defines a Significant location change as traveling a distance of at least 500 meters in 5 minutes. This mode allows the app to run in background and minimize the power consumption.

This standard tracking mode reports significant location changes only (>500m and at most once every 5 minutes). This is defined by Apple and is optimal with respect to battery usage.

This can be started with the following API call startMonitoringSignificantLocationChanges and stopping with stopMonitoringSignificantLocationChanges

Examples:

if you don't move, no new location is published - even if you don't move for hours. (Note, however, that the app will publish a ping-type message once in a while.)
if you move at least 500 meters, a new location will be published after 5 minutes
if you move 10 kilometers in 5 minutes, only one location will be published

To get a consistent result on android we can use the following:
locatorDisplacement : 500m
locatorInterval : 300 seconds
LocatorPriority : BalancedPowerAccurancy

Describe alternatives you've considered

Using an additional application solely for GPS data (owntracks0

Additional context

No response

@kloknibor kloknibor added the enhancement New features, or improvements to existing features. label Jan 9, 2025
@kloknibor
Copy link
Contributor Author

Potentially I might look into this myself, however if someone is looking for the same feature be more than welcome :-)

@freakboy3742
Copy link
Member

Definitely sounds like a worthwhile addition to the location API.

In terms of a specific API, I'm guessing this would be an optional parameter to start_tracking(), plus a property that can be read/written to retrieve the current location tracking mode. The only questions from there are:

  1. Do we use a boolean (continuous=True/False), or a CONTINUOUS/SIGNIFICANT enum?
  2. What's the default value? Do we default to SIGNIFICANT (where possible) for battery preservation reasons?

It would also be worth a quick survey of the Android docs to work out if there are any other mode options that we might need to accomodate. I can imagine there might be a need for options around how significant "significant" is (a significant when walking is a lot less than a significant change when driving).

@kloknibor
Copy link
Contributor Author

Personally, I would keep the Android implementation as close as possible to the iOS implementation so that the same parameters Apple defines are used. This would ensure the same results on both platforms.

For question 1, I'm unsure what the pros or cons are. I assume with True/False you can only have 2 options and with enum more. On iOS, I personally see added value in also the CLvisit API, but since it's not part of the Location manager and there is no equivalent for Android, I would consider it out of scope.

For your second option, this totally depends on the kind of app that is being built; personally, I think we will get fewer questions if we just keep it on continuous as default since significant really is optimization; if someone needs that, they will look for it.

@kloknibor
Copy link
Contributor Author

I did some more research, actually startmonitoringvisits is part of the location manager : https://developer.apple.com/documentation/corelocation/cllocationmanager/startmonitoringvisits()?language=objc

Because of that I would suggest to use enum and I will check if we somehow can duplicate this behaviour on android.

@freakboy3742
Copy link
Member

For question 1, I'm unsure what the pros or cons are. I assume with True/False you can only have 2 options and with enum more. On iOS, I personally see added value in also the CLvisit API, but since it's not part of the Location manager and there is no equivalent for Android, I would consider it out of scope.

It depends entirely on whether there is, even conceptually, an option other than CONTINUOUS or SIGNIFICANT. If there's even a prospect of there being a third option, then it needs to be an enum so that we could add that option in future if we chose to do so.

Specifically availability across all platforms isn't the issue - Toga is a cross-platform API, so we need to keep an eye to what could be implemented. Even if Android doesn't have an API today, if there's a conceptual feature that iOS provides, it's reasonable to assume that Android might add that feature in a future release (and vice versa, for that matter).

@kloknibor
Copy link
Contributor Author

Let me know if the draft looks like something you agree with. If so, I will expand it to Android (no test device available, and it's kind of hard to test location serviceses in simulation. Should I just give it a try or not support it yet?), create the tests, and do the tests on iOS.

@freakboy3742
Copy link
Member

The implementation you've provided for significant vs continuous broadly makes sense.

As for needing an enum for VISITS... you're possibly correct, but I think a little more elaboration is needed here.

In particular, how are the "points of interest" defined? And are they mutually exclusive with other forms of tracking? Based on the iOS API at least, I would expect that I could label my home as a place of interest, then receive a specific callback when I arrive at home; but I could also register to receive any other continuous updates. For example, imagine a route tracking app that knows it can stop updates when it arrives at the destination - you need continuous tracking, but you also need a notification when the target location is reached.

To that end, I suspect it would be more helpful to register a separate handler for "visits" as you've described them here; otherwise; and to be able to register individual places of interest, and then get those handed back as identifiers on this separate handler.

That also suggests that we don't need the enum for "location mode" - we only need to know whether we're doing "continuous" tracking as a boolean, with a completely orthogonal feature for place of interest detection.

Also - to be clear about expectations here - while a fully worked solution for place-of-interest tracking would be great, That's not a requirement for the PR to be accepted. A PR that only implements location tracking would be completely acceptable; however, we do need to be clear how the API changes we're making for significant change tracking will interact with other potential API changes.

@freakboy3742
Copy link
Member

Oh - and as for Android testing; give it a try, and we can test the implementation as required.

@kloknibor
Copy link
Contributor Author

@freakboy3742 what you are describing are geo fences. The visits API is not that and you don't need to register any locations at all, see: https://developer.apple.com/documentation/corelocation/clvisit?language=objc

Criteria Continuous Location Tracking Significant-Change Location Service Visits Location Service
Description Provides frequent, real-time location updates. Triggers updates when the device’s location changes significantly (e.g., by a few hundred meters). Triggers notifications when the system detects that the user has arrived at or departed from a significant place.
Accuracy / Granularity High accuracy possible (based on desiredAccuracy). Less frequent updates; accuracy depends on larger changes in location (e.g., cell tower transitions). Focused on arrival/departure events; granular point-of-interest detection is based on Apple’s internal algorithms.
Update Frequency As frequently as the system can deliver (depends on hardware & desiredAccuracy). Updates occur when iOS deems there’s a “significant” location change (no fixed time interval). Updates occur only when iOS detects the user has arrived or departed a place—no continuous or frequent updates.
Battery Impact Highest battery consumption (continuous GPS usage). Moderate battery consumption (less frequent GPS usage). Lowest battery consumption (leverages system-level location cues).
Use Cases Turn-by-turn navigation, fitness tracking, delivery apps, or any real-time location tracking. Location-triggered tasks that don’t require real-time data (e.g., geofenced alerts, region-based reminders). Apps needing to log “visits” for location history, journaling, or context-aware experiences based on user dwell times.
Background Execution Requires background location permission; app remains active in the background. Can run in the background with less frequent wake-ups. App is launched/woken in the background when visits are detected.
Configuration (Core Location) Use locationManager.startUpdatingLocation() with desiredAccuracy (e.g., kCLLocationAccuracyBest). Use locationManager.startMonitoringSignificantLocationChanges(). Use locationManager.startMonitoringVisits().
When to Choose When you need real-time or near-real-time location updates (navigation, live tracking, etc.). When you only need to know about major location changes and want to conserve battery. When you only need to know about arrivals/departures at places (lowest battery impact).

@kloknibor
Copy link
Contributor Author

So they have different use cases. However visits has another return format than significant and contuous tracking. On top of this, I could also foresee someone using more options at the same time (e.g. use significant or visits but as soon as user starts moving start continuous). So I see 3 options:

  • Do it is as suggested in this PR (Not desired)
  • Give every tracking method their own start and stop function
  • Split continuous + significant from visits as you suggested.

Personally I currently lean towards just giving all tracking methods their own start and stop function, but if you want to continue with what you suggested than I can make that too.

@freakboy3742
Copy link
Member

Ah - thanks for clarifying.

So, if I'm understanding correctly, a "visit" is really just a "really really low granularity significant change update" - where "significant" is downgraded to "you have arrived/departed a location" - and it's the OS that determines what a "location" is?

@mhsmith
Copy link
Member

mhsmith commented Feb 10, 2025

Surely such a feature would only be useful if it also gave you the name of the location, rather than just the co-ordinates?

Before we settle on this API, we should consider whether and how it would be possible to implement it on at least one other platform, otherwise we're in danger of committing ourselves to something Apple-specific.

@kloknibor
Copy link
Contributor Author

@freakboy3742 This is exactly right,the iOS Visits API is very handy for many different kinds of apps, much like Life Cycle or Google Timeline. Apple itself seems to leverage this same mechanism to notify me how long my drive home will be as soon as I depart a location I’ve been at for a while. It’s particularly useful for low-battery use cases, since it only fires events when the user leaves a place after some dwell time, rather than constantly polling the GPS.

@mhsmith As noted, stops can be anywhere, so there’s no predefined location name, just arrival and departure times plus approximate coordinates. This is great if you don’t need the specific route in between. In my case, I’m looking to automatically fill out my timesheets based on these visit logs, rather than running continuous location tracking.

Additional Use Case
Another interesting scenario is creating contextual reminders triggered by departure events. For example, an app could remind you to pick up groceries as soon as you leave work or to send a summary report once you depart a client site. Since the API wakes up your app only when the user leaves a stop, it can power these location-based reminders without draining the device battery, making it a lightweight yet powerful way to handle on-the-go tasks.

it's basically geofences without needing to explicitly settings the geofence. Ofcourse from your app you can than still define certain areas and automate based on the location.

However it's indeed the question if Android will introduce the same logic.

Potentially something close can be created with these options (found from chatgpt), but it's not completely the same:

Activity Recognition + Location
How it works:
The Activity Recognition API detects whether the user is walking, driving, still, etc.
The Fused Location Provider can give low-power location updates (e.g., significant location changes).
Combine these signals to infer that the user has stopped moving at a new location and then left later on.
Upsides:
Can dynamically detect if someone has “come to rest” in an unknown location.
More flexibility than geofences, since you’re not locked to known places.
Downsides:
Requires custom logic to detect “arrived at a spot” and “departed” events.
Battery optimization and background execution can be tricky, as different Android devices handle background tasks differently.

Periodic (Low-Frequency) Location Updates
How it works:
Request location updates with PRIORITY_BALANCED_POWER_ACCURACY or PRIORITY_LOW_POWER and a fairly large interval.
Check if the user’s location remains roughly the same over multiple updates.
Conclude an “arrival,” wait for a location change to signal “departure.”
Upsides:
Straightforward to implement with the Fused Location Provider.
Controlled battery usage if you request updates at infrequent intervals.
Downsides:
Less precise arrival/departure detection because updates can be delayed.
May miss short stops.

@freakboy3742
Copy link
Member

This is exactly right... It’s particularly useful for low-battery use cases, since it only fires events when the user leaves a place after some dwell time, rather than constantly polling the GPS.

In which case, I think it makes sense that this is another level of granularity on updates as you've proposed in the PR, rather than an orthogonal feature.

it's basically geofences without needing to explicitly settings the geofence. Ofcourse from your app you can than still define certain areas and automate based on the location.

In practical terms, I'd argue you almost have to define the areas (or, at least, have some mechanism for saying "location X is close to location Y" for this to be useful. Saying "You've arrived at <lat, lng>" isn't really helpful to anyone - you need to know that location is "home" or "work" for that notification to be useful in a user context.

However, explicitly naming "places of interest" is definitely an orthogonal feature that is tied to defining and using geofences, rather than something that needs to be handled in a "granularity" change.

However it's indeed the question if Android will introduce the same logic.

Even if Android doesn't implement the feature, it's conceivable that we could:

  1. "fake" an implementation (i.e., receive the notifications at the native level, but only send them to the user if the exceed some distance threshold, or changes mode of transportation), or
  2. document that on platforms that don't support explicit "visits" level granularity, the implementation falls back to "significant" (and, I guess, if the platform doesn't support "significant", that it falls back to "continuous")

(2) is the simplest solution; if that approach includes a log message that warns the developer they're not going to get true "visit" notifications, that's probably the best approach for a v1 implementation on Android (unless you're especially motivated to try implementing (1)).

@kloknibor
Copy link
Contributor Author

I'm personally only interested in using the visits API on iOS, which I currently do by subclassing, but I am fine to put in some more effort and give back to the project.

However how do we move forward?

Do we want start tracking for only continuous? have another function for tracking significant location changes? Or do we switch between these modes with a boolean input?

Is it ok to write an implementation for visits at the current time? And if so we want to do start and stop this from seperate functions right? Or you also want to merge it under start tracking?

@freakboy3742
Copy link
Member

However how do we move forward?

When a new feature is added by a contributor, we don't expect that they'll necessarily implement it on every platform (we won't complain if they do, but it's not expected). All we require is that enough technical elaboration has been done to prove the feature could be implemented on other platforms.

However, if they add the feature for one platform, then the tests for the new feature must be written/updated so that they will at least be skipped on platforms where the feature isn't supported yet.

In terms of moving this feature forward specifically: you've met the design requirement, and what you've got on #3177 is a very good starting point. From here, I'd suggest:

  • Complete the implementation of start_tracking(granularity=ENUM), with a default value of LocationGranularity.CONTINUOUS.
  • Defining and implementing granularity=VISITS is optional (although it sounds like you're motivated to implement it on iOS); if we do, it will be a separate granularity level.
  • The handler for granularity=VISITS tracking will be the same as for any other location tracking, but it will also include the arrival/departure time for the location. These fields won't be provided for CONTINUOUS/SIGNIFICANT tracking. The documentation for the location tracking handler will need to be updated to describe these extra data points.
  • Defining an implementation of granularity tracking on Android is also optional (with the "must still pass tests" caveat above)
  • The platform notes for the location service should note that granularity may not be fully supported on all platforms, and the service will lean towards "more updates". If there's no implementation of VISITS, it will fall back to SIGNIFICANT; if there's no implementation of SIGNIFICANT, it will fall back to CONTINUOUS; and if a fallback is used, a warning will be output.

Does that sound achievable?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New features, or improvements to existing features.
Projects
None yet
Development

No branches or pull requests

3 participants