Android
Bluetooth Low Energy
Suche…
Einführung
Diese Dokumentation ist als Erweiterung der Originaldokumentation gedacht und konzentriert sich auf die neueste Bluetooth LE-API, die in Android 5.0 (API 21) eingeführt wurde. Es werden sowohl die zentralen als auch die peripheren Rollen behandelt sowie der Start des Scan- und Werbevorgangs.
BLE-Geräte suchen
Die folgenden Berechtigungen sind erforderlich, um die Bluetooth-APIs zu verwenden:
android.permission.BLUETOOTH android.permission.BLUETOOTH_ADMIN
Wenn Sie auf Geräte mit Android 6.0 ( API Level 23 ) oder höher zielen und Scan- / Werbevorgänge durchführen möchten, benötigen Sie eine Standortberechtigung:
android.permission.ACCESS_FINE_LOCATION
oder
android.permission.ACCESS_COARSE_LOCATION
Hinweis.- Bei Geräten mit Android 6.0 (API Level 23) oder höher müssen auch die Ortungsdienste aktiviert sein.
Zum Starten von Scan- / Werbevorgängen ist ein BluetoothAdapter-Objekt erforderlich:
BluetoothManager bluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
bluetoothAdapter = bluetoothManager.getAdapter();
Die startScan (ScanCallback callback)
Methode startScan (ScanCallback callback)
der BluetoothLeScanner-Klasse ist die einfachste Methode, um einen Scanvorgang zu starten. Ein ScanCallback
Objekt ist erforderlich, um Ergebnisse zu erhalten:
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());
}
});
Verbindung zu einem GATT-Server
Wenn Sie ein gewünschtes BluetoothDevice-Objekt erkannt haben, können Sie eine Verbindung mit ihm herstellen, indem Sie die Methode connectGatt()
verwenden, die als Parameter ein Context-Objekt verwendet. Ein boolescher connectGatt()
, der angibt, ob automatisch eine Verbindung zum BLE-Gerät hergestellt werden soll, und eine BluetoothGattCallback-Referenz, bei der Verbindungsereignisse und Clientvorgänge ausgeführt werden Ergebnisse werden geliefert:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
device.connectGatt(context, false, bluetoothGattCallback, BluetoothDevice.TRANSPORT_AUTO);
} else {
device.connectGatt(context, false, bluetoothGattCallback);
}
onConnectionStateChange
in BluetoothGattCallback, um Verbindungsereignisse und Verbindungsereignisse zu empfangen:
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.");
}
}
};
Schreiben und Lesen aus Merkmalen
Sobald Sie mit einem Gatt-Server verbunden sind, werden Sie mit ihm interagieren, indem Sie von den Eigenschaften des Servers aus schreiben und lesen. Dazu müssen Sie zunächst herausfinden, welche Dienste auf diesem Server verfügbar sind und welche Merkmale in den einzelnen Diensten verfügbar sind:
@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
}
}
}
}
Ein grundlegender Schreibvorgang lautet wie folgt:
characteristic.setValue(newValue);
characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
gatt.writeCharacteristic(characteristic);
Wenn der Schreibvorgang abgeschlossen ist, wird die onCharacteristicWrite
Methode Ihres BluetoothGattCallback
aufgerufen:
@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicWrite(gatt, characteristic, status);
Log.d(TAG, "Characteristic " + characteristic.getUuid() + " written);
}
Ein grundlegender Schreibvorgang lautet wie folgt:
gatt.readCharacteristic(characteristic);
Wenn der Schreibvorgang abgeschlossen ist, wird die onCharacteristicRead
Methode Ihres BluetoothGattCallback
aufgerufen:
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicRead(gatt, characteristic, status);
byte[] value = characteristic.getValue();
}
Abonnieren von Benachrichtigungen vom Gatt-Server
Sie können anfordern, vom Gatt-Server benachrichtigt zu werden, wenn der Wert eines Merkmals geändert wurde:
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 Benachrichtigungen vom Server werden in der onCharacteristicChanged
Methode Ihres BluetoothGattCallbacks empfangen:
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicChanged(gatt, characteristic);
byte[] newValue = characteristic.getValue();
}
Werbung für ein BLE-Gerät
Sie können Bluetooth LE Advertising verwenden, um Datenpakete an alle in der Nähe befindlichen Geräte zu senden, ohne zuerst eine Verbindung herstellen zu müssen. Beachten Sie, dass die Ankündigungsdaten auf 31 Bytes begrenzt sind. Werbung für Ihr Gerät ist auch der erste Schritt, um anderen Benutzern die Verbindung zu Ihnen zu ermöglichen.
Da nicht alle Geräte Bluetooth LE Advertising unterstützen, müssen Sie zunächst prüfen, ob Ihr Gerät über alle erforderlichen Voraussetzungen verfügt, um dies zu unterstützen. Anschließend können Sie ein BluetoothLeAdvertiser
Objekt initialisieren und damit den Werbevorgang starten:
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);
}
Verwendung eines Gatt-Servers
Damit Ihr Gerät als Peripheriegerät fungieren kann, müssen Sie zuerst einen BluetoothGattServer
öffnen und mit mindestens einem BluetoothGattService
und einer BluetoothGattCharacteristic
.
BluetoothGattServer server=bluetoothManager.openGattServer(context, bluetoothGattServerCallback);
BluetoothGattService service = new BluetoothGattService(SERVICE_UUID, BluetoothGattService.SERVICE_TYPE_PRIMARY);
Dies ist ein Beispiel für eine BluetoothGattCharacteristic mit vollständigen Schreib-, Lese- und Benachrichtigungsberechtigungen. Je nach Ihren Anforderungen möchten Sie möglicherweise die Berechtigungen, die Sie dieses Merkmal gewähren, genau einstellen:
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);
Der BluetoothGattServerCallback
ist für den Empfang aller Ereignisse im Zusammenhang mit Ihrem 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);
}
Wenn Sie eine Anforderung zum Schreiben / Lesen eines Merkmals oder eines Deskriptors erhalten, müssen Sie eine Antwort senden, damit die Anforderung erfolgreich abgeschlossen werden kann:
@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);
}