Skip to content

Methods

Reference for the public methods on CircadifySDK.

Runs the full measurement flow: session creation, camera capture, quality checks, secure upload, and result polling.

lifecycleScope.launch {
try {
val result = sdk.measureVitals(
MeasurementOptions(
lifecycleOwner = this@MainActivity,
previewView = previewView,
),
)
showResult(result)
} catch (error: CircadifyError) {
showError(error.message)
}
}

Parameters (MeasurementOptions):

NameTypeRequiredDescription
lifecycleOwnerLifecycleOwnerYesLifecycle used by CameraX. Usually an Activity, Fragment, or LifecycleOwner from Compose.
previewViewPreviewView?NoCameraX preview surface owned by your app.
demographicsDemographics?NoOptional age, sex, and Fitzpatrick skin type. See Configuration → Demographics for the full type.
cancellationSignalCancellationSignal?NoCancels this measurement.

Returns: VitalSignsResult

data class VitalSignsResult(
val heartRate: Double,
val hrv: Double?,
val respiratoryRate: Double?,
val spo2: Double?,
val systolicBp: Double?,
val diastolicBp: Double?,
val confidence: Double,
val timestamp: Long,
val sessionId: String,
)

The Android SDK uses a frame-threshold capture policy instead of requiring a fixed 720-frame payload. By default, capture targets 10 FPS and starts upload once at least 150 quality frames have been accepted. The SDK encodes the actual frame count and FPS in the upload payload so the Circadify backend can process measurements from a wider range of Android devices.

If a lower-end device accepts frames more slowly, the SDK continues only until the minimum accepted-frame threshold is reached or the capture timeout is hit. If quality is good, upload starts immediately after enough usable frames are available.

val sdk = CircadifySDK(
context = context,
config = CircadifyConfig(
apiKey = "ck_live_your_key_here",
measurementDurationSeconds = 30,
targetCaptureFps = 10,
minimumAcceptedFrames = 150,
maximumAcceptedFrames = 720,
),
)

Checks whether camera permission is granted and a camera exists on the device. It does not request permission.

if (sdk.checkCameraAccess()) {
startMeasurement()
} else {
requestCameraPermission()
}

Returns: Boolean

Returns camera support and permission information.

val capabilities = sdk.getDeviceCapabilities()
if (!capabilities.hasFrontCamera) {
showMessage("A front camera is required.")
}

Returns: DeviceCapabilities

data class DeviceCapabilities(
val hasCamera: Boolean,
val hasFrontCamera: Boolean,
val cameraPermissionGranted: Boolean,
val mediaDevicesSupported: Boolean = true,
val isSecureContext: Boolean = true,
val maxResolution: Resolution? = null,
)

Cancels an active measurement. The running measureVitals() call throws a CircadifyError with code CANCELLED.

cancelButton.setOnClickListener {
sdk.cancel()
}

You can also cancel by cancelling the coroutine or by passing a CancellationSignal:

val signal = CancellationSignal()
lifecycleScope.launch {
sdk.measureVitals(
MeasurementOptions(
lifecycleOwner = this@MainActivity,
previewView = previewView,
cancellationSignal = signal,
),
)
}
signal.cancel()

Releases SDK resources and cancels active scanning. Call it when the owning screen is destroyed.

override fun onDestroy() {
sdk.destroy()
super.onDestroy()
}