android: add batched and configurable Health Connect heart-rate export - #3
Open
maxboeer wants to merge 3 commits into
Open
android: add batched and configurable Health Connect heart-rate export#3maxboeer wants to merge 3 commits into
maxboeer wants to merge 3 commits into
Conversation
Author
|
@thibaup It would be great if you could have a look at it and potentially merge this PR into your fork, so it can become part of your librepods PR. I've been personally using my fork with my Airpods Pro 3 since the time I created it and haven't had any issues yet. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
First of all, thank you for the great work on AirPods heart-rate monitoring. I have been using the v3 release APK for the past two days and am very happy with it. It is fantastic to finally have this feature available on Android.
Motivation
Writing every one-second heart-rate reading to Health Connect individually preserves the full detail and provides effectively live data, but it also requires a Health Connect write for every sample. These frequent phone-side writes can cause unnecessary battery usage.
The existing Average mode already avoids this, but it discards the individual readings. I wanted to retain the full one-second resolution; apart from the additional storage usage, there is little downside to keeping these samples when they can be written efficiently.
Changes
This PR adds a third storage mode:
Batched mode defaults to five minutes. Batch and average intervals can both be configured between 30 seconds and 15 minutes in 30-second steps; Average keeps its previous one-minute default.
Each batch is stored as one
HeartRateRecordcontaining all timestamped samples. This requires only one set of record metadata per interval instead of separate metadata for every reading, slightly reducing the stored data in addition to reducing write operations.The exporter continues to use its mutex-protected buffering and retry path. Pending samples are handled before mode or interval changes are applied, and stable record IDs keep retries idempotent.
UI
I reorganized the original Health Connect controls because the storage strategies are mutually exclusive modes rather than independent options. Multiple switches and changing descriptions made that relationship harder to understand.
Health Connect is now presented as one grouped section with:
This better matches LibrePods’ general navigation and grouping patterns in both the Liquid Glass and Material 3 Expressive designs.
Since an interval control was already needed for batching, I also made the Average interval configurable. This adds useful flexibility with very little additional UI or implementation complexity.
StyledSlidergained an optionalonValueChangeFinishedcallback for both design implementations. The displayed value can update continuously while dragging, while preferences and exporter state are updated only after the gesture finishes. Existing slider call sites remain unchanged because the callback defaults to a no-op.Unit tests cover preservation of individual samples and timestamps, average calculation, interval normalization and bounds, mode mapping, legacy settings, and the configured interval for every mode. The existing test suite and Foss/coexist debug builds pass.
Testing and AI disclosure
The implementation was developed with GPT-5.6 Codex assistance. I have reviewed the code extensively by hand and am currently testing it on my Pixel 6a. So far, I have not found any bugs and everything behaves as intended.
Additional testing, feedback, improvements, and bug reports would be very welcome.