Repository navigation
Health Connect export creates fragmented sleep sessions instead of one complete session #193
Description
What happened?
Summary
OpenStrap Edge exports every sleep-stage segment to Health Connect as a separate SleepSessionRecord instead of exporting one complete sleep session containing all stages.
As a result, apps reading the Health Connect data display multiple short sleep sessions and an incorrect total sleep duration.
Actual behavior
OpenStrap Edge detected the full night correctly:
- Sleep window: 23:55–07:46
- Awake: 32 min
- REM: 1 h 35 min
- Light: 5 h 18 min
- Deep: 16 min
- Total detected sleep: approximately 7 h 9 min
After exporting to Health Connect, the receiving app displayed only 49 minutes split into separate sessions:
- 23:59–00:17
- 01:37–01:56
- 02:38–02:51
The full sleep session was not available.
Expected behavior
Health Connect should contain exactly one SleepSessionRecord covering the complete sleep window:
23:55–07:46
├── Awake stages
├── REM stages
├── Light stages
└── Deep stages
All sleep stages should be contained in the stages list of that single session.
Steps to reproduce
- Wear a WHOOP 4.0 overnight.
- Let OpenStrap Edge sync and derive the sleep data.
- Confirm that the complete night appears correctly in OpenStrap Edge.
- Enable Health Connect export.
- Open the exported sleep data in a Health Connect-compatible app.
- Observe that the sleep is split into multiple short sessions and the total duration is incorrect.
Suspected root cause
Based on the current implementation in lib/health/health_export.dart, each hypnogram segment appears to be written independently using writeHealthData() with types such as:
SLEEP_LIGHTSLEEP_DEEPSLEEP_REMSLEEP_AWAKE
The Android implementation of the Flutter health package converts each of these writes into a separate SleepSessionRecord containing only one stage.
Although SLEEP_SESSION is included in the requested/exported data types, the complete sleep window does not appear to be written as one session containing all stage records.
This produces a structure similar to:
SleepSessionRecord(stage 1)
SleepSessionRecord(stage 2)
SleepSessionRecord(stage 3)
...
Instead of:
SleepSessionRecord(
startTime: sleep onset,
endTime: sleep offset,
stages: all hypnogram stages
)
Additional issue
The return value of writeHealthData() should also be checked.
The method returns Future<bool>, but the exporter currently appears to treat the operation as successful unless an exception is thrown. Health Connect or plugin failures returning false may therefore be silently ignored.
Proposed fix
Add a dedicated sleep-session export method that accepts:
- Full sleep-session start time
- Full sleep-session end time
- All sleep stages
- Stage start and end times
- Stage type
On Android, create exactly one SleepSessionRecord:
SleepSessionRecord(
startTime = onset,
endTime = offset,
stages = stages.map {
SleepSessionRecord.Stage(
startTime = it.start,
endTime = it.end,
stage = it.type
)
},
metadata = metadata
)The current per-stage writeHealthData() loop should not be used for Android sleep export.
The exporter should also:
- Check the Boolean result of every Health Connect write.
- Delete previous sleep records using the actual sleep-session window, including periods before midnight.
- Re-export the full session idempotently.
- Ensure stages do not overlap and remain inside the session bounds.
Suggested regression test
Use a session crossing midnight:
Session: 23:55–07:46
Awake: 32 min
REM: 95 min
Light: 318 min
Deep: 16 min
Verify that:
- Exactly one sleep session is exported.
- The session covers 23:55–07:46.
- Every stage is inside the parent session.
- Stages do not overlap.
- A repeated export still leaves exactly one session.
- A failed or
falseHealth Connect write marks the export as unsuccessful.
App version
0.9.21+52
Platform
Android (APK)
Phone model and OS version
Google Pixel 9 Pro XL, Android 17
Which band?
WHOOP 4.0
Screenshots
Quick checks
- The official WHOOP app is not also connected to this band
- I've searched existing issues for this
Activity
FlixiDoe commentedon Aug 5, 2026
Fixed in #196.
I tested the updated APK on my Pixel 9 Pro XL. Health Connect now receives exactly one complete sleep session from 23:55–07:46, with all awake, REM, light, and deep stages contained inside that parent session.
I also verified the export using a fresh Google Health account, where the complete session was imported correctly. My existing Google account continued showing its previously cached sleep data, but Health Connect itself contains the corrected record.
The regression tests pass,
flutter analyzeis clean, and the Android release APK builds successfully.ramishroshan commentedon Aug 5, 2026
Same issue syncing with apple health.