Sleep Tracking Implementation via Mobile Application
Sleep tracking on phone without wearable — accelerometer under pillow or mattress. With wearable — heart rate + accelerometer for phase classification. Both work but fundamentally different accuracies and technical complexity.
Without Wearable: Accelerometer as Movement Sensor
Classic — phone placed on mattress. Body movements transmit through mattress to phone. Task: classify movement periods (restless sleep, awakenings) and rest (deep/light sleep).
Algorithm:
- Record accelerometer at 10 Hz (battery-optimal, sufficient for detecting body movements)
- Every 30 seconds — epoch: calculate
activity_count = sum(|delta_x| + |delta_y| + |delta_z|)per epoch - Classification:
activity_count < threshold → SLEEP, > threshold → WAKE - N-epoch patterns → determine sleep start and end
Activity threshold selected empirically — depends on phone placement, mattress firmness. First 3–7 nights — calibration via feedback ("I fell asleep at 23:15, correct?").
Sleep phase accuracy (REM/N1/N2/N3) — below 60% without heart rate. Movement only — rough division into "calm/restless". If product claims medical-grade — need wearable sensor.
With Wearable: HealthKit Sleep / Health Connect Sleep
iOS + Apple Watch:
Apple Watch automatically records sleep via own algorithms (accelerometer + heart rate + skin temperature on Series 8+). Result — in HealthKit as HKCategoryValueSleepAnalysis:
let sleepType = HKObjectType.categoryType(forIdentifier: .sleepAnalysis)!
let query = HKSampleQuery(
sampleType: sleepType,
predicate: HKQuery.predicateForSamples(withStart: startDate, end: endDate),
limit: HKObjectQueryNoLimit,
sortDescriptors: [NSSortDescriptor(key: HKSampleSortIdentifierStartDate, ascending: true)]
) { _, samples, _ in
guard let samples = samples as? [HKCategorySample] else { return }
samples.forEach { sample in
switch sample.value {
case HKCategoryValueSleepAnalysis.asleepCore.rawValue:
// N1/N2 — light sleep (watchOS 9+)
case HKCategoryValueSleepAnalysis.asleepDeep.rawValue:
// N3 — deep sleep
case HKCategoryValueSleepAnalysis.asleepREM.rawValue:
// REM
case HKCategoryValueSleepAnalysis.awake.rawValue:
// Awake
default: break
}
}
}
Before watchOS 9 only inBed and asleep — no phases. If app must show sleep phases from Apple Watch — minimum iOS 16 / watchOS 9.
Android + Health Connect:
val response = healthConnectClient.readRecords(
ReadRecordsRequest(
recordType = SleepSessionRecord::class,
timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
)
)
response.records.forEach { session ->
val duration = Duration.between(session.startTime, session.endTime)
session.stages.forEach { stage ->
when (stage.stage) {
SleepSessionRecord.STAGE_TYPE_DEEP -> { /* deep */ }
SleepSessionRecord.STAGE_TYPE_REM -> { /* REM */ }
SleepSessionRecord.STAGE_TYPE_LIGHT -> { /* light */ }
SleepSessionRecord.STAGE_TYPE_AWAKE -> { /* awake */ }
}
}
}
Recording Sleep (Own Data)
If app itself analyzes sleep (via phone accelerometer):
iOS — write to HealthKit:
let sleepSample = HKCategorySample(
type: HKObjectType.categoryType(forIdentifier: .sleepAnalysis)!,
value: HKCategoryValueSleepAnalysis.asleepCore.rawValue,
start: phaseStart,
end: phaseEnd
)
healthStore.save(sleepSample) { success, error in }
Smart Alarm
Most tracker feature — wake in "light" phase within window (e.g., ±30 min from desired time). Implementation on phone: app active in background, analyzes accelerometer, detects activity in alarm window — triggers via UNUserNotificationCenter (iOS) or AlarmManager.setAlarmClock() (Android).
AlarmManager.setAlarmClock() — only Android alarm guaranteed to fire on strict battery saver (Doze mode). Regular setExact() and setAlarmClock() may delay several minutes.
Typical Errors
- Not accounting for sleep breaks (person woke 20 min) — algorithm splits one session into two
- Forgetting daylight saving time — timestamps UTC, convert to local only for display
- Not filtering "sleep" < 30 min duration — naps or classification errors get into statistics
Timeframes
Basic tracker with accelerometer and alarm — 3–5 weeks. With HealthKit/Health Connect integration, sleep phases and period analytics — 6–10 weeks.







