Upload
johnny-sung
View
1.216
Download
4
Embed Size (px)
Citation preview
EVERYTHING ABOUT BLUETOOTHJohnny Sung
02. Peripheral mode in Android
https://fb.com/j796160836
Johnny SungMobile devices Developer
https://plus.google.com/+JohnnySung
http://about.me/j796160836
(Samsung S6 Edge)Peripheral Central
(LG Nexus 5)
2.0 2.0 + 4.0 Dual Mode 4.0Bluetooth SMART READYBluetooth Bluetooth SMART
Bluetooth low energy Protocol Stack
• Peripheral
• Central
• Broadcaster
• Observer
GAP Roles
PeripheralCentral
PeripheralCentral
PeripheralCentral
GATT
• Service
• Characteristic
• Data
• Descriptor
GATT
• Heart Rate Service
• Heart Rate Measurement
• Data
• Descriptor
00002A37-0000-1000-8000-00805F9B34FB
GATT
Heart Rate Monitor
0000180D-0000-1000-8000-00805F9B34FB
Property: Notify
Property: Indicate
• Health Thermometer
• Temperature Measurement
• Data
• Descriptor
GATT
Health Thermometer
00001809-0000-1000-8000-00805F9B34FB
00002A1C-0000-1000-8000-00805F9B34FB
• Read
• Write
• Notify
• Indicate
Characteristic Properties
UUID
00002A37-0000-1000-8000-00805F9B34FB
0x2A37Heart Rate Measurement
• an indicate operation is identical to a notify operation except that indications are acknowledged, while notifications are not.
Notify vs Indicate
http://mbientlab.com/blog/bluetooth-low-energy-introduction/
https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.health_thermometer.xml
Property: Indicate
• Health Thermometer
• Temperature Measurement
• Data
• Descriptor
GATT
Health Thermometer
00001809-0000-1000-8000-00805F9B34FB
00002A1C-0000-1000-8000-00805F9B34FB
• Central
• Android 4.3 (API Level 18)
• Peripheral
• Android 5.0 (API Level 21)
• Specific BLE chip
Requirement in Android
What? Specific BLE chip ?
http://altbeacon.github.io/android-beacon-library/beacon-transmitter-devices.html
BluetoothManager manager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); BluetoothAdapter adapter = manager.getAdapter();
adapter.isMultipleAdvertisementSupported();
Check if devices support Peripheral mode
PERIPHERAL
<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"/>
Bluetooth permissions
AndroidManifest.xml
Bluetooth permissionsCheck system featuregetPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)
@Overridepublic void onActivityResult(int requestCode , int resultCode, Intent data) { if (requestCode == REQUEST_ENABLE_BT) { if (resultCode == Activity.RESULT_OK) { // Bluetooth has turned on } else { // User did not enable Bluetooth or an error occurred } }}
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
Request to enable Bluetooth
BluetoothGattService hrmService = new BluetoothGattService(SERVICE_HEALTH_THERMOMETER_UUID, BluetoothGattService.SERVICE_TYPE_PRIMARY);
BluetoothGattCharacteristic tempChar = new BluetoothGattCharacteristic(CHAR_TEMP_UUID,
BluetoothGattCharacteristic.PROPERTY_INDICATE, BluetoothGattCharacteristic.PERMISSION_READ);
tempChar.addDescriptor(new BluetoothGattDescriptor( UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"), (BluetoothGattDescriptor.PERMISSION_READ | BluetoothGattDescriptor.PERMISSION_WRITE))); hrmService.addCharacteristic(tempChar);
Prepare service structure
Health Thermometer
2A1C
1809
AdvertiseData.Builder datas = new AdvertiseData.Builder(); AdvertiseSettings.Builder settings = new AdvertiseSettings.Builder(); datas.addServiceUuid(new ParcelUuid(hrmService.getUuid()));
BluetoothLeAdvertiser advertiser = adapter.getBluetoothLeAdvertiser(); advertiser.startAdvertising(settings.build(), datas.build(), advertiseCallback);
BluetoothManager manager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); BluetoothAdapter adapter = bluetoothManager.getAdapter();
BluetoothGattServer gattServer = manager.openGattServer(context, gattServerCallback);
gattServer.addService(hrmService);
Open server
Advertise to others
AdvertiseCallback advertiseCallback = new AdvertiseCallback() { @Override public void onStartSuccess(AdvertiseSettings settingsInEffect) { // ... } @Override public void onStartFailure(int errorCode) { // ... } };
Advertise callback
private HashSet<BluetoothDevice> bleDevices = new HashSet<>(); private final BluetoothGattServerCallback gattServerCallback = new BluetoothGattServerCallback() { @Override public void onConnectionStateChange(BluetoothDevice device, int status, int newState) { super.onConnectionStateChange(device, status, newState); if (status == BluetoothGatt.GATT_SUCCESS) { if (newState == BluetoothGatt.STATE_CONNECTED) { // Connect bleDevices.add(device); } else if (newState == BluetoothGatt.STATE_DISCONNECTED) { // Disconnect bleDevices.remove(device); } } else { // Disconnect with error bleDevices.remove(device); } } // ... (略) };
Handle device connect
private final BluetoothGattServerCallback gattServerCallback = new BluetoothGattServerCallback() { // ... (略) @Override public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) { // ... gattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, characteristic.getValue()); } // ... (略) };
Reading Characteristic
Writing Characteristic
http://developer.android.com/reference/android/bluetooth/BluetoothGattServerCallback.html#onCharacteristicWriteRequest(android.bluetooth.BluetoothDevice, int, android.bluetooth.BluetoothGattCharacteristic,
boolean, boolean, int, byte[])
private final BluetoothGattServerCallback gattServerCallback = new BluetoothGattServerCallback() { // ... (略) @Override public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) { // ... ByteBuffer buffer = ByteBuffer.wrap(value); buffer.order(ByteOrder.LITTLE_ENDIAN); characteristic.setValue(buffer.getInt(), BluetoothGattCharacteristic.FORMAT_UINT16, 0); if (responseNeeded) { gattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, 0, null); } } // ... (略) };
private final BluetoothGattServerCallback mGattServerCallback = new BluetoothGattServerCallback() { // ... (略) @Override public void onDescriptorWriteRequest(BluetoothDevice device, int requestId, BluetoothGattDescriptor descriptor, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) { super.onDescriptorWriteRequest(device, requestId, descriptor, preparedWrite, responseNeeded, offset, value); if (responseNeeded) { gattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, 0, null); } } // ... (略) };
Writing Descriptor
public void sendNotificationToDevices( BluetoothGattCharacteristic characteristic) { boolean indicate = (characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_INDICATE) == BluetoothGattCharacteristic.PROPERTY_INDICATE; for (BluetoothDevice device : bleDevices) { gattServer.notifyCharacteristicChanged(device, characteristic, indicate); } }
Send Characteristic Notify
Q&A
ADDITIONAL SLIDES
The story
About Nexus 5
http://altbeacon.github.io/android-beacon-library/beacon-transmitter-devices.html
https://code.google.com/p/android-developer-preview/issues/detail?id=1570
We introduced BLE peripheral mode in Android 5.0 Lollipop. Nexus 6 and Nexus 9 are the first two production Nexus devices that support BLE peripheral mode. Due to hardware chipset dependency, older Nexus devices (4/5/7) will not have access to the feature on Lollipop.
#52 Won’t Fix