Android Bluetooth Hello World
Jumping into the world of Bluetooth LE and was having a hard time finding a barebones, hello world style resource. With many of the tutorials I’ve seen, they cloud the minimal BLE code with permissions, ui and architecture. I like to start with the minimal possible code and build from there. Here’s my go at it.
Minimal code to scan for Bluetooth devices. Don’t forget to allow Nearby Devices Permission in the App info.
The Kotlin code below starts the Bluetooth LE scanning process when the Start BLE Scan button is pressed.
The scanning is done via the bleScanner which is passed in the scanSettings and scanCallback object.
The scanCallback has barebones functionality to print the name and address of an advertising BLE server.
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Column(
Modifier.padding(all = 8.dp)
) {
Text(text = "Scan for Bluetooth LE devices")
Spacer(modifier = Modifier.height(8.dp))
Button(onClick = {
startBleScan()
}) {
Text(text = "Start BLE Scan")
}
}
}
}
@SuppressLint("MissingPermission")
private fun startBleScan() {
Log.d("mgm", "start Bluetooth scan")
bleScanner.startScan(null, scanSettings, scanCallback)
}
@SuppressLint("MissingPermission")
private val scanCallback = object : ScanCallback() {
override fun onScanResult(callbackType: Int, result: ScanResult) {
val device = result.device
if (device == null) {
return
}
val name: String? = result.scanRecord?.deviceName ?: "result.device.name"
val info = "$now name=$name address= ${device.name}"
Log.d("mgm", "onScanResult $info")
}
override fun onScanFailed(errorCode: Int) {}
}
private val bleScanner by lazy {
bluetoothAdapter.bluetoothLeScanner
}
private val bluetoothAdapter: BluetoothAdapter by lazy {
(this.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager).adapter
}
private val scanSettings = ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_BALANCED)
.setReportDelay(0)
.build()
}
The scans can come across pretty quickly, code to pick out specific devices can help focus on individual or groupings of devices. The code below can replace the single Log.d line in the scanCallback.onScanResult method to filter out devices whose name contains “GoDice” which are Bluetooth enabled 6 sided dice.
if (name?.contains("GoDice") == true) {
val now = Calendar.getInstance().time
val info = "$now name=$name address= ${device.name}"
Log.d("mgm", "onScanResult $info")
}
The result of this code can be seen in the following YouTube short from my developer YouTube channel.