syncSteps

abstract suspend fun syncSteps(): AFResult

Full sync cycle: fetches dates to sync, reads health data, and submits it.

This is the primary sync entry point. It orchestrates the complete flow:

  1. Checks that a member ID and device type are available.

  2. For HealthKit/Health Connect devices: calls getDatesToSync, reads data from the device health store for those dates, and calls submitActivities.

  3. For legacy Android/Fitbit devices: triggers a server-side sync via API.

  4. On success, records the current timestamp as smartWalkingLastSyncTimestamp.

Concurrency guard: If a sync is already in progress, returns immediately with AFResult(false, "Sync already in progress"). Only one sync runs at a time.

Sync state: Emits SmartWalkingEvent.SyncStarted at the start, then SmartWalkingEvent.SyncSubmitted once the SmartWalking API accepts the submission. The submission is always followed by exactly one terminal processing event:

  • SmartWalkingEvent.SyncProcessed — backend job completed and data is queryable via the Mobile API. Refresh activity totals on this event.

  • SmartWalkingEvent.SyncProcessingTimedOut — backend accepted the job but the SDK could not confirm completion within its polling budget. Data will land on a later Windows Service cycle.

  • SmartWalkingEvent.SyncProcessingDeferred — backend did not issue a jobId (typically because the promotion service is disabled or not yet enabled on this environment). The submitted steps remain in the SmartWalking DB until a backend-side scheduled promotion task picks them up, or until the consumer calls syncSteps again. Consumers may surface a "processing pending" hint and/or refresh on their own cadence.

  • SmartWalkingEvent.SyncFailed — submission or backend processing failed.

Kotlin

lifecycleScope.launch {
val result = AFCore.smartWalking().syncSteps()
if (result.status) {
showMessage("Sync complete")
} else {
showMessage("Sync skipped: ${result.statusMessage}")
}
}

Swift

Task {
let result = try await AFCore.shared.smartWalking().syncSteps()
if result.status {
showMessage("Sync complete")
} else {
showMessage("Sync skipped: \(result.statusMessage ?? "")")
}
}

Return

AFResult — check status for success.