Android SBeacon Framework Beacon Pairing - scopetech/Mobile-Public GitHub Wiki

Beacon Pairing

SBeacon SDK v1.6.13

This guide covers pairing and unpairing SBeacon devices, connection management, and monitoring connection state.


Pair a Beacon

private fun pairBeacon(beacon: ScopeBeacon, subscriptionId: Int = 0, serialNumber: String = "") {
    lifecycleScope.launch(Dispatchers.IO) {
        try {
            val bleManager = BLEManager.retrieveInstance(requireContext())

            // Pair the beacon
            bleManager.pairBeacon(beacon, subscriptionId, serialNumber)

            Timber.i("Paired beacon: ${beacon.macAddress}")

            withContext(Dispatchers.Main) {
                Toast.makeText(context, "Beacon paired successfully", Toast.LENGTH_SHORT).show()
            }
        } catch (e: Exception) {
            Timber.e(e, "Failed to pair beacon")
        }
    }
}

Parameters

Parameter Type Description
beacon ScopeBeacon The beacon object from scan results
subscriptionId Int Optional subscription identifier (use 0 if not applicable)
serialNumber String Optional device serial number (use empty string if not applicable)

Unpair a Beacon

private fun unpairBeacon(beacon: ScopeBeacon) {
    lifecycleScope.launch(Dispatchers.IO) {
        try {
            BLEManager.retrieveInstance(requireContext()).unpairBeacon(beacon)
            Timber.i("Unpaired beacon: ${beacon.macAddress}")

            withContext(Dispatchers.Main) {
                Toast.makeText(context, "Beacon unpaired", Toast.LENGTH_SHORT).show()
            }
        } catch (e: Exception) {
            Timber.e(e, "Failed to unpair beacon")
        }
    }
}

Connection Status

Check if a Specific Beacon is Connected

val isConnected = BLEManager.retrieveInstance(context).isBeaconConnected(beacon)

Check if Any Paired Beacon is Connected

val hasSingleConnection = BLEManager.retrieveInstance(context).singleBeaconConnection()

Connection Events

Subscribe to connection events using IBFHelper.EventsReceiver:

private val beaconEventsReceiver = object : IBFHelper.EventsReceiver() {

    override fun onBeaconConnected(mac: String) {
        lifecycleScope.launch(Dispatchers.Main) {
            updateConnectionStatus(mac, connected = true)
        }
    }

    override fun onBeaconDisconnected(mac: String) {
        lifecycleScope.launch(Dispatchers.Main) {
            updateConnectionStatus(mac, connected = false)
        }
    }

    override fun onBeaconPaired(name: String) {
        Timber.i("Beacon paired: $name")
    }

    override fun onBeaconUnpaired(name: String) {
        Timber.i("Beacon unpaired: $name")
    }
}

override fun onResume() {
    super.onResume()
    IBFHelper.registerEventsReceiver(requireContext(), beaconEventsReceiver)
}

override fun onPause() {
    super.onPause()
    IBFHelper.unregisterEventsReceiver(requireContext(), beaconEventsReceiver)
}

Connection Events Reference

Event Description
MyCarDetected Paired SBeacon connected and recognized
MyCarNotDetected Paired SBeacon disconnected
onBeaconConnected(mac) SBeacon connected
onBeaconDisconnected(mac) SBeacon disconnected
onBeaconPaired(name) SBeacon pairing completed
onBeaconUnpaired(name) SBeacon unpairing completed

Auto-Connection

The SDK automatically attempts to reconnect to paired beacons. To manually trigger reconnection:

BLEManager.retrieveInstance(context).runAutoConnectionTask()

Disconnect from All Beacons

lifecycleScope.launch(Dispatchers.IO) {
    BLEManager.retrieveInstance(context).disconnectFromAllBeacons()
}

Data Persistence

Paired beacons are automatically persisted to local storage using Room database. They remain paired across app restarts:

// Get all stored beacons (paired and unpaired)
val allBeacons = BLEManager.retrieveInstance(context).allBeacons()

// Get only paired beacons
val pairedBeacons = allBeacons.filter { it.paired }

Best Practices

Threading

Always perform pairing/unpairing operations on IO dispatcher:

lifecycleScope.launch(Dispatchers.IO) {
    bleManager.pairBeacon(beacon, subscriptionId, serialNumber)
}

Error Handling

Wrap pairing operations in try-catch:

try {
    bleManager.pairBeacon(beacon, subscriptionId, serialNumber)
} catch (e: Exception) {
    Timber.e(e, "Pairing failed")
    // Show error to user
}

Single Beacon Mode

If your app supports only one paired beacon at a time, unpair existing beacons before pairing a new one:

// Unpair all existing beacons
val existingPaired = bleManager.allBeacons().filter { it.paired }
existingPaired.forEach { bleManager.unpairBeacon(it) }

// Then pair the new beacon
bleManager.pairBeacon(newBeacon, subscriptionId, serialNumber)

Next Steps