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

ITT 2015 - Hugo Domenech-Juarez - What's All Th...

ITT 2015 - Hugo Domenech-Juarez - What's All That Hype About BLE?

Hugo Domenech-Juarez discusses about the possibilities that Android provides by using BLE to connect to sensors and actuators around you. He shares some tips and tricks learned from building a SDK for interacting with the WunderBar, a BLE enabled starter kit for the Internet of Things, and his experiences on how to make your connections secure and fast.

Istanbul Tech Talks

April 27, 2015
Tweet

More Decks by Istanbul Tech Talks

Other Decks in Programming

Transcript

  1. 3

  2. 4

  3. 5

  4. 6

  5. 7

  6. 10

  7. 11

  8. 12

  9. Eclair 2.0 (API 5) BlueZ Android 1.x 4.3 (API 18)

    Bluedroid JellyBean Bluetooth Smart 5.0 (API 20) Lollipop Full BLE Older Broadcom stack - Samsung & HTC < 4.0 Motorola Bluetooth Stack 17
  10. 20

  11. BLE Scanning private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() { @Override

    public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) { // You are not in the UI thread // or in the thread you subscribed for what matters! } }; 25
  12. BLE Scanning /** * Decodes the services uuid from the

    advertisement packet since * {@link android.bluetooth.BluetoothDevice#getUuids()} returns null most of * the times. */ public static List<String> decodeServicesUuid(byte[] data); /** * Decodes the device name from the Complete Local Name or Shortened * Local Name field in the * Advertisement packet. {@link * android.bluetooth.BluetoothDevice#getName()} does it already, * although some phones skip it. i.e. Sony Xperia Z1 (C6903) with Android 4.3 * where getName() always returns <code>null</code>. */ public static String decodeDeviceName(byte[] data); 26
  13. BLE Scanning: Lollipop improvements mBluetoothAdapter.startScan(filters, scanSettings, scanCallback) name deviceAddress uuid

    serviceDataUuid serviceData manufacturerId manufacturerData Low Power Balanced Low Latency 27
  14. interface ScanCallback { public void onScanResult(int callbackType, ScanResult result); public

    void onBatchScanResults(List<ScanResult> results); public void onScanFailed(int errorCode) } BLE Scanning: Lollipop improvements 28
  15. Advertisement GATT server Hardware feature - chipset needs to support

    it - nexus 9 vs nexus 5 & 7 BluetoothAdapter.isMultipleAdvertisementSupported() Peripheral mode: Lollipop features 29
  16. The GATT Protocol Peripheral Central Read - Write - Subscribe

    Respond - Push GATT Peripheral GATT protocol Service Service Characteristic Characteristic Value Indications Notifications Descriptor Descriptor Descriptor 31 Server Client Generic Attribute Profile
  17. The GATT Protocol class BluetoothAdapterLeScanCallback { void onLeScan(BluetoothDevice device, int

    rssi, byte[] scanRecord) { device.connectGatt(context, false, mBluetoothGattReceiver); } } class BluetoothGattReceiver { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {} } 32
  18. 36

  19. 37

  20. 38

  21. Data subscriptions: Indication / Notification gatt.setCharacteristicNotification(characteristic, enable); descriptor.setValue(ENABLE_NOTIFICATION_VALUE); gatt.writeDescriptor(descriptor); gatt.setCharacteristicNotification(characteristic,

    enable); descriptor.setValue(ENABLE_INDICATION_VALUE); gatt.writeDescriptor(descriptor); gatt.setCharacteristicNotification(characteristic, enable); descriptor.setValue(DISABLE_NOTIFICATION_VALUE); gatt.writeDescriptor(descriptor); @Override public void onCharacteristicChanged( BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { } 39
  22. Reliable Write ?= Long Write gatt.beginReliableWrite(); characteristic.setValue(data); gatt.reliableWriteCharacteristic(mBluetoothGatt, characteristic, subscriber);

    gatt.executeReliableWrite(); 40 18 byte: 16 bytes content + 1 offset + 1 length package Regular Write supports 18 bytes
  23. Disconnecting GATT vs Closing GATT gatt.disconnect(); @Override public void onConnectionStateChange(BluetoothGatt

    gatt, int status, int newState) { if (newState == STATE_DISCONNECTED && noLongerInterestedInTheDevice) { gatt.close(); } } gatt.close(); 41
  24. Stack metrics: why you should close your GATT - Constants

    defined in BlueDroid - Max concurrent active notifications - BTA_GATTC_NOTIF_REG_MAX - (4) Android 4.3 - (7) Android 4.4 - (15) Android 5.0+ - Max concurrent GATT connections - BTA_GATTC_CON_MAX - (4) Android 4.3 - (7) Android 4.4+ 42
  25. Security: Instability static class UndocumentedBleStuff { static boolean isUndocumentedErrorStatus(int status)

    { return status == 133 || status == 137; } static void fixUndocumentedBleStatusProblem(BluetoothGatt gatt, BluetoothGattReceiver receiver) { DeviceCompatibilityUtils.refresh(gatt); gatt.getDevice().connectGatt(RelayrApp.get(), false, receiver); } } GATT_INSUFFICIENT_AUTHENTICATION GATT_INSUFFICIENT_ENCRYPTION 45
  26. Security: Instability boolean refresh(BluetoothGatt gatt) { try { Method localMethod

    = gatt.getClass().getMethod("refresh", new Class[0]); if (localMethod != null) { return (Boolean) localMethod.invoke(gatt); } } catch (Exception localException) { Log.e(TAG, "An exception occurred while performing: refresh”, localException.getCause()); } return false; } 46
  27. Security: Instability class DeviceCompatibilityUtils { boolean createBond(BluetoothDevice device) { if

    (isSdk19()) return doCreateBond(device); return callMethod(device, "createBond"); } @TargetApi(Build.VERSION_CODES.KITKAT) boolean doCreateBond(BluetoothDevice device) { return device.createBond(); } boolean removeBond(BluetoothDevice device) { return callMethod(device, "removeBond"); } } 47
  28. 50

  29. 52