BLE SDK
Core module that provides low-level API for connecting to Corsano bracelets, performing commands on the bracelet, and getting raw data.
Main interfaces
The main entry point of BLE SDK is interface BleSdk. Its instance can be obtained by calling BleSdk.getInstance(). This method will always return the same (singleton) instance, so it is safe to keep a reference to it in the scope of your app.
Note: Make sure that
CorsanoSdk.initialize()is called before accessing any other methods.
BleSdk – API surface of the BLE module, which provides access to other interfaces listed in the table below.
| Interface | Description | How to obtain |
|---|---|---|
| BleScanner | An abstraction around Android BLE Scanner for performing Corsano device lookup. | BleSdk.getScanner() |
| BleDevice | Represents physical Bluetooth device (bracelet) and provides methods for interaction with it. | BleSdk.getDevice(address) |
| BleRequest | Represents an intent to execute a command on the bracelet. Contains a command ID and parameters. | Create using public constructor, e.g. GetBatteryLevelRequest() |
| BleCommand | Represents an executable command. | BleDevice.newCommand(request) |
| BleFileTransfer | Special type of BleCommand for data streaming. | BleDevice.newFileTransfer(request) |
| NotificationSource | Interface for listening to Notifications from the device. | BleDevice.notifications |
| Bluetooth | Utility interface for working with Android BluetoothAdapter | BleSdk.getBluetooth() |
BleSdk also exposes getBpCuffDevice(address) for an external blood pressure cuff, getRecentDevices() for previously seen bracelets, and removeDevice(address) to unpair.
Note:
getWatch()andremoveWatch()are deprecated in favour ofgetDevice()andremoveDevice().
Executing commands
Every interaction with the bracelet follows the same shape: you build a request, turn it into a command on a device, and enqueue it.
BleDevice
.newCommand(BleCommandRequest<T>) -> BleCommand<T>
.newFileTransfer(FileTransferRequest<T>) -> BleFileTransfer<T>
You rarely call newCommand directly — the extension functions below wrap it.
Callback style
enqueueCommand for a single value, enqueueFileTransfer for a file, which additionally reports progress:
bleDevice.enqueueCommand(
request = GetBatteryLevelRequest(),
onSuccess = { level -> Log.d("Corsano-SDK", "Battery: $level") },
onError = { error -> Log.e("Corsano-SDK", "Failed: $error") }
)
bleDevice.enqueueFileTransfer(
request = ActivityFileTransferRequest(sizeInBytes),
onSuccess = { data -> Log.d("Corsano-SDK", "Got ${data.items.size} records") },
onError = { error -> Log.e("Corsano-SDK", "Failed: $error") },
onProgress = { progress -> Log.d("Corsano-SDK", "Progress: $progress") }
)
Coroutine style (recommended)
If your app uses coroutines, prefer awaitCommandV2 and awaitFileTransferV2 from com.corsano.sdk.data.util. They return a Result<T> rather than throwing, and accept an optional timeout in milliseconds.
import com.corsano.sdk.data.util.awaitCommandV2
val result: Result<BatteryLevel> = bleDevice.awaitCommandV2(
request = GetBatteryLevelRequest(),
timeout = 10_000
)
result
.onSuccess { level -> Log.d("Corsano-SDK", "Battery: $level") }
.onFailure { error -> Log.e("Corsano-SDK", "Failed: $error") }
Warning: The earlier
awaitCommandandawaitFileTransferare deprecated — they can crash if the bracelet disconnects mid-command. Use theV2variants, which capture the failure in the returnedResultinstead.
Note that these helpers live in the data module, so they are available only if you depend on com.corsano.sdk:data.
Listening to notifications
The bracelet pushes notifications without being asked. Observe them all, or filter by type:
// everything
bleDevice.observeNotifications { notification ->
Log.d("Corsano-SDK", "Notification: $notification")
}
// just one type
bleDevice.observeNotificationsOfType<Notification.RealTimePing> { ping ->
Log.d("Corsano-SDK", "Live heart rate: ${ping.hrm}")
}
Both return the underlying NotificationSource.NotificationListener, which you pass to bleDevice.notifications.removeNotificationListener(listener) when you are done.
Notification is a sealed class with four cases: RegularPing, RealTimePing, LiveHrm and ChargingEventPing. They are described in Instant data.
Errors
Commands fail through onError (callback style) or a failed Result (coroutine style). The BLE module defines these exceptions in com.corsano.sdk.ble.exceptions:
| Exception | Meaning |
|---|---|
PairingRequiredException | The bracelet is not bonded; pair it first. See Pairing |
InvalidCommandResponseException | The bracelet returned a response that could not be decoded |
CommandResponseValidationException | The response decoded but failed validation |