Android
Bluetooth Low Energy
Zoeken…
Invoering
Deze documentatie is bedoeld als een verbetering van de originele documentatie en zal zich richten op de nieuwste Bluetooth LE API geïntroduceerd in Android 5.0 (API 21). Zowel centrale als perifere rollen komen aan bod, evenals hoe te beginnen met scannen en adverteren.
BLE-apparaten zoeken
De volgende machtigingen zijn vereist om de Bluetooth API's te gebruiken:
android.permission.BLUETOOTH android.permission.BLUETOOTH_ADMIN
Als u apparaten met Android 6.0 ( API-niveau 23 ) of hoger target en scan- / advertentiebewerkingen wilt uitvoeren, hebt u een locatietoestemming nodig:
android.permission.ACCESS_FINE_LOCATION
of
android.permission.ACCESS_COARSE_LOCATION
Opmerking. - Apparaten met Android 6.0 (API Level 23) of hoger moeten ook Location Services hebben ingeschakeld.
Een BluetoothAdapter-object is vereist om scan- / reclamebewerkingen te starten:
BluetoothManager bluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
bluetoothAdapter = bluetoothManager.getAdapter();
De startScan (ScanCallback callback)
methode startScan (ScanCallback callback)
van de BluetoothLeScanner-klasse is de eenvoudigste manier om een scanbewerking te starten. Een ScanCallback
object is vereist om resultaten te ontvangen:
bluetoothAdapter.getBluetoothLeScanner().startScan(new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
super.onScanResult(callbackType, result);
Log.i(TAG, "Remote device name: " + result.getDevice().getName());
}
});
Verbinding maken met een GATT-server
Nadat u een gewenst BluetoothDevice-object hebt ontdekt, kunt u er verbinding mee maken door de methode connectGatt()
gebruiken die als parameters een Context-object, een Boolean neemt die aangeeft of er automatisch verbinding moet worden gemaakt met het BLE-apparaat en een BluetoothGattCallback-referentie bij verbindingsgebeurtenissen en clientbewerkingen resultaten worden geleverd:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
device.connectGatt(context, false, bluetoothGattCallback, BluetoothDevice.TRANSPORT_AUTO);
} else {
device.connectGatt(context, false, bluetoothGattCallback);
}
Overschrijven onConnectionStateChange
in BluetoothGattCallback om verbindings- en verbreekgebeurtenissen te ontvangen:
BluetoothGattCallback bluetoothGattCallback =
new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status,
int newState) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
Log.i(TAG, "Connected to GATT server.");
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
Log.i(TAG, "Disconnected from GATT server.");
}
}
};
Schrijven en lezen van kenmerken
Zodra u bent verbonden met een Gatt-server, gaat u ermee communiceren door te schrijven en lezen van de kenmerken van de server. Om dit te doen, moet u eerst ontdekken welke services beschikbaar zijn op deze server en welke kenmerken beschikbaar zijn in elke service:
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status,
int newState) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
Log.i(TAG, "Connected to GATT server.");
gatt.discoverServices();
}
. . .
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
List<BluetoothGattService> services = gatt.getServices();
for (BluetoothGattService service : services) {
List<BluetoothGattCharacteristic> characteristics = service.getCharacteristics();
for (BluetoothGattCharacteristic characteristic : characteristics) {
///Once you have a characteristic object, you can perform read/write
//operations with it
}
}
}
}
Een eenvoudige schrijfbewerking gaat als volgt:
characteristic.setValue(newValue);
characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
gatt.writeCharacteristic(characteristic);
Wanneer het schrijfproces is voltooid, wordt de onCharacteristicWrite
methode van uw BluetoothGattCallback
genoemd:
@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicWrite(gatt, characteristic, status);
Log.d(TAG, "Characteristic " + characteristic.getUuid() + " written);
}
Een eenvoudige schrijfbewerking gaat als volgt:
gatt.readCharacteristic(characteristic);
Wanneer het schrijfproces is voltooid, wordt de methode onCharacteristicRead
van uw BluetoothGattCallback
genoemd:
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicRead(gatt, characteristic, status);
byte[] value = characteristic.getValue();
}
Abonneren op meldingen van de Gatt-server
U kunt vragen om een melding van de Gatt Server wanneer de waarde van een kenmerk is gewijzigd:
gatt.setCharacteristicNotification(characteristic, true);
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(descriptor);
Alle meldingen van de server worden ontvangen in de onCharacteristicChanged
methode van uw BluetoothGattCallback:
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicChanged(gatt, characteristic);
byte[] newValue = characteristic.getValue();
}
Adverteren voor een BLE-apparaat
U kunt Bluetooth LE Advertising gebruiken om datapakketten naar alle apparaten in de buurt uit te zenden zonder eerst een verbinding tot stand te brengen. Houd er rekening mee dat er een strikte limiet van 31 bytes aan advertentiegegevens is. Het adverteren voor uw apparaat is ook de eerste stap om andere gebruikers verbinding met u te laten maken.
Aangezien niet alle apparaten Bluetooth LE Advertising ondersteunen, is de eerste stap om te controleren of uw apparaat alle benodigde vereisten heeft om het te ondersteunen. Daarna kunt u een BluetoothLeAdvertiser
object initialiseren en hiermee kunt u beginnen met adverteren:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && bluetoothAdapter.isMultipleAdvertisementSupported())
{
BluetoothLeAdvertiser advertiser = bluetoothAdapter.getBluetoothLeAdvertiser();
AdvertiseData.Builder dataBuilder = new AdvertiseData.Builder();
//Define a service UUID according to your needs
dataBuilder.addServiceUuid(SERVICE_UUID);
dataBuilder.setIncludeDeviceName(true);
AdvertiseSettings.Builder settingsBuilder = new AdvertiseSettings.Builder();
settingsBuilder.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_POWER);
settingsBuilder.setTimeout(0);
//Use the connectable flag if you intend on opening a Gatt Server
//to allow remote connections to your device.
settingsBuilder.setConnectable(true);
AdvertiseCallback advertiseCallback=new AdvertiseCallback() {
@Override
public void onStartSuccess(AdvertiseSettings settingsInEffect) {
super.onStartSuccess(settingsInEffect);
Log.i(TAG, "onStartSuccess: ");
}
@Override
public void onStartFailure(int errorCode) {
super.onStartFailure(errorCode);
Log.e(TAG, "onStartFailure: "+errorCode );
}
};
advertising.startAdvertising(settingsBuilder.build(),dataBuilder.build(),advertiseCallback);
}
Een Gatt-server gebruiken
Om uw apparaat als randapparaat te laten werken, moet u eerst een BluetoothGattServer
en deze vullen met ten minste één BluetoothGattService
en één BluetoothGattCharacteristic
:
BluetoothGattServer server=bluetoothManager.openGattServer(context, bluetoothGattServerCallback);
BluetoothGattService service = new BluetoothGattService(SERVICE_UUID, BluetoothGattService.SERVICE_TYPE_PRIMARY);
Dit is een voorbeeld van een BluetoothGattCharacteristic met volledige schrijf-, lees- en kennisgevingsrechten. Afhankelijk van uw behoeften, wilt u misschien de machtigingen die u aan dit kenmerk verleent, verfijnen:
BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(CHARACTERISTIC_UUID,
BluetoothGattCharacteristic.PROPERTY_READ | BluetoothGattCharacteristic.PROPERTY_WRITE |
BluetoothGattCharacteristic.PROPERTY_NOTIFY,
BluetoothGattCharacteristic.PERMISSION_READ | BluetoothGattCharacteristic.PERMISSION_WRITE);
characteristic.addDescriptor(new BluetoothGattDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"), BluetoothGattCharacteristic.PERMISSION_WRITE));
service.addCharacteristic(characteristic);
server.addService(service);
De BluetoothGattServerCallback
is verantwoordelijk voor het ontvangen van alle gebeurtenissen met betrekking tot uw BluetoothGattServer
:
BluetoothGattServerCallback bluetoothGattServerCallback= new BluetoothGattServerCallback() {
@Override
public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
super.onConnectionStateChange(device, status, newState);
}
@Override
public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicReadRequest(device, requestId, offset, characteristic);
}
@Override
public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
super.onCharacteristicWriteRequest(device, requestId, characteristic, preparedWrite, responseNeeded, offset, value);
}
@Override
public void onDescriptorReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattDescriptor descriptor) {
super.onDescriptorReadRequest(device, requestId, offset, descriptor);
}
@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);
}
Wanneer u een verzoek tot schrijven / lezen ontvangt voor een kenmerk of descriptor, moet u een antwoord erop sturen om het verzoek te kunnen voltooien:
@Override
public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicReadRequest(device, requestId, offset, characteristic);
server.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, YOUR_RESPONSE);
}