Skip to main content

Fit@Home

The Fit@Home feature allows members to submit selfies as proof of participation in at‑home workouts.
Selfies are lightweight validation snapshots, recommended to be screen captures from the camera preview rather than full‑resolution photos.

⚠️ Note: Avoid adding too much information or overlays to the images. Extra data can increase upload times and will be stripped out during processing.
This behavior is subject to change in future versions as more advanced features are introduced.


Host app responsibilities

  • The host app is responsible for building the camera preview and taking the screenshot.
  • The preview image must be converted to bytes before being sent to AFCore.fitAtHome().submitSelfie().
  • The SDK will transmit the image to the server for analysis.
  • We recommend using third-party camera libraries to expedite development of this feature.
  • Use AFPermissions.requestPermission(Permission.CAMERA) if you want to build your own camera workflow or rely on our permissions helper.

What you can build

  • At‑home workout check‑in flows with selfie validation.
  • Lightweight uploads that keep bandwidth low.

Permissions & threading

  • Camera permission required to preview and capture.
  • Android: use AFPermissions.requestPermission(Permission.CAMERA).
  • iOS: use AFPermissions.requestPermission(Permission.CAMERA).
  • Always call from background (Dispatchers.IO) and update UI on Dispatchers.Main.

Submit a selfie

Uploads a selfie for Fit-At-Home check-in validation. The submission includes the raw image bytes, a timestamp (UTC epoch seconds), and optional latitude/longitude coordinates.

Android (Kotlin)

lifecycleScope.launch {
val selfieBytes = snapshotBytes // ByteArray from camera
val timestamp = Clock.System.now().epochSeconds
val lat = location?.latitude
val lng = location?.longitude

val result = withContext(Dispatchers.IO) {
AFCore.fitAtHome().submitSelfie(
media = selfieBytes,
timestampInSeconds = timestamp,
lat = lat,
lng = lng
)
}

if (result.status) {
logger.d("Selfie submitted successfully: ${result.message}")
// Example: update UI state, mark check-in as "completed"
refreshUi()
} else {
logger.e("Selfie submission failed: ${result.code} - ${result.message}")
showToast("Could not submit selfie: ${result.message}")
}
}

iOS (Swift)

func submitSelfie(snapshotBytes: Data, coords: CLLocationCoordinate2D?) async {
do {
let timestamp = Int64(Date().timeIntervalSince1970)

let result = try await AFCore.shared.fitAtHome().submitSelfie(
media: snapshotBytes,
timestampInSeconds: timestamp,
lat: coords?.latitude,
lng: coords?.longitude
)

if result.status {
print("Selfie submitted successfully: \(result.message ?? "")")
refreshUI()
} else {
print("Selfie submission failed: \(result.code ?? "NO_CODE") - \(result.message ?? "")")
showAlert("Error submitting selfie: \(result.message ?? "Unknown error")")
}

} catch {
print("Unexpected error during selfie submission: \(error.localizedDescription)")
showAlert("Unexpected error sending selfie. Please try again.")
}
}

Delete a selfie

Deletes a previously submitted selfie for a given UTC date (formatted as YYYY-MM-DD).

Android (Kotlin)

lifecycleScope.launch {
val dateToDelete = "2025-08-20"

val result = withContext(Dispatchers.IO) {
AFCore.fitAtHome().deleteSelfie(date = dateToDelete)
}

if (result.status) {
logger.d("Selfie deleted successfully for $dateToDelete: ${result.message}")
refreshUi()
} else {
logger.e("Failed to delete selfie: ${result.code} - ${result.message}")
showToast("Could not delete selfie: ${result.message}")
}
}

iOS (Swift)

func deleteSelfie() async {
let dateToDelete = "2025-08-20"

do {
let result = try await AFCore.shared.fitAtHome().deleteSelfie(date: dateToDelete)

if result.status {
print("Selfie deleted successfully for \(dateToDelete): \(result.message ?? "")")
refreshUI()
} else {
print("Failed to delete selfie: \(result.code ?? "NO_CODE") - \(result.message ?? "")")
showAlert("Could not delete selfie: \(result.message ?? "Unknown error")")
}

} catch {
print("Unexpected error deleting selfie: \(error.localizedDescription)")
showAlert("Unexpected error. Please try again.")
}
}```

---

## UI patterns & tips
- Use a camera preview overlay with capture button.
- Immediately show thumbnail of captured snapshot before upload.
- Confirm deletion with a dialog before calling API.

---

## Error handling
- Show network errors clearly:Couldn’t upload selfie, check connection.
- Permission denied: instruct user to enable camera in settings.

---


*Document updated: 2025-11-19*