Declare permissions in AndroidManifest.xml <uses-permission android:name="android.permission.BLUETOOTH"/> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/> <uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/> Require Bluetooth BLE if essential to the app
Get the Bluetooth Adapter BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); mBluetoothAdapter = bluetoothManager.getAdapter(); (but…this also works) mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) { Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); } Check that bluetooth is enabled
of device public boolean startLeScan (UUID[] serviceUuids, BluetoothAdapter.LeScanCallback callback) Does not work with 128 bit UUIDs Solution: DIY filtering stackoverflow.com/questions/18019161/startlescan-with-128-bit- uuids-doesnt-work-on-native-android-ble-implementation 14
of results* Power modes* ParcelUuid uuid = ParcelUuid.fromString("a495ff10-c5b1-4b44-b512-1370f02d74de"); BluetoothManager bm = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE); BluetoothAdapter adapter = bm.getAdapter(); ScanFilter scanFilter = new Builder().setServiceUuid(uuid).build(); ScanSettings settings = new ScanSettings.Builder().build(); * this asterix might spoil the party 16
new ScanCallback() { @Override public void onScanResult(int callbackType, ScanResult result) { // process the result, there's currently only one callbackType defined } @Override public void onBatchScanResults(List<ScanResult> results) { // terms and conditions apply } @Override public void onScanFailed(int errorCode) { // handle error based on the errorCode! } }); 17
BluetoothDevice device = ... // obtained from scanning device.connectGatt(this, false, new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { if (status == BluetoothGatt.GATT_SUCCESS) { if (newState == BluetoothGatt.STATE_CONNECTED) { if (!gatt.discoverServices()) { // requesting service failed, make sure we clean up gatt.close(); } } } else { // connection failed, clean up gatt.close(); } } public void onServicesDiscovered(BluetoothGatt gatt, int status) { // find the service we like to use mSerialService = gatt.getService(BEAN_SERIAL_CHARACTERISTIC_UUID); if (mSerialService == null) { // service is not found, close the client gatt.close(); } } }); 23
void write(byte[] data) { mCharacteristic.setValue(data); if (!mGatt.writeCharacteristic(mCharacteristic)) { mGatt.close(); } // important: wait for onCharacteristicWrite callback before attempting the next write! } 29
design the Bean SDK does a lot of writing Split data in 20 byte packets, write to characteristic Assemble packets from notifications Single characteristic for read/write makes it harder 30
full support for BLE, maturing in Lollipop The BLE related API’s are really low level Error checking all over the place Documentation could use some work 31
multiple characteristics in a single callback. Low level interface seems straightforward, but is difficult to get right. Bean SDK has GattClient to solve some of those problems 32