BluetoothGatt — κλάση Android που παρέχει API για τη λειτουργία GATT-πελάτη (Generic Attribute Profile) μέσω σύνδεσης BLE. Το BluetoothGatt ενσωματώνει τη σύνδεση σε απομακρυσμένο GATT-διακομιστή (περιφερειακή συσκευή BLE) και διαχειρίζεται όλες τις λειτουργίες προφίλ: ανακάλυψη υπηρεσιών, ανάγνωση και εγγραφή χαρακτηριστικών, εγγραφή σε ειδοποιήσεις και ενδείξεις. Το στιγμιότυπο BluetoothGatt λαμβάνεται μέσω BluetoothDevice.connectGatt() με επανάκληση BluetoothGattCallback. Σύμφωνα με το Android Developers, 2026, το BluetoothGatt είναι η κεντρική κλάση για αμφίδρομη επικοινωνία BLE, υποστηρίζοντας λειτουργίες GATT από BLE 4.0 έως BLE 5.4.
Κύρια σημεία
BluetoothGatt — είναι ένα αντικείμενο proxy που αντιπροσωπεύει τη σύνδεση GATT μεταξύ συσκευής Android (κέντρο) και περιφέρειας BLE (διακομιστής). Κάθε στιγμιότυπο BluetoothGatt αντιστοιχεί σε μία ενεργή σύνδεση BLE. Μέσω αυτού εκτελούνται όλες οι λειτουργίες προφίλ GATT: ανακάλυψη, ανάγνωση, εγγραφή, ειδοποιήσεις. Το BluetoothGatt δεν δημιουργείται άμεσα — επιστρέφεται από τη μέθοδο BluetoothDevice.connectGatt().
Η δημιουργία BluetoothGatt απαιτεί τέσσερις παραμέτρους. Context — πλαίσιο εφαρμογής (Activity ή Application). autoConnect — αν false, το Android ξεκινά αμέσως άμεση σύνδεση· αν true, το Android συνδέεται αυτόματα κατά τον εντοπισμό συσκευής (χρήσιμο για σύνδεση παρασκηνίου). BluetoothGattCallback — υποχρεωτική επανάκληση για όλα τα συμβάντα GATT. transport — BluetoothDevice.TRANSPORT_LE (BLE) ή TRANSPORT_BREDR (Classic). Σε συσκευές BLE χρησιμοποιείτε πάντα TRANSPORT_LE.
Κύκλος ζωής BluetoothGatt αποτελείται από πέντε καταστάσεις. DISCONNECTED — αρχική κατάσταση. CONNECTING — μετά την κλήση connectGatt, έως την επιβεβαίωση. CONNECTED — μετά το onConnectionStateChange με STATE_CONNECTED. Μετά τη σύνδεση καλείται το discoverServices() για απόκτηση της ιεραρχίας GATT. Μετά την ολοκλήρωση — disconnect() και close() για απελευθέρωση πόρων συστήματος. Χωρίς close(), η εφαρμογή μπορεί να εξαντλήσει το όριο συνδέσεων BLE Android (συνήθως 4–8).
// Δημιουργία σύνδεσης BluetoothGatt
import android.bluetooth.*
class GattConnector(private val context: Context) {
private var bluetoothGatt: BluetoothGatt? = null
fun connect(device: BluetoothDevice): BluetoothGatt? {
// Κλείσιμο προηγούμενης σύνδεσης εάν υπάρχει
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. Σύνδεση εγκαταστάθηκε → Ανακάλυψη
gatt.discoverServices()
}
BluetoothProfile.STATE_DISCONNECTED -> {
// 3. Σύνδεση χάθηκε
close()
}
}
}
override fun onServicesDiscovered(
gatt: BluetoothGatt, status: Int
) {
if (status == BluetoothGatt.GATT_SUCCESS) {
// 4. Ιεραρχία GATT ελήφθη
onGattReady(gatt)
}
}
},
BluetoothDevice.TRANSPORT_LE
)
return bluetoothGatt
}
private fun onGattReady(gatt: BluetoothGatt) {
// GATT έτοιμο για λειτουργίες ανάγνωσης/εγγραφής
}
fun close() {
bluetoothGatt?.disconnect()
bluetoothGatt?.close()
bluetoothGatt = null
}
}
Η κλάση GattConnector παρουσιάζει τη σωστή δημιουργία BluetoothGatt. Η παράμετρος autoConnect=false — άμεση σύνδεση (για σαρωμένες συσκευές). Στο onConnectionStateChange με STATE_CONNECTED καλείται αμέσως το discoverServices(). Το onServicesDiscovered σηματοδοτεί την ετοιμότητα GATT. Η close() καλεί διαδοχικά disconnect() και close() — χωρίς close() οι πόροι συστήματος δεν απελευθερώνονται, οδηγώντας σε διαρροή συνδέσεων BLE.
discoverServices() — η πρώτη μέθοδος GATT που καλείται μετά τη σύνδεση. Ξεκινά ασύγχρονη αναζήτηση όλων των υπηρεσιών στην περιφέρεια BLE. Το αποτέλεσμα έρχεται στο onServicesDiscovered() με κωδικό κατάστασης: GATT_SUCCESS (0) — επιτυχία, 133 — GATT_ERROR, 8 — GATT_CONNECTION_TIMEOUT. Μετά από επιτυχή ανακάλυψη, το BluetoothGatt συμπληρώνει τη λίστα υπηρεσιών που είναι διαθέσιμες μέσω getServices().
Κάθε BluetoothGattService περιέχει μια λίστα BluetoothGattCharacteristic. Το χαρακτηριστικό έχει UUID, ιδιότητες (PROPERTY_READ, PROPERTY_WRITE, PROPERTY_NOTIFY) και προαιρετικούς περιγραφείς. Οι ιδιότητες καθορίζουν ποιες λειτουργίες επιτρέπονται: αν το χαρακτηριστικό δεν έχει PROPERTY_READ, η κλήση readCharacteristic θα επιστρέψει σφάλμα. Για λήψη των περιγραφέων του χαρακτηριστικού χρησιμοποιείται το getDescriptors().
// Ανακάλυψη υπηρεσίας και αναζήτηση χαρακτηριστικού
class GattServiceExplorer {
// Εύρεση υπηρεσίας κατά UUID
fun findService(gatt: BluetoothGatt, uuid: UUID): BluetoothGattService? {
return gatt.services?.firstOrNull { it.uuid == uuid }
}
// Εύρεση χαρακτηριστικού στην υπηρεσία
fun findCharacteristic(
service: BluetoothGattService,
uuid: UUID
): BluetoothGattCharacteristic? {
return service.characteristics?.firstOrNull { it.uuid == uuid }
}
// Λήψη όλων των υποστηριζόμενων λειτουργιών χαρακτηριστικού
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("WRITE")
if (and(BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) != 0) props.add("WRITE_NO_RESP")
if (and(BluetoothGattCharacteristic.PROPERTY_NOTIFY) != 0) props.add("NOTIFY")
if (and(BluetoothGattCharacteristic.PROPERTY_INDICATE) != 0) props.add("INDICATE")
}
return props
}
// Καταγραφή ολόκληρης ιεραρχίας GATT
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}")
}
}
}
}
}
Η κλάση GattServiceExplorer παρέχει βοηθητικά προγράμματα για πλοήγηση στην ιεραρχία GATT. Οι findService και findCharacteristic αναζητούν υπηρεσίες και χαρακτηριστικά βάσει UUID. Η getCharacteristicProperties ελέγχει bitmasks ιδιοτήτων μέσω and(). Η dumpGattTree εξάγει ολόκληρη την ιεραρχία στο αρχείο καταγραφής — χρήσιμη κατά τον εντοπισμό σφαλμάτων συσκευών BLE. Όλες οι λειτουργίες στο BluetoothGatt πρέπει να εκτελούνται μετά από επιτυχημένο onServicesDiscovered, διαφορετικά η getServices() θα επιστρέψει κενή λίστα.
readCharacteristic() — ασύγχρονη μέθοδος BluetoothGatt για ανάγνωση της τιμής χαρακτηριστικού από απομακρυσμένη συσκευή BLE. Το αποτέλεσμα έρχεται στο onCharacteristicRead() του BluetoothGattCallback. Εάν υπάρχουν 2+ αντίστοιχα χαρακτηριστικά στη συσκευή (απίθανο αλλά πιθανό), η readCharacteristic() μπορεί να διαβάσει λάθος στόχο — είναι ασφαλέστερο να καλείτε readCharacteristic() στο στιγμιότυπο BluetoothGattCharacteristic, όχι βάσει UUID.
readDescriptor() — μέθοδος για ανάγνωση της τιμής περιγραφέα χαρακτηριστικού. Ένας τυπικός περιγραφέας — CCCD (Client Characteristic Configuration Descriptor, UUID 0x2902) που καθορίζει εάν οι ειδοποιήσεις είναι ενεργοποιημένες. Αποτέλεσμα στο onDescriptorRead(). Η ανάγνωση περιγραφέων σπάνια απαιτείται στην πράξη — το CCCD διαχειρίζεται από το setCharacteristicNotification(), αλλά για προσαρμοσμένους περιγραφείς (User Description 0x2901, Presentation Format 0x2904) η readDescriptor() είναι ο μόνος τρόπος λήψης μεταδεδομένων.
MTU και ανάγνωση μεγάλων δεδομένων — εάν η τιμή χαρακτηριστικού υπερβαίνει το MTU (23 byte για BLE 4.0), το Android αυτόματα κατατμεί και συναρμολογεί δεδομένα μέσω μιας σειράς αιτημάτων ανάγνωσης μέσω της στοίβας BLE. Για BLE 5.0+ με εκτεταμένο MTU (έως 251 byte) δεν απαιτείται κατατμηματισμός — μία ανάγνωση επιστρέφει πλήρη δεδομένα. Πριν από την ανάγνωση μπορεί να κληθεί requestMtu() για διαπραγμάτευση μέγιστου MTU.
// Ανάγνωση χαρακτηριστικού και περιγραφέα μέσω BluetoothGatt
class GattReader {
fun readHeartRate(gatt: BluetoothGatt) {
// UUID υπηρεσίας Heart Rate = 0x180D
val service = gatt.getService(UUID.fromString("0000180D-0000-1000-8000-00805F9B34FB"))
?: return
// UUID μέτρησης Heart Rate = 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) }
}
// Επεξεργασία δεδομένων στην επανάκληση onCharacteristicRead:
fun parseHeartRate(value: ByteArray): Int {
// BLE Heart Rate: byte = flags, δεύτερο = 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
}
}
Η κλάση GattReader παρουσιάζει την ανάγνωση του χαρακτηριστικού Heart Rate. Η υπηρεσία 0x180D περιέχει το χαρακτηριστικό 0x2A37 (Heart Rate Measurement) — το τυπικό προφίλ BLE του Bluetooth SIG. Πριν από την ανάγνωση, η ιδιότητα PROPERTY_READ ελέγχεται μέσω hasProperty. Η parseHeartRate αναλύει τη μορφή BLE καρδιακών παλμών: πρώτο byte — flags (μορφή δεδομένων), δεύτερο — τιμή bpm. Ο περιγραφέας CCCD (0x2902) διαβάζεται για έλεγχο της κατάστασης ειδοποιήσεων.
writeCharacteristic() — μέθοδος BluetoothGatt για εγγραφή δεδομένων στην περιφέρεια BLE. Στο Android API 33+, η writeCharacteristic() αντικαταστάθηκε από writeCharacteristic(request), όπου BluetoothGattCharacteristicWriteRequest είναι ένα αντικείμενο αιτήματος που περιέχει το χαρακτηριστικό, έναν πίνακα byte και WriteType. Η παλιά μέθοδος writeCharacteristic(characteristic) με setValue() είναι παρωχημένη. Το WriteType καθορίζει τη συμπεριφορά αιτήματος: WRITE_TYPE_DEFAULT (εξαρτάται από ιδιότητες χαρακτηριστικού), WRITE_TYPE_NO_RESPONSE (withoutResponse) και WRITE_TYPE_SIGNED (εξουσιοδότηση).
Η επιλογή WriteType επηρεάζει την ταχύτητα και αξιοπιστία. Το WRITE_TYPE_DEFAULT αντιστοιχεί συνήθως σε withResponse (εάν το χαρακτηριστικό έχει PROPERTY_WRITE) ή withoutResponse (εάν έχει PROPERTY_WRITE_NO_RESPONSE). Για δεδομένα ροής (ενημερώσεις OTA, αρχεία καταγραφής) χρησιμοποιήστε WRITE_TYPE_NO_RESPONSE — μέγιστο εύρος ζώνης. Για εντολές με εγγύηση παράδοσης (ενεργοποίηση, διαμόρφωση) — WRITE_TYPE_DEFAULT με επιβεβαίωση μέσω onCharacteristicWrite.
// Εγγραφή χαρακτηριστικού BLE σε Android API 33+
class GattWriter {
// Εγγραφή με απόκριση (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)
}
}
// Εγγραφή χωρίς απόκριση (μέγιστη ταχύτητα)
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 (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")
}
}
}
}
Η κλάση GattWriter υποστηρίζει και τους δύο WriteType για διαφορετικά επίπεδα API. Η writeWithResponse χρησιμοποιεί WRITE_TYPE_DEFAULT — η συσκευή BLE επιβεβαιώνει την εγγραφή μέσω onCharacteristicWrite. Η writeWithoutResponse χρησιμοποιεί WRITE_TYPE_NO_RESPONSE — τα δεδομένα αποστέλλονται χωρίς επιβεβαίωση, μέγιστο εύρος ζώνης. Σε API 33+ χρησιμοποιείται η νέα writeCharacteristic(request) με BluetoothGattCharacteristicWriteRequest. Σε API < 33 — η παλιά setValue() + writeCharacteristic().
setCharacteristicNotification() — μέθοδος BluetoothGatt για εγγραφή σε ειδοποιήσεις αλλαγής χαρακτηριστικού στην περιφέρεια. Μετά την ενεργοποίηση της εγγραφής, η συσκευή BLE στέλνει νέες τιμές μέσω onCharacteristicChanged(). Ωστόσο, η setCharacteristicNotification() ενεργοποιεί μόνο την τοπική ειδοποίηση Android — για ενεργοποίηση ειδοποιήσεων στην ίδια τη συσκευή BLE, πρέπει επίσης να εγγραφεί η τιμή 0x0100 στον περιγραφέα CCCD (0x2902).
CCCD (Client Characteristic Configuration Descriptor) — περιγραφέας που διαχειρίζεται την αποστολή ειδοποιήσεων από την περιφέρεια BLE. Τιμή 0x0000 — ειδοποιήσεις απενεργοποιημένες, 0x0100 — ειδοποιήσεις ενεργοποιημένες (notifications), 0x0200 — ενδείξεις ενεργοποιημένες (indications). Η εγγραφή στο CCCD γίνεται μέσω writeDescriptor() στο BluetoothGatt μετά την κλήση setCharacteristicNotification(). Το Android δεν γράφει αυτόματα το CCCD — αυτή η ευθύνη ανήκει στον προγραμματιστή.
// Σωστή εγγραφή σε ειδοποιήσεις BLE
class GattNotificationManager {
// 1. Ενεργοποίηση ειδοποιήσεων
fun enableNotification(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) {
// Βήμα 1: τοπική εγγραφή Android
val success = gatt.setCharacteristicNotification(characteristic, true)
if (!success) {
print("Αποτυχία εγγραφής")
return
}
// Βήμα 2: εγγραφή CCCD (0x2902) στη συσκευή BLE
val cccdDescriptor = characteristic.getDescriptor(
UUID.fromString("00002902-0000-1000-8000-00805F9B34FB")
) ?: return
// 0x0100 = ειδοποίηση, 0x0200 = ένδειξη
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. Ανακάλυψη χαρακτηριστικού
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. Επανάκληση ειδοποίησης
private val notificationCallback = object : BluetoothGattCallback() {
override fun onCharacteristicChanged(
gatt: BluetoothGatt,
characteristic: BluetoothGattCharacteristic,
value: ByteArray,
callbackType: Int
) {
// Νέα τιμή από περιφέρεια BLE
print("Notification: ${value.size} bytes")
}
}
}
Η κλάση GattNotificationManager υλοποιεί το σωστό πρωτόκολλο δύο βημάτων για εγγραφή σε ειδοποιήσεις BLE. Η enableNotification πρώτα καλεί setCharacteristicNotification(true) στο Android, στη συνέχεια γράφει 0x0100 στον περιγραφέα CCCD μέσω writeDescriptor. Η disableNotification εκτελεί αντίστροφες λειτουργίες. Χωρίς εγγραφή CCCD, η συσκευή BLE δεν στέλνει ειδοποιήσεις — αυτό είναι το πιο συνηθισμένο λάθος προγραμματιστών BLE σε Android.
Πλήρες παράδειγμα GATT-πελάτη σε Kotlin, που συνδυάζει δημιουργία BluetoothGatt, ανακάλυψη, ανάγνωση και εγγραφή σε ειδοποιήσεις σε έναν ενιαίο διαχειριστή χρησιμοποιώντας coroutines για ασύγχρονη επεξεργασία.
// Πλήρης GATT-πελάτης με coroutines σε Kotlin
class GattClient(context: Context) {
private val context = context.applicationContext
private var gatt: BluetoothGatt? = null
// Σύνδεση με coroutine
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
)
}
// Ανάγνωση χαρακτηριστικού μέσω coroutine
suspend fun readCharacteristicValue(char: BluetoothGattCharacteristic): ByteArray? =
suspendCoroutine { continuation ->
gatt?.let { gatt ->
// Αποθήκευση ετικέτας χαρακτηριστικού για αναγνώριση επανάκλησης
gatt.setCharacteristic(char, null) // για API < 33
gatt.readCharacteristic(char)
}
}
// Κλείσιμο σύνδεσης
fun release() {
gatt?.disconnect()
gatt?.close()
gatt = null
}
}
Ο GATT-πελάτης GattClient χρησιμοποιεί coroutines (suspendCoroutine) για να μετατρέψει το βασισμένο σε callback API BluetoothGatt σε ακολουθιακές κλήσεις. Η connect() περιμένει το onServicesDiscovered, μετά το οποίο η ιεραρχία GATT είναι διαθέσιμη. Η readCharacteristicValue() περιμένει το onCharacteristicRead. Αυτή η προσέγγιση εξαλείφει τα ένθετα callbacks και καθιστά τον κώδικα BLE γραμμικό. Η release() εγγυάται την απελευθέρωση πόρων — υποχρεωτική κλήση στο onDestroy του Activity ή ViewModel.onCleared.
Συχνές ερωτήσεις
BluetoothGatt — κλάση για τον GATT-πελάτη Android που διαχειρίζεται σύνδεση BLE με περιφερειακή συσκευή. Δημιουργείται μέσω BluetoothDevice.connectGatt(), παρέχει μεθόδους discoverServices(), readCharacteristic(), writeCharacteristic(), setCharacteristicNotification(). Τα αποτελέσματα όλων των λειτουργιών έρχονται ασύγχρονα μέσω BluetoothGattCallback. Χωρίς BluetoothGatt, η αμφίδρομη επικοινωνία BLE σε Android είναι αδύνατη.
Η κατάσταση 133 (GATT_ERROR) σημαίνει εσωτερικό σφάλμα της στοίβας BLE Android. Αιτίες: η συσκευή αποσυνδέθηκε κατά την ανακάλυψη, το MTU είναι μικρότερο από το ελάχιστο (23 byte) ή η στοίβα BLE είναι υπερφορτωμένη. Λύση: επαναλάβετε το discoverServices() με καθυστέρηση 500 ms, ελέγξτε το RSSI της συσκευής και βεβαιωθείτε ότι η περιφέρεια υποστηρίζει ανακάλυψη GATT στην τρέχουσα κατάσταση.
Για εγγραφή με επιβεβαίωση, καλέστε writeCharacteristic() με WRITE_TYPE_DEFAULT (API 33+: BluetoothGattCharacteristicWriteRequest). Σε επιτυχία, η συσκευή BLE στέλνει επιβεβαίωση και το Android καλεί onCharacteristicWrite με GATT_SUCCESS. Εάν η συσκευή δεν αποκριθεί εντός 30 δευτερολέπτων (χρονικό όριο στοίβας), η επανάκληση επιστρέφει κατάσταση σφάλματος. Για watchdog, χρησιμοποιήστε Handler με postDelayed.
Σε Android 13+ (API 33) άλλαξαν οι μέθοδοι BluetoothGatt: η writeCharacteristic() τώρα δέχεται BluetoothGattCharacteristicWriteRequest, η readCharacteristic() — BluetoothGattCharacteristicReadRequest. Οι παλιές setValue()/writeCharacteristic() είναι παρωχημένες. Επίσης άλλαξε το BluetoothGattCallback: onCharacteristicRead(), onCharacteristicWrite(), onCharacteristicChanged() λαμβάνουν ByteArray value και callbackType. Χρησιμοποιήστε Build.VERSION.SDK_INT για διακλάδωση.
Το Android υποστηρίζει 4–8 ταυτόχρονες συνδέσεις BLE-GATT (εξαρτάται από τον κατασκευαστή και την έκδοση Android). Pixel/Google: έως 7, Samsung: έως 5, Xiaomi: έως 4. Κατά υπέρβαση του ορίου, η connectGatt επιστρέφει null ή το onConnectionStateChange καλείται με σφάλμα. Για εργασία με πολλές συσκευές, χρησιμοποιήστε κυκλική σύνδεση ή Bluetooth Mesh.
Σύνοψη
Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση
Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.
Διαβάστε επίσης