Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Talking to your bike and other devices (wait, what?)

Talking to your bike and other devices (wait, what?)

When it comes to connectivity between Android apps and other devices, Bluetooth is usually the way to go, right? But, how does that work, exactly? And what does the future look like in that matter, by the way?

In this talk, we're going to learn how Android applications can talk with real, consumer devices (like a smart bike!), what kind of APIs and implementation options we have for making that communication happen and what's new in terms of technologies, sensors and possibilities when it comes to communicating with real devices through your Android application!

Walmyr Carvalho

October 28, 2022

More Decks by Walmyr Carvalho

Other Decks in Technology


  1. Talking to your bike and other devices Walmyr Carvalho Senior

    Android Engineer @ VanMoof Google Developer Expert for Android @walmyrcarvalho (wait, what?)
  2. Main features • Touch Unlock: tap a button to unlock

    your bike; • Assistance level: change how much the motor helps you; • Gear shifting moments: adjust how the bike shift gears according to your needs; • Firmware updates: get the latest software updates for your bike; • Lights and Sounds: set the lights behavior and change the bell sound of your bike; • Many more! (let me demonstrate!) VanMoof App VanMoof (Google Play)
  3. <manifest> <!-- Request legacy Bluetooth permissions on older devices. -->

    <uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" /> <!-- Needed only if your app looks for Bluetooth devices. If your app doesn't use Bluetooth scan results to derive physical location information, you can strongly assert that your app doesn't derive physical location. --> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation"/> <!-- Needed only if your app makes the device discoverable to Bluetooth devices. --> <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
  4. ... <!-- Needed only if your app communicates with already-paired

    Bluetooth devices. --> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> <!-- Needed only if your app uses Bluetooth scan results to derive physical location. --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> ... </manifest>
  5. // First, you need a BluetoothAdapter: val bluetoothManager: BluetoothManager =

    getSystemService(BluetoothManager::class.java) val bluetoothAdapter: BluetoothAdapter? = bluetoothManager.getAdapter() if (bluetoothAdapter == null) { // Device doesn't support Bluetooth } // Then, you can enable Bluetooth if it's not the case: if (bluetoothAdapter?.isEnabled == false) { val enableBluetoothIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE) startActivityForResult(enableBluetoothIntent, REQUEST_ENABLE_BT) }
  6. // Once we have the adapter and BLE connection, we

    can scan for devices: private val bluetoothLeScanner = bluetoothAdapter.bluetoothLeScanner private var scanning = false private val handler = Handler() // Stops scanning after 10 seconds. private val SCAN_PERIOD: Long = 10000 private fun scanLeDevice() { if (!scanning) { // Stops scanning after a pre-defined scan period. handler.postDelayed({ scanning = false bluetoothLeScanner.stopScan(leScanCallback) }, SCAN_PERIOD) scanning = true bluetoothLeScanner.startScan(leScanCallback) } else { scanning = false bluetoothLeScanner.stopScan(leScanCallback) } }
  7. private val leDeviceListAdapter = LeDeviceListAdapter() // Device scan callback, including

    a ScanResult // which can contain one or more devices private val leScanCallback: ScanCallback = object : ScanCallback() { override fun onScanResult(callbackType: Int, result: ScanResult) { super.onScanResult(callbackType, result) leDeviceListAdapter.addDevice(result.device) leDeviceListAdapter.notifyDataSetChanged() } } // With the device, you can have the BluetoothGatt, which has the // characteristics read/write commands to interact with your device var bluetoothGatt: BluetoothGatt? = null bluetoothGatt = device.connectGatt(this, false, gattCallback) bluetoothGatt.readCharacteristic(characteristic) bluetoothGatt.writeCharacteristic(characteristic, value, writeType)
  8. • So many concepts to understand (Service, GATT, Characteristics, Advertising,

    etc) • Differences across devices OEMs and OS versions can affect how your implementation behaves on different devices; • You can experience a lot of false positives/negatives when developing for BLE; • Queueing and handling of GATT messages can be also tricky/prone to errors; • Connectivity issues is a constant ghost flying around; • Most team/companies are shipping custom solutions to address different issues; • Many small things… :') Well… Bluetooth is tricky :(
  9. RxAndroidBle • A RxJava-first approach for the whole BLE process;

    • Observables and handy classes for device scanning, adapter state and device connectivity; • Singles for read/write operations, to improve chaining in general; • Helper tools to improve logging using Timber; • We're using it in production! https://github.com/dariuszseweryn/RxAndroidBle
  10. Kable • A Kotlin Coroutines-first approach for the whole BLE

    process; • Proper DSLs for scanning, filtering and connecting with BLE devices; • KMM ready + JS support; • Custom DataProcessor for HEX intercepting and manipulation; • Many more features! https://github.com/JuulLabs/kable
  11. Companion device pairing • A better proposed approach to reach

    BLE and WiFi devices and setup a proper bonding to them; • Improves discoverability of the devices while keeping the privacy of the user; • Available for Android 8.0 and up; • Recommended if Nearby Fast Pair implementations are being planned; • The main point is that it can find devices close by without asking for the user location permission.
  12. // First you need to define how you want to

    filter the devices // PS: BluetoothLeDeviceFilter and WifiDeviceFilter are also available val deviceFilter: BluetoothDeviceFilter = BluetoothDeviceFilter.Builder() // Match only Bluetooth devices whose name matches the pattern. .setNamePattern(Pattern.compile("My device")) // Match only Bluetooth devices whose service UUID matches this pattern. .addServiceUuid(ParcelUuid(UUID(0x123abcL, -1L)), null) .build() // Once you have this filter done, you can prepare an AssociationRequest val pairingRequest: AssociationRequest = AssociationRequest.Builder() // Find only devices that match this request filter. .addDeviceFilter(deviceFilter) // Stop scanning as soon as one device matching the filter is found. .setSingleDevice(true) .build()
  13. val deviceManager = requireContext().getSystemService(Context.COMPANION_DEVICE_SERVICE) // The AssociationRequest also provides a

    callback function deviceManager.associate(pairingRequest, object : CompanionDeviceManager.Callback() { // Called when a device is found. Launch the IntentSender so the user // can select the device they want to pair with. override fun onDeviceFound(chooserLauncher: IntentSender) { startIntentSenderForResult(chooserLauncher, SELECT_DEVICE_REQUEST_CODE, null, 0, 0, 0) } override fun onFailure(error: CharSequence?) { // Handle the failure. } }, null)
  14. // When you select a device on the system popup,

    it's returned as result of the intent override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { when (requestCode) { SELECT_DEVICE_REQUEST_CODE -> when(resultCode) { Activity.RESULT_OK -> { // The user chose to pair the app with a Bluetooth device. val deviceToPair: BluetoothDevice? = data?.getParcelableExtra(CompanionDeviceManager.EXTRA_DEVICE) deviceToPair?.let { device -> device.createBond() // Continue to interact with the paired device. } } } else -> super.onActivityResult(requestCode, resultCode, data) } }
  15. Emulated Bluetooth • Supports two emulated Bluetooth devices with Virtual

    Bluetooth; • Available on Android Emulator 31.3.8 and system images with API 33 (T); • Planned to improve Bluetooth integration test with emulated devices; • There're some plans to add different devices in the future, such as heart rate monitors and beacons! Source: Android Developers Blog
  16. Google Nearby / Fast Pair • Improving out of box

    experience for devices ("AirPods"-like); • Relies on CDM to improve BLE pairing; • Documentation and implementation reference available both for Android and device manufacturers; • Currently most used for headphones, but some manufacturers are already using it for different boards. https://developers.google.com/nearby Source: Google
  17. Ultra-wide band (early) support • Some initial API support already

    in Jetpack (androidx.core.uwb, version 1.0.0-alpha3) • Some companies are already selling some developer devices with UWB support, like Estimote. • Some Android devices are already supporting them, but not many (Pixel 6 Pro, Galaxy Note 20 and Galaxy S22 Plus/Ultra) • Widely adopted by Apple with Find My / AirTags; • Ideal for contextual connections, like vehicle unlocking, object finding, etc; • Seems like the future of connectivity, but still yet to come on Android platform. Source: Estimote
  18. Go with BLE, but watch the future! • Connected devices

    are cool to work with it, but tricky sometimes (which is fine); • BLE is the industry standard for connected devices, (at least for now); • Google is definitely aware of the challenges around it, and things are getting better! <3 • Fast Pair is already a reality for plenty of products, so definitely check it out; • UWB is promising to be a good replacement for BLE in the future, but it's still yet to come!
  19. Thank you and have a nice conference! ❤ Walmyr Carvalho

    Senior Android Engineer @ VanMoof Google Developer Expert for Android @walmyrcarvalho
  20. BLE Content Recommendation Bluetooth LE for Modern Android Development, by

    Erik Hellman Droidcon Berlin 2021 State of BLE on Android in 2022, by Erik Hellman Droidcon London 2022 (aka tomorrow)
  21. Reference Links • Talk - Bluetooth LE for Modern Android

    Development - droidcon Berlin 2021 • Slides - Bluetooth LE for Modern Android Development - droidcon Berlin 202 • GitHub - Android X (Bluetooth) • Ultra-wideband (UWB) communication | Android Developers • Core Ultra Wideband (UWB) | Android Developers • Google Fast Pair Service • Google I/O 2022: What’s new in Android Development Tools Slides available here: tinyurl.com/dcldn22-talk-walmyr Soon available on SpeakerDeck as well!