I've been stuck on this problem for quite some time and couldn't find a clear answer anywhere, so posting here.
Here's my setup:
- Android app acts as a scanner
- Multiple BLE sensors are placed in the same room
- When a sensor receives a SCAN_REQ from the phone, it starts advertising its data
- App receives that advertisement, parses it and displays it
The problem is — when the phone starts active scanning, SCAN_REQ goes to every nearby scannable sensor at the same time. All sensors trigger at once. I need only one specific sensor to trigger at a time.
What I tried:
1. ScanFilter with specific MAC address:
I passed the target sensor's MAC in ScanFilter like this:
<
val filter = ScanFilter.Builder()
.setDeviceAddress("XX:XX:XX:XX:XX:XX")
.build()
val settings = ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
.build()
bluetoothLeScanner.startScan(listOf(filter), settings, scanCallback)>
But I'm not sure if this actually restricts the SCAN_REQ at the hardware level or just filters results on the app side.
2. Sensor-side whitelisting:
Tried making the sensor respond only to my phone's MAC. But Android's BLE Advertisement API randomizes the MAC address periodically — so the sensor can never maintain a reliable whitelist.
3. GATT connection:
Not suitable for my case. Need advertisement-based communication only — no connections.
My questions:
1. Does ScanFilter with setDeviceAddress() restrict SCAN_REQ at the controller level or only on the app side?
2. Is there any Android API to control which device gets the SCAN_REQ?
3. Can we set a fixed public MAC when using Android BLE Advertisement API?
4. Is sensor firmware-side filtering the only real solution?
I believe this is a hardware/OS level limitation but would love a confirmation from someone who knows BLE internals well.
Thanks!
ScanFilter operates entirely on the host. There is no standard API or HCI command to direct a SCAN_REQ. You cannot force a public or static random address via the public API. The burden falls on the sensor firmware.