BluetoothGatt — was es ist, Methoden und GATT-BLE-Protokoll in Android

Autor: IT Sectr Veröffentlicht: 2026-07-16 Lesezeit: 10 Min.

BluetoothGatt ist eine Android-Klasse, die eine API für GATT-Client-Operationen (Generic Attribute Profile) über eine BLE-Verbindung bereitstellt. BluetoothGatt kapselt die Verbindung zu einem entfernten GATT-Server (peripheres BLE-Gerät) und verwaltet alle Profiloperationen: Service-Discovery, Lesen und Schreiben von Characteristics, Abonnieren von Benachrichtigungen und Indikationen. Eine BluetoothGatt-Instanz wird über BluetoothDevice.connectGatt() mit einem BluetoothGattCallback erhalten. Laut Android Developers, 2026 ist BluetoothGatt die zentrale Klasse für bidirektionale BLE-Kommunikation und unterstützt GATT-Operationen von BLE 4.0 bis BLE 5.4.

Wichtige Punkte

  • BluetoothGatt ist eine Android-Klasse für den GATT-Client, die die BLE-Verbindung mit einem peripheren Gerät verwaltet
  • connectGatt() ist eine BluetoothDevice-Methode zum Erstellen von BluetoothGatt; sie akzeptiert Kontext, autoConnect, Callback und Transport
  • discoverServices() ist eine Methode zum Abrufen der GATT-Hierarchie: Dienste (BluetoothGattService), Characteristics (BluetoothGattCharacteristic)
  • readCharacteristic/writeCharacteristic sind Lese- und Schreibmethoden mit asynchronem Ergebnis über BluetoothGattCallback
  • setCharacteristicNotification ist eine Methode zum Abonnieren von BLE-Benachrichtigungen mit obligatorischem Schreiben des CCCD-Descriptors

Was ist BluetoothGatt: Wesen und Verbindungsaufbau

BluetoothGatt ist ein Proxy-Objekt, das eine GATT-Verbindung zwischen einem Android-Gerät (Central) und einem BLE-Peripheriegerät (Server) darstellt. Jede BluetoothGatt-Instanz entspricht einer aktiven BLE-Verbindung. Alle GATT-Profiloperationen werden darüber ausgeführt: Discovery, Lesen, Schreiben, Benachrichtigungen. BluetoothGatt wird nicht direkt erstellt — es wird von der Methode BluetoothDevice.connectGatt() zurückgegeben.

Das Erstellen eines BluetoothGatt erfordert vier Parameter. Context — der Anwendungskontext (Activity oder Application). autoConnect — bei false initiiert Android sofort eine direkte Verbindung; bei true verbindet Android automatisch, wenn das Gerät erkannt wird (nützlich für Hintergrundverbindungen). BluetoothGattCallback — obligatorischer Callback für alle GATT-Ereignisse. transport — BluetoothDevice.TRANSPORT_LE (BLE) oder TRANSPORT_BREDR (Classic). Verwenden Sie bei BLE-Geräten immer TRANSPORT_LE.

BluetoothGatt-Lebenszyklus besteht aus fünf Zuständen. DISCONNECTED — Anfangszustand. CONNECTING — nach dem Aufruf von connectGatt, vor der Bestätigung. CONNECTED — nach onConnectionStateChange mit STATE_CONNECTED. Nach der Verbindung wird discoverServices() aufgerufen, um die GATT-Hierarchie zu erhalten. Nach Abschluss der Arbeit — disconnect() und close() zur Freigabe von Systemressourcen. Ohne close() kann die Anwendung das BLE-Verbindungslimit von Android (normalerweise 4–8) erschöpfen.

kotlin
// BluetoothGatt-Verbindung wird hergestellt
import android.bluetooth.*

class GattConnector(private val context: Context) {

    private var bluetoothGatt: BluetoothGatt? = null

    fun connect(device: BluetoothDevice): BluetoothGatt? {
        // Vorherige Verbindung schließen, falls vorhanden
        close()

        bluetoothGatt = device.connectGatt(
            context,
            false,  // autoConnect = false ( )
            object : BluetoothGattCallback() {
                override fun onConnectionStateChange(
                    gatt: BluetoothGatt, status: Int, newState: Int
                ) {
                    when (newState) {
                        BluetoothProfile.STATE_CONNECTED -> {
                            // 2. Verbindung hergestellt → Discovery
                            gatt.discoverServices()
                        }
                        BluetoothProfile.STATE_DISCONNECTED -> {
                            // 3. Verbindung verloren
                            close()
                        }
                    }
                }

                override fun onServicesDiscovered(
                    gatt: BluetoothGatt, status: Int
                ) {
                    if (status == BluetoothGatt.GATT_SUCCESS) {
                        // 4. GATT-Hierarchie empfangen
                        onGattReady(gatt)
                    }
                }
            },
            BluetoothDevice.TRANSPORT_LE
        )
        return bluetoothGatt
    }

    private fun onGattReady(gatt: BluetoothGatt) {
        // GATT bereit für Lese-/Schreiboperationen
    }

    fun close() {
        bluetoothGatt?.disconnect()
        bluetoothGatt?.close()
        bluetoothGatt = null
    }
}

Die Klasse GattConnector demonstriert die korrekte BluetoothGatt-Erstellung. Der Parameter autoConnect=false bedeutet eine direkte Verbindung (für gescannte Geräte). Bei onConnectionStateChange mit STATE_CONNECTED wird sofort discoverServices() aufgerufen. onServicesDiscovered signalisiert, dass GATT bereit ist. close() ruft nacheinander disconnect() und close() auf — ohne close() werden Systemressourcen nicht freigegeben, was zu BLE-Verbindungslecks führt.

Service- und Characteristic-Discovery über BluetoothGatt

discoverServices() ist die erste GATT-Methode, die nach der Verbindung aufgerufen wird. Sie initiiert eine asynchrone Suche aller Dienste auf dem BLE-Peripheriegerät. Das Ergebnis kommt in onServicesDiscovered() mit einem Statuscode: GATT_SUCCESS (0) — Erfolg, 133 — GATT_ERROR, 8 — GATT_CONNECTION_TIMEOUT. Nach erfolgreichem Discovery füllt BluetoothGatt die Liste der über getServices() zugänglichen Dienste.

Jeder BluetoothGattService enthält eine Liste von BluetoothGattCharacteristic. Ein Characteristic hat eine UUID, Eigenschaften (PROPERTY_READ, PROPERTY_WRITE, PROPERTY_NOTIFY) und optionale Descriptoren. Die Eigenschaften bestimmen, welche Operationen erlaubt sind: wenn ein Characteristic nicht PROPERTY_READ hat, gibt readCharacteristic einen Fehler zurück. Verwenden Sie getDescriptors() um die Descriptoren eines Characteristics zu erhalten.

kotlin
// Service-Discovery und Characteristic-Suche
class GattServiceExplorer {

    // Service per UUID finden
    fun findService(gatt: BluetoothGatt, uuid: UUID): BluetoothGattService? {
        return gatt.services?.firstOrNull { it.uuid == uuid }
    }

    // Characteristic im Service finden
    fun findCharacteristic(
        service: BluetoothGattService,
        uuid: UUID
    ): BluetoothGattCharacteristic? {
        return service.characteristics?.firstOrNull { it.uuid == uuid }
    }

    // Alle unterstützten Characteristic-Operationen abrufen
    fun getCharacteristicProperties(chars: BluetoothGattCharacteristic): List<String> {
        val props = mutableListOf<String>()
        with(chars.properties) {
            if (and(BluetoothGattCharacteristic.PROPERTY_READ) != 0) props.add("READ")
            if (and(BluetoothGattCharacteristic.PROPERTY_WRITE) != 0) props.add("SCHREIBEN")
            if (and(BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) != 0) props.add("SCHREIBEN_OHNE_ANTWORT")
            if (and(BluetoothGattCharacteristic.PROPERTY_NOTIFY) != 0) props.add("NOTIFY")
            if (and(BluetoothGattCharacteristic.PROPERTY_INDICATE) != 0) props.add("INDICATE")
        }
        return props
    }

    // Gesamte GATT-Hierarchie protokollieren
    fun dumpGattTree(gatt: BluetoothGatt) {
        gatt.services?.forEach { service ->
            print("Service: ${service.uuid}")
            service.characteristics?.forEach { char ->
                print("  Characteristic: ${char.uuid}, properties: ${char.properties}")
                char.descriptors?.forEach { desc ->
                    print("    Descriptor: ${desc.uuid}")
                }
            }
        }
    }
}

Die Klasse GattServiceExplorer bietet Hilfsmittel zur Navigation in der GATT-Hierarchie. findService und findCharacteristic suchen Dienste und Characteristics per UUID. getCharacteristicProperties prüft Bitmasken von Eigenschaften über and(). dumpGattTree gibt die vollständige Hierarchie im Log aus — nützlich beim Debuggen von BLE-Geräten. Alle Operationen auf BluetoothGatt müssen nach erfolgreichem onServicesDiscovered ausgeführt werden, sonst gibt getServices() eine leere Liste zurück.

Lesen von BLE-Characteristics: readCharacteristic und readDescriptor

readCharacteristic() ist eine asynchrone BluetoothGatt-Methode zum Lesen eines Characteristic-Werts von einem entfernten BLE-Gerät. Das Ergebnis kommt in onCharacteristicRead() des BluetoothGattCallback. Wenn ein Gerät 2+ übereinstimmende Characteristics hat (unwahrscheinlich aber möglich), kann readCharacteristic() ein nicht Ziel-Characteristic lesen — es ist sicherer, readCharacteristic() auf einer BluetoothGattCharacteristic-Instanz statt per UUID aufzurufen.

readDescriptor() ist eine Methode zum Lesen eines Characteristic-Descriptor-Werts. Ein typischer Descriptor ist CCCD (Client Characteristic Configuration Descriptor, UUID 0x2902), der bestimmt, ob Benachrichtigungen aktiviert sind. Das Ergebnis ist in onDescriptorRead(). Das Lesen von Descriptoren ist in der Praxis selten erforderlich — CCCD wird von setCharacteristicNotification() verwaltet, aber für benutzerdefinierte Descriptoren (User Description 0x2901, Presentation Format 0x2904) ist readDescriptor() die einzige Möglichkeit, Metadaten zu erhalten.

MTU und Lesen großer Datenmengen — wenn der Characteristic-Wert die MTU (23 Bytes für BLE 4.0) überschreitet, fragmentiert und setzt Android die Daten automatisch über eine Sequenz von Leseanfragen über den BLE-Stack zusammen. Für BLE 5.0+ mit erweiterter MTU (bis zu 251 Bytes) ist keine Fragmentierung erforderlich — ein einzelner Lesevorgang gibt vollständige Daten zurück. Vor dem Lesen können Sie requestMtu() aufrufen, um die maximale MTU auszuhandeln.

kotlin
// Characteristic und Descriptor über BluetoothGatt lesen
class GattReader {

    fun readHeartRate(gatt: BluetoothGatt) {
        // Herzfrequenz-Service UUID = 0x180D
        val service = gatt.getService(UUID.fromString("0000180D-0000-1000-8000-00805F9B34FB"))
            ?: return
        // Herzfrequenz-Messung UUID = 0x2A37
        val characteristic = service.getCharacteristic(
            UUID.fromString("00002A37-0000-1000-8000-00805F9B34FB")
        ) ?: return

        if (hasProperty(characteristic, BluetoothGattCharacteristic.PROPERTY_READ)) {
            gatt.readCharacteristic(characteristic)
        }
    }

    fun readDescriptor(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) {
        // CCCD (0x2902)
        val cccd = characteristic.getDescriptor(
            UUID.fromString("00002902-0000-1000-8000-00805F9B34FB")
        )
        cccd?.let { gatt.readDescriptor(it) }
    }

    // Daten im onCharacteristicRead-Callback verarbeiten:
    fun parseHeartRate(value: ByteArray): Int {
        // BLE Herzfrequenz: bytes = flags, second = bpm
        return if (value.isNotEmpty()) value[1].toInt() and 0xFF else 0
    }

    private fun hasProperty(char: BluetoothGattCharacteristic, prop: Int): Boolean {
        return char.properties and prop != 0
    }
}

Die Klasse GattReader demonstriert das Lesen eines Herzfrequenz-Characteristics. Der Dienst 0x180D enthält das Characteristic 0x2A37 (Heart Rate Measurement) — ein standardmäßiges BLE-Profil von Bluetooth SIG. Vor dem Lesen wird die Eigenschaft PROPERTY_READ über hasProperty geprüft. parseHeartRate analysiert das BLE-Herzfrequenzformat: erstes Byte — Flags (Datenformat), zweites — bpm-Wert. Der CCCD-Descriptor (0x2902) wird gelesen, um den Benachrichtigungsstatus zu prüfen.

Schreiben von Characteristics: writeCharacteristic mit WriteType

writeCharacteristic() ist eine BluetoothGatt-Methode zum Schreiben von Daten auf ein BLE-Peripheriegerät. Ab Android API 33+ wurde writeCharacteristic() durch writeCharacteristic(request) ersetzt, wobei BluetoothGattCharacteristicWriteRequest ein Anforderungsobjekt ist, das das Characteristic, das Byte-Array und den WriteType enthält. Die alte Methode writeCharacteristic(characteristic) mit setValue() ist veraltet. WriteType bestimmt das Anforderungsverhalten: WRITE_TYPE_DEFAULT (abhängig von den Characteristic-Eigenschaften), WRITE_TYPE_NO_RESPONSE (ohne Antwort) und WRITE_TYPE_SIGNED (Autorisierung).

Die Wahl des WriteType beeinflusst Geschwindigkeit und Zuverlässigkeit. WRITE_TYPE_DEFAULT entspricht normalerweise withResponse (wenn das Characteristic PROPERTY_WRITE hat) oder withoutResponse (wenn es PROPERTY_WRITE_NO_RESPONSE hat). Für Streaming-Daten (OTA-Updates, Logs) verwenden Sie WRITE_TYPE_NO_RESPONSE — maximaler Durchsatz. Für Befehle mit Liefergarantie (Aktivieren, Konfigurieren) — WRITE_TYPE_DEFAULT mit Bestätigung über onCharacteristicWrite.

kotlin
// BLE-Characteristic-Schreiben auf Android API 33+
class GattWriter {

    // Schreiben mit Antwort (withResponse)
    fun writeWithResponse(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, data: ByteArray) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            // API 33+: writeCharacteristic
            val request = BluetoothGattCharacteristicWriteRequest(
                characteristic,
                data,
                BluetoothGattCharacteristicWriteRequest.WRITE_TYPE_DEFAULT,
                @android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
            )
            gatt.writeCharacteristic(request)
        } else {
            // API < 33:   (deprecated)
            characteristic.setValue(data)
            gatt.writeCharacteristic(characteristic)
        }
    }

    // Schreiben ohne Antwort (maximale Geschwindigkeit)
    fun writeWithoutResponse(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, data: ByteArray) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            val request = BluetoothGattCharacteristicWriteRequest(
                characteristic,
                data,
                BluetoothGattCharacteristicWriteRequest.WRITE_TYPE_NO_RESPONSE,
                @android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
            )
            gatt.writeCharacteristic(request)
        } else {
            characteristic.setValue(data)
            characteristic.writeType = BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE
            gatt.writeCharacteristic(characteristic)
        }
    }

    // onCharacteristicWrite-Callback (API 33+)
    private val writeCallback = object : BluetoothGattCallback() {
        override fun onCharacteristicWrite(
            gatt: BluetoothGatt,
            characteristic: BluetoothGattCharacteristic,
            value: ByteArray,
            status: Int,
            callbackType: Int
        ) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
                print("Write success: ${value.size} bytes")
            }
        }
    }
}

Die Klasse GattWriter unterstützt beide WriteTypes für verschiedene API-Level. writeWithResponse verwendet WRITE_TYPE_DEFAULT — das BLE-Gerät bestätigt das Schreiben über onCharacteristicWrite. writeWithoutResponse verwendet WRITE_TYPE_NO_RESPONSE — Daten werden ohne Bestätigung gesendet, maximaler Durchsatz. Auf API 33+ wird das neue writeCharacteristic(request) mit BluetoothGattCharacteristicWriteRequest verwendet. Auf API < 33 — das alte setValue() + writeCharacteristic().

Abonnieren von Benachrichtigungen: setCharacteristicNotification und CCCD

setCharacteristicNotification() ist eine BluetoothGatt-Methode zum Abonnieren von Benachrichtigungen über Characteristic-Änderungen auf dem Peripheriegerät. Nach Aktivierung des Abonnements sendet das BLE-Gerät neue Werte über onCharacteristicChanged(). Allerdings aktiviert setCharacteristicNotification() nur die lokale Android-Benachrichtigung — um Benachrichtigungen auf dem BLE-Gerät selbst zu aktivieren, müssen Sie auch den Wert 0x0100 in den CCCD-Descriptor (0x2902) schreiben.

CCCD (Client Characteristic Configuration Descriptor) ist ein Descriptor, der das Senden von Benachrichtigungen vom BLE-Peripheriegerät steuert. Wert 0x0000 — Benachrichtigungen deaktiviert, 0x0100 — Benachrichtigungen aktiviert, 0x0200 — Indikationen aktiviert. Das Schreiben in CCCD erfolgt über writeDescriptor() auf BluetoothGatt nach dem Aufruf von setCharacteristicNotification(). Android schreibt CCCD nicht automatisch — diese Verantwortung liegt beim Entwickler.

kotlin
// Korrektes BLE-Benachrichtigungs-Abonnement
class GattNotificationManager {

    // 1. Benachrichtigungen aktivieren
    fun enableNotification(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) {
        // Schritt 1: lokales Android-Abonnement
        val success = gatt.setCharacteristicNotification(characteristic, true)
        if (!success) {
            print("Abonnement fehlgeschlagen")
            return
        }

        // Schritt 2: CCCD (0x2902) auf BLE-Gerät schreiben
        val cccdDescriptor = characteristic.getDescriptor(
            UUID.fromString("00002902-0000-1000-8000-00805F9B34FB")
        ) ?: return

        // 0x0100 = Benachrichtigung, 0x0200 = Indikation
        val cccdValue = if (characteristic.properties
            and BluetoothGattCharacteristic.PROPERTY_NOTIFY != 0) {
            BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE  // [0x01, 0x00]
        } else {
            BluetoothGattDescriptor.ENABLE_INDICATION_VALUE     // [0x02, 0x00]
        }

        cccdDescriptor.setValue(cccdValue)
        gatt.writeDescriptor(cccdDescriptor)
    }

    // 2. Characteristic-Discovery
    fun disableNotification(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) {
        gatt.setCharacteristicNotification(characteristic, false)
        val cccdDescriptor = characteristic.getDescriptor(
            UUID.fromString("00002902-0000-1000-8000-00805F9B34FB")
        ) ?: return
        cccdDescriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE)
        gatt.writeDescriptor(cccdDescriptor)
    }

    // 3. Benachrichtigungs-Callback
    private val notificationCallback = object : BluetoothGattCallback() {
        override fun onCharacteristicChanged(
            gatt: BluetoothGatt,
            characteristic: BluetoothGattCharacteristic,
            value: ByteArray,
            callbackType: Int
        ) {
            // Neuer Wert vom BLE-Peripheriegerät
            print("Notification: ${value.size} bytes")
        }
    }
}

Die Klasse GattNotificationManager implementiert das korrekte zweistufige BLE-Benachrichtigungs-Abonnementprotokoll. enableNotification ruft zuerst setCharacteristicNotification(true) auf Android auf und schreibt dann 0x0100 in den CCCD-Descriptor über writeDescriptor. disableNotification führt die umgekehrten Operationen aus. Ohne das Schreiben von CCCD sendet das BLE-Gerät keine Benachrichtigungen — dies ist der häufigste Fehler bei BLE-Entwicklern auf Android.

GATT-Client-Beispiel in Kotlin mit BluetoothGattCallback

Vollständiges Beispiel eines GATT-Clients in Kotlin, der BluetoothGatt-Erstellung, Discovery, Lesen und Benachrichtigungsabonnement in einem einzigen Manager unter Verwendung von Coroutinen für die asynchrone Verarbeitung kombiniert.

kotlin
// Vollständiger GATT-Client mit Coroutinen in Kotlin
class GattClient(context: Context) {

    private val context = context.applicationContext
    private var gatt: BluetoothGatt? = null

    // Mit Coroutine verbinden
    suspend fun connect(device: BluetoothDevice): Boolean =
        suspendCoroutine { continuation ->
            gatt = device.connectGatt(
                context, false,
                object : BluetoothGattCallback() {
                    override fun onConnectionStateChange(
                        gatt: BluetoothGatt, status: Int, newState: Int
                    ) {
                        if (newState == BluetoothProfile.STATE_CONNECTED) {
                            gatt.discoverServices()
                        } else {
                            continuation.resume(false)
                        }
                    }

                    override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) {
                        continuation.resume(status == BluetoothGatt.GATT_SUCCESS)
                    }
                },
                BluetoothDevice.TRANSPORT_LE
            )
        }

    // Characteristic über Coroutine lesen
    suspend fun readCharacteristicValue(char: BluetoothGattCharacteristic): ByteArray? =
        suspendCoroutine { continuation ->
            gatt?.let { gatt ->
                // Characteristic-Tag zur Callback-Identifikation speichern
                gatt.setCharacteristic(char, null)  // für API < 33
                gatt.readCharacteristic(char)
            }
        }

    // Verbindung schließen
    fun release() {
        gatt?.disconnect()
        gatt?.close()
        gatt = null
    }
}

Der GATT-Client GattClient verwendet Coroutinen (suspendCoroutine), um die Callback-basierte BluetoothGatt-API in sequenzielle Aufrufe umzuwandeln. connect() wartet auf onServicesDiscovered, wonach die GATT-Hierarchie verfügbar ist. readCharacteristicValue() wartet auf onCharacteristicRead. Dieser Ansatz eliminiert Callback-Verschachtelungen und macht BLE-Code linear. release() garantiert die Ressourcenbereinigung — ein obligatorischer Aufruf in onDestroy der Activity oder ViewModel.onCleared.

Häufig gestellte Fragen

Was ist BluetoothGatt in Android?

BluetoothGatt ist eine Android-Klasse für den GATT-Client, der eine BLE-Verbindung mit einem peripheren Gerät verwaltet. Sie wird über BluetoothDevice.connectGatt() erstellt und stellt Methoden discoverServices(), readCharacteristic(), writeCharacteristic(), setCharacteristicNotification() bereit. Die Ergebnisse aller Operationen kommen asynchron über BluetoothGattCallback. Ohne BluetoothGatt ist bidirektionale BLE-Kommunikation auf Android unmöglich.

Warum gibt onServicesDiscovered Status 133 zurück?

Status 133 (GATT_ERROR) zeigt einen internen Android BLE-Stack-Fehler an. Ursachen: Das Gerät hat während des Discovery die Verbindung getrennt, die MTU ist unter dem Minimum (23 Bytes) oder der BLE-Stack ist überlastet. Lösung: Wiederholen Sie discoverServices() mit einer Verzögerung von 500 ms, überprüfen Sie das RSSI des Geräts und stellen Sie sicher, dass das Peripheriegerät GATT-Discovery in seinem aktuellen Zustand unterstützt.

Wie schreibt man ein Characteristic korrekt mit Bestätigung?

Für das Schreiben mit Bestätigung rufen Sie writeCharacteristic() mit WRITE_TYPE_DEFAULT auf (API 33+: BluetoothGattCharacteristicWriteRequest). Bei Erfolg sendet das BLE-Gerät eine Bestätigung und Android ruft onCharacteristicWrite mit GATT_SUCCESS auf. Wenn das Gerät nicht innerhalb von 30 Sekunden (Stack-Timeout) antwortet, gibt der Callback einen Fehlerstatus zurück. Für Watchdog verwenden Sie Handler mit postDelayed.

Wie arbeitet man mit BLE auf Android 33+?

Ab Android 13+ (API 33) haben sich die BluetoothGatt-Methoden geändert: writeCharacteristic() akzeptiert jetzt BluetoothGattCharacteristicWriteRequest, readCharacteristic() — BluetoothGattCharacteristicReadRequest. Die alten setValue()/writeCharacteristic() sind veraltet. BluetoothGattCallback hat sich ebenfalls geändert: onCharacteristicRead(), onCharacteristicWrite(), onCharacteristicChanged() erhalten ByteArray value und callbackType. Verwenden Sie Build.VERSION.SDK_INT für die Verzweigung.

Wie viele BLE-Verbindungen unterstützt Android?

Android unterstützt 4–8 gleichzeitige BLE-GATT-Verbindungen (variiert je nach Hersteller und Android-Version). Pixel/Google: bis zu 7, Samsung: bis zu 5, Xiaomi: bis zu 4. Bei Überschreitung des Limits gibt connectGatt null zurück oder onConnectionStateChange mit einem Fehler. Für die Arbeit mit einer großen Anzahl von Geräten verwenden Sie zyklische Verbindung oder Bluetooth Mesh.

Zusammenfassung

  • BluetoothGatt — Android GATT-Client für BLE-Verbindung, erstellt über BluetoothDevice.connectGatt() mit BluetoothGattCallback
  • discoverServices() — obligatorischer Schritt nach der Verbindung zum Abrufen von BLE-Gerätediensten, Characteristics und Descriptoren
  • Lesen — readCharacteristic() mit asynchronem Ergebnis in onCharacteristicRead(); für große Daten ist MTU-Aushandlung erforderlich
  • Schreiben — writeCharacteristic() mit WriteType: DEFAULT (withResponse) oder NO_RESPONSE (ohne Bestätigung)
  • Benachrichtigungen — zweistufige Aktivierung: setCharacteristicNotification() + Schreiben von CCCD (0x2902) mit Wert 0x0100
  • API 33+ — neue Methoden writeCharacteristic(request) und readCharacteristic(request) mit Anforderungsobjekten
  • Ressourcen freigeben — obligatorischer Aufruf von disconnect() und close() zur Vermeidung von BLE-Verbindungslecks

Wir entwickeln eine mobile Applikation schlüsselfertig

IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.

Projekt besprechen

Lesen Sie auch