Repository navigation
OpenVitals 2.1.0
Released 2026-07-13.
This release is about the activities the app was throwing away. A treadmill run, a trainer ride, a strength session — anything recorded without GPS — was refused at the door as a broken file. It was not broken. It had no route, and the app had quietly decided those were the same thing.
-
Import a whole folder of FIT files. Pick the folder; every FIT file inside it is imported, including the ones in the sub-folders where a watch buries them (
GARMIN/ACTIVITY, and the like). A file that will not read fails on its own and the rest of the folder carries on. The files are opened one at a time as the import reaches them, so a folder holding a year of rides costs no more memory than the single largest ride in it. - TCX files. The format Strava and Garmin actually export an indoor activity as. The app could not open one at all, which is why a user reporting "GPX route must contain at least 2 timestamped location points" was so often holding a TCX: it is XML, so it fell through to the GPX reader, which found no track and blamed the file.
- The elevation profile of an activity — where you climbed, not just how much. Health Connect has no elevation series (it stores one total for the session, so it can tell you that you climbed 240 m and never where), so the profile is drawn from the altitudes on the route itself.
- A speed graph for an activity whose device recorded no speed — which is most watches. It is rebuilt from the splits, which knew each segment's distance and duration all along. It is drawn as a step, one flat run per split, because that is the resolution those numbers really have; a smooth curve would claim a precision they do not.
- Indoor activities could not be imported. Two separate faults, and every routeless FIT file hit the first one. A FIT file records total calories and has no active-calorie field, so the app filled the blank with an estimate — and stood that estimate next to the number the file had actually measured. A treadmill run arrived as 226 estimated active calories against its own recorded 208 total, Health Connect refuses a record whose total is below its active, and the import died. A guess was allowed to contradict a measurement. Now it is estimate both or estimate neither: a file that measured nothing still gets a full estimate, and a file that measured something is not second-guessed.
-
An indoor bike ride imported as a run. The app worked out what an activity was by mashing the sport, the name and the file name into one string and looking for words in it — testing "run" before "cycling". So
Indoor_CyclingiSmoothRun.fitwas read as a run, because the exporter's name is in the file name, and the file's own sport (which said cycling, and knew) was outvoted by it. A 27 km ride was saved as a run, with a runner's calorie estimate to match. The file's sport is now asked first, and on its own. - A stationary bike had nowhere to go. It is now an activity type of its own, so a trainer ride is no longer saved as an outdoor one. FIT names the indoor variants (treadmill, trainer, indoor rowing, strength) in a field the app had never read; it reads it now.
- A GPX with no locations in it was refused. Real exporters write indoor sessions as GPX track points that carry a time, a heart rate and no coordinates at all — 1,931 of them for a strength session, in one of the files this was fixed against. The session was in the file the whole time: the timestamps give the start, the end and the duration, and the extensions give the heart rate. What such a file genuinely lacks is distance and calories, and those are not invented.
- A GPX with a heart rate in it lost the heart rate, and imported as a bare line on a map.
A file with no locations and no timestamps is still refused, which is what keeps a corrupt download from arriving as a blank activity.
The app keeps the same package name and signing certificate, so this installs as a normal update.
Distribution flow:
- Codeberg release with signed APK and signed Android App Bundle assets.
- Direct Google Play production upload from the approved Woodpecker deployment.
Generated from docs/releases/2.1.0.md. Edit it there; changes made here are overwritten.
This wiki mirrors the Markdown in Hale-MTU/OpenVitals on every push to main.
Features
- Features
- Achievements
- Activity And Training Plans
- Activity Metrics
- Apple Health Import
- Beverage Logging And Caffeine
- Bluetooth LE Sensors
- Body Energy
- Body Metrics
- CoMaps Navigation Context
- CSV Import
- Cycle Tracking
- Daily Readiness
- Elevation Correction
- Feature Map
- FIT Files Import
- Food Logging
- GPX/KML/KMZ/TCX Route Import
- Health Connect Metrics Dashboard
- Health Report Export
- Heart And Vitals
- Heart Rate Recovery
- Home Screen Widgets
- Hydration
- Manual Entry Of Metrics
- Medical Records
- Metric Detail Customization
- Mindfulness
- Non Health Connect Metrics Dashboard
- Nutrition
- Offline Maps Support
- Onboarding And Permissions
- Preloaded Beverage Nutrition Reference
- Privacy, Support, And Diagnostics
- Recording Of Activity
- Reminders
- Settings And Preferences
- Share With Other Apps
- Sleep Score And Recovery
- Sleep Tracking
- Statistics
- Sync With Another Phone
How-to
App
- App Guide
- FAQ
- Getting Started
- Health Connect
- Install
- Local And Connected Editions
- Permissions
- Privacy
- Screenshots
- Support
Reference
- Design Reference
- Reference
- Design Guidelines for Offline & Sync
- OpenVitals UI Notes
- Reference: Data Capture
- Reference: Data Display
- Reference: Health Connect Matchmaking
- Reference: Health Connect Onboarding
- Reference: Health Connect Permissions
- Reference: Health Connect UX
- Reference: Promoting Health Connect
Engineering
- Code Analysis
- Engineering
- Flutter ↔ Kotlin test-parity matrix
- apple-health-import
- Architecture
- body-cycle-recovery
- Design system conformance
- Development
- Feature Playbook
- Flutter -> Kotlin test parity: domain/data/core/contract/state/navigation/di/bootstrap/l10n/widget_test
- Flutter → Kotlin test-parity matrix: features section
- Flutter → Kotlin test-parity matrix: ui / goldens / integration / fixtures
- Flutter-to-Kotlin test-parity matrix — dashboard + devicesync
- manual-entry
- Translations
Proposals
- Proposals
- Activity Start Flow Analysis
- Activity Start Flow Simplification Proposals
- Caffeine Detail And Future Sleep Insights
- Cycle Tracking: Design and Status
- Medical Records Through Health Connect
- Medical Records: What Is Left
Releases
- OpenVitals 2.17.0
- OpenVitals 2.16.0
- OpenVitals 2.15.2
- OpenVitals 2.15.1
- OpenVitals 2.15.0
- OpenVitals 2.14.5
- OpenVitals 2.14.4
- OpenVitals 2.14.3
- OpenVitals 2.14.2
- OpenVitals 2.14.1
- OpenVitals 2.14.0
- OpenVitals 2.13.0
- OpenVitals 2.12.0
- OpenVitals 2.11.2
- OpenVitals 2.11.1
- OpenVitals 2.11.0
- OpenVitals 2.10.1
- OpenVitals 2.10.0
- OpenVitals 2.9.1
- OpenVitals 2.9.0
- OpenVitals 2.8.0
- OpenVitals 2.7.3
- OpenVitals 2.7.2
- OpenVitals 2.7.1
- OpenVitals 2.7.0
- OpenVitals 2.6.6
- OpenVitals 2.6.5
- OpenVitals 2.6.4
- OpenVitals 2.6.3
- OpenVitals 2.6.2
- OpenVitals 2.6.1
- OpenVitals 2.6.0
- OpenVitals 2.5.0
- OpenVitals 2.4.1
- OpenVitals 2.4.0
- OpenVitals 2.3.2
- OpenVitals 2.3.1
- OpenVitals 2.3.0
- OpenVitals 2.2.8
- OpenVitals 2.2.7
- OpenVitals 2.2.6
- OpenVitals 2.2.5
- OpenVitals 2.2.4
- OpenVitals 2.2.3
- OpenVitals 2.2.2
- OpenVitals 2.2.1
- OpenVitals 2.2.0
- OpenVitals 2.1.0
- OpenVitals 2.0.4
- OpenVitals 2.0.3
- OpenVitals 2.0.2
- OpenVitals 2.0.1
- OpenVitals 1.9.0
- OpenVitals 1.8.0
- OpenVitals 1.7.7
- OpenVitals 1.7.6
- OpenVitals 1.7.5
- OpenVitals 1.7.4
- OpenVitals 1.7.3
- OpenVitals 1.7.2
- OpenVitals 1.7.1
- OpenVitals 1.7.0
- OpenVitals 1.6.3
- OpenVitals 1.6.2
- OpenVitals 1.6.1
- OpenVitals 1.6.0
- OpenVitals 1.5.1
- OpenVitals 1.5.0
Project