Pairing and connection
To set up the bracelet and the Android SDK here are the main steps to implement:
- Pair and connect to the bracelet
- Set up the bracelet parameter
- Set up the automatic data transfer between the Bracelet to the Android SDK database
- Retrieve the data
Step 1: Pairing to the bracelet
To setup the connection to the bracelet:
- Detect the nearby bracelets
- Detect a particular bracelet (pusher press)
- Pair and connect
Getting device status
enum class ConnectionState {
NOT_CONNECTED,
DISCONNECTING,
CONNECTING,
CONNECTED
}
Use DeviceManager.getCurrentDevice()?.connectionState
Scanning and connecting to bracelet
This guide will walk you through the process of pairing with the bracelet.
Preparing for BLE scan
The first step is to check that everything is ready for BLE scan.
Checking Bluetooth state
In order to be able to discover and connect to Bluetooth devices via Android API, it must be enabled. This is a restriction of Android, its methods will throw exception if you try to access Bluetooth devices. That’s why it is important to check Bluetooth state before working with the SDK.
In this guide:
if (!BluetoothUtil.isBluetoothSupported()) {
// show Bluetooth not supported screen
return
}
if (!BluetoothUtil.isBluetoothEnabled()) {
// request to turn the Bleutooth on
val intent = BluetoothUtil.getEnableBluetoothIntent()
fragment.startActivity(intent)
}
You can check Bluetooth adapter state at any given moment, but we recommend subscribing to state change notifications:
// Listen to Bluetooth state updates
val listener = object : Bluetooth.StateListener {
override fun onBluetoothStateChanged(state: BluetoothState) {
// handle state change here
}
}
BleSdk.getBluetooth().addStateListener(listener)
Getting Scanner
Once you know that Bluetooth Adapter is enabled, you can perform device lookup. To do it you will first need to get an instance of BleScanner
.
// get BleSdk instance
val bleSdk = BleSdk.getInstance()
// get BleScanner instance
val scanner = bleSdk.getScanner()
Requesting runtime permissions
Since Android 6 in order to perform a lookup of a Bluetooth device, the app needs to request special runtime permissions.
Android version | Required permissions |
---|---|
Android 5.x | No permissions needed |
Android 6+ | android.permission.ACCESS_COARSE_LOCATION |
Android 9+ | android.permission.ACCESS_FINE_LOCATION |
Android 12+ | android.permission.BLUETOOTH_SCAN |
However, you don’t need to check Android version and and decide which permission to request. For convenience, you can just use BleScanner.getMissingPermissions()
to check if you need to request any of these permissions.
val permissions = scanner.getMissingPermissions()
if (permissions.isNotEmpty()) {
fragment.requestPermissions(permissions)
}
Performing BLE scan
You can perform scanning for new devices.
val scanner = BleSdk.getInstance().getScanner()
// start scan
scanner.startScan { event ->
// handle event here
}
// stop scan
scanner.stopScan()`
Scan events
Event | Description |
---|---|
BleScanStarted | Emitted when scanner successfully started BLE scan. Only emitted once. |
BleScanResults | Emitted when something was found. The event will contain the addresses and advertisement data from found devices in a BleScanRecord object. The same device may be “discovered” multiple times during scan. |
BleScanStopped | Emitted after scan was stopped. Only emitted once. |
BleScanFailed | Emitted when error occurred during scan or it failed to start. Only emitted once. |
Note: We recommend limiting scan with a reasonable timeout and only perform it when your app is in foreground to avoid battery drain.
During scan you need to collect all device addresses from BleScanResults
events in a Set
or remove duplicates manually.
// start scan
var foundDevices = emptyList<BleScanRecord>()
scanner.startScan { event ->
when (event) -> {
is BleScanEvent.BleScanResults -> {
foundDevices = (event.results + foundDevices).distinctBy { it.address }
}
// ...
}
}
Pairing with bracelet
Detecting Pusher event
Mandatory starting SDK 0.8.7
Before pairing and connecting to the bracelet for the first time, a user action is necessary for security: a pusher press. B1: push on the pusher button B2: doesn't have a pusher button, the equivalent is to put the bracelet on the charger and take it off the charger.
Technically the information "isPusherPressed" is contained in the advertisement data. After the scan, launch the second scan to detect the pusher press on a specific device:
val scanner = BleSdk.getInstance().getScanner()
// start scan
scanner.startScanForPusherEvent(macAddress) { event ->
// handle event here
}
// stop scan
scanner.stopScan()
Scan for pusher press events
Event | Description |
---|---|
BleScanStarted | Emitted when scanner successfully started BLE scan. Only emitted once. |
BleScanResults | Emitted when the bracelet with a pusher press was found. The event will contain the advertisement data from found device in a BleScanRecord object. The same device may be “discovered” multiple times during scan. |
BleScanStopped | Emitted after scan was stopped. Only emitted once. |
BleScanFailed | Emitted when error occurred during scan or it failed to start. Only emitted once. |
The pusher press in the advertizing data:
val foundDevices = //...
val targetDevice = newDevices.find {
it.advertisementData?.isPusherPressed == true
}
if (targetDevice != null) {
// start pairing process
}
Connecting to bracelet
You can connect to the bracelet by its address that was obtained during scanning. Connection will automatically start pairing if the bracelet is not already paired.
To establish connection, obtain an instance of BleDevice
, check permissions and connect()
.
val address = "..."
// get a device by address
val device = BleSdk.getInstance().getDevice(address)
// check permissions
val permissions = device.getMissingConnectPermissions()
if (permissions.isEmpty()) {
// connect to device
device.connect(keepAlive = true)
} else {
// request permissions
}
The BleDevice
returned by BleSdk#getWatch(address)
is retained in the pool. You may safely invoke this method multiple times – it will always return the same instance.
Connection to watch is an async operation. Use BleDevice#addConnectionStateListener()
to subscribe to connection state notifications.
The keepAlive
flag determines whether to automatically retry connection if it is lost or bluetooth adapter state changed. Set it to false
only if you want to manually manage the connection to the watch.
Note: Multiple simultaneous connections are also supported. However, there is a limit, which depends on the phone and Android version.
Pairing with bracelet
Before performing any commands a bond needs to be established. This is also referred to as "pairing". Pairing starts automatically when connection is initiated for the first time, you don’t need to do anything to start it.
However, you might need to check the bond state because it is required to interact with the bracelet.
You can check current pairing state or observe its changes for a particular device:
val watch = getDevice(address)
if (watch.bondState == BondState.BONDED) {
// do something
}
watch.addBondStateListener(
object : BleDevice.DeviceBondStateListener {
override fun onBondStateChanged(state: BondState) {
// do something
}
}
)
Alternatively, you can subscribe to bond state updates for all devices:
val bluetooth = BleSdk.getInstance().getBluetooth()
bluetooth.addBondStateListener(
object : Bluetooth.BondStateListener {
override fun onBondStateChanged(address: String, state: BondState) {
// do something
}
}
)
Disconnecting
To disconnect just call device.disconnect()
. Call this when you finished working with the watch. But keep in mind that this operation will cancel()
all currently running and previously scheduled commands.
Unpair
To unpair and cancel all running tasks and future events, please use the following code:
fun unpair(context: Context) {
DeviceManager.getCurrentDevice()?.let {
DataSdk.getInstance().getDownloadManager().stopAll(context,
address = it.address,
onSuccess = { },
onError = { }
)
}
DeviceManager.clearCurrentDevice(unpair = true)
}
Check the Sample app in the class WatchFragmentViewModel.kt
Next step: set up the bracelet