What to watch out for in Android Bluetooth apps
Once you read through the Android Bluetooth APIs and start coding an integration, it's not uncommon to see some interesting issues and behavior with your device.
To save time chasing down problems - and also save your sanity - here are some things to know about the Android Bluetooth stack
- Bluetooth operations can fail if API calls are too close together
Android Bluetooth APIs work best when using the callbacks provided. Not waiting for each call to complete can cause the Bluetooth stack to get into an unexpected state. Most likely you will see periodic failures with connections, reads, and writes, and the GATT Error 133 will start showing up in the logs.
Note: even things like setting MTU size and registering for notifications or indications need to happen one at a time. - Allow time for disconnects to complete
This is a specific use case, but worth noting. Android Bluetooth APIs will indicate that a device has disconnected - perhaps the device is out of range, or the app itself called disconnect+close.
If the app has called disconnect - an soon after tries to reconnect, the connection may fail. Android has a 5 second supervisor timeout whose job is to ensure traffic is actually stopped between the device and app. Connecting before that timeout can lead to failed re-connects. - Allow time for scanning to start before stopping (and vice-versa)
This recommendation is just based on experience, but toggling scan state too quickly can lead to inconsistent scan states. e.g. attempting to stop a scan right after it was started may not actually work.
Speaking of scanning - Android limits scans to 5 per 30s.
- Leaving scanning running while connecting to a device sometimes causes connection issues.
This will vary by device manufacturer - sometimes leaving scanning running while connecting will be ok. Again, it's just something to be aware of. - Scanning and connecting in the background is limited
The documentation states background scanning will be paused unless using a ScanFilter. If possible, use a ScanFilter configured to look for your device's service class (adverisement packet value 0x07).
Earlier versions of Android would allow apps to scan indefinitely in the background, regardless of filter.
In Android 8 and above, Android apps were limted to running services in the background for 10 minutes.
The ForegroundService became the go-to for keeping Bluetooth scanning running in the foreground (via an always-on notification).
However, Android 12 added new rules to when a ForegroundService can be started - most notably that it cannot be started in the background.
The ForegroundService may or may not fit your use case for keeping long running BLE tasks.
If not, consider not using Android Services altogether. This recent article by David Young sheds some more light on how to perform long running BLE operations without Foreground (or other) services.