BluetoothGatt — ano ito, mga pamamaraan at GATT-protocol BLE sa Android

May-akda: IT Sectr Nai-publish: 2026-07-16 Oras ng pagbabasa: 10 min

BluetoothGatt — klase ng Android na nagbibigay ng API para sa paggana ng GATT-client (Generic Attribute Profile) sa BLE connection. Ang BluetoothGatt ay nag-eencapsulate ng koneksyon sa remote GATT server (peripheral BLE device) at namamahala sa lahat ng operasyon ng profile: discovery ng mga serbisyo, pagbasa at pagsulat ng mga katangian, pag-subscribe sa mga notification at indication. Ang instance ng BluetoothGatt ay nakukuha sa pamamagitan ng BluetoothDevice.connectGatt() na may callback na BluetoothGattCallback. Ayon sa Android Developers, 2026, ang BluetoothGatt ay ang sentral na klase para sa two-way BLE communication, sumusuporta sa GATT operations mula BLE 4.0 hanggang BLE 5.4.

Mga pangunahing punto

  • BluetoothGatt — klase ng Android para sa GATT-client na namamahala ng BLE connection sa peripheral device
  • connectGatt() — paraan ng BluetoothDevice para gumawa ng BluetoothGatt; tumatanggap ng context, autoConnect, callback at transport
  • discoverServices() — paraan para makuha ang GATT hierarchy: mga serbisyo (BluetoothGattService), mga katangian (BluetoothGattCharacteristic)
  • readCharacteristic/writeCharacteristic — mga paraan ng pagbasa at pagsulat na may asynchronous na resulta sa pamamagitan ng BluetoothGattCallback
  • setCharacteristicNotification — paraan ng pag-subscribe sa mga BLE notification na may mandatoryong pagsulat ng CCCD descriptor

Ano ang BluetoothGatt: esensya at paggawa ng koneksyon

BluetoothGatt — ay isang proxy object na kumakatawan sa GATT connection sa pagitan ng Android device (central) at BLE peripheral (server). Bawat instance ng BluetoothGatt ay tumutugma sa isang aktibong BLE connection. Sa pamamagitan nito isinasagawa ang lahat ng GATT profile operations: discovery, pagbasa, pagsulat, mga notification. Ang BluetoothGatt ay hindi direktang ginagawa — ito ay ibinabalik ng pamamaraang BluetoothDevice.connectGatt().

Ang paggawa ng BluetoothGatt ay nangangailangan ng apat na parameter. Context — konteksto ng application (Activity o Application). autoConnect — kung false, agad na sinisimulan ng Android ang direktang koneksyon; kung true, awtomatikong kumokonekta ang Android kapag may nakitang device (kapaki-pakinabang para sa background connection). BluetoothGattCallback — mandatoryong callback para sa lahat ng GATT events. transport — BluetoothDevice.TRANSPORT_LE (BLE) o TRANSPORT_BREDR (Classic). Sa mga BLE device palaging gamitin ang TRANSPORT_LE.

Lifecycle ng BluetoothGatt ay binubuo ng limang estado. DISCONNECTED — paunang estado. CONNECTING — pagkatapos tawagan ang connectGatt, hanggang sa kumpirmasyon. CONNECTED — pagkatapos ng onConnectionStateChange na may STATE_CONNECTED. Pagkatapos kumonekta, tinatawag ang discoverServices() para makuha ang GATT hierarchy. Pagkatapos ng trabaho — disconnect() at close() para palayain ang system resources. Kung walang close(), maaaring maubos ng app ang limitasyon ng BLE connections ng Android (karaniwang 4–8).

kotlin
// Gumagawa ng BluetoothGatt connection
import android.bluetooth.*

class GattConnector(private val context: Context) {

    private var bluetoothGatt: BluetoothGatt? = null

    fun connect(device: BluetoothDevice): BluetoothGatt? {
        // Isara ang nakaraang connection kung mayroon
        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. Connection naitatag → Discovery
                            gatt.discoverServices()
                        }
                        BluetoothProfile.STATE_DISCONNECTED -> {
                            // 3. Connection nawala
                            close()
                        }
                    }
                }

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

    private fun onGattReady(gatt: BluetoothGatt) {
        // GATT handa na para sa read/write operations
    }

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

Ang klase na GattConnector ay nagpapakita ng tamang paggawa ng BluetoothGatt. Parameter autoConnect=false — direktang koneksyon (para sa na-scan na mga device). Sa onConnectionStateChange na may STATE_CONNECTED, agad na tinatawag ang discoverServices(). Ang onServicesDiscovered ay nagpapahiwatig ng kahandaan ng GATT. Ang close() ay sunod-sunod na tumatawag ng disconnect() at close() — kung walang close(), hindi napapalaya ang system resources, na nagdudulot ng pagtagas ng BLE connections.

Pag-discovery ng mga serbisyo at katangian sa pamamagitan ng BluetoothGatt

discoverServices() — unang GATT method na tinatawag pagkatapos kumonekta. Sinisimulan ang asynchronous na paghahanap ng lahat ng serbisyo sa BLE peripheral. Ang resulta ay dumarating sa onServicesDiscovered() na may status code: GATT_SUCCESS (0) — tagumpay, 133 — GATT_ERROR, 8 — GATT_CONNECTION_TIMEOUT. Pagkatapos ng matagumpay na discovery, pinupunan ng BluetoothGatt ang listahan ng mga serbisyo na available sa pamamagitan ng getServices().

Bawat BluetoothGattService ay naglalaman ng listahan ng BluetoothGattCharacteristic. Ang katangian ay may UUID, mga property (PROPERTY_READ, PROPERTY_WRITE, PROPERTY_NOTIFY) at opsyonal na mga descriptor. Tinutukoy ng mga property kung aling mga operasyon ang pinapayagan: kung ang katangian ay walang PROPERTY_READ, ang pagtawag sa readCharacteristic ay magbabalik ng error. Para makuha ang mga descriptor ng katangian, gamitin ang getDescriptors().

kotlin
// Service discovery at paghahanap ng katangian
class GattServiceExplorer {

    // Hanapin ang serbisyo sa pamamagitan ng UUID
    fun findService(gatt: BluetoothGatt, uuid: UUID): BluetoothGattService? {
        return gatt.services?.firstOrNull { it.uuid == uuid }
    }

    // Hanapin ang katangian sa serbisyo
    fun findCharacteristic(
        service: BluetoothGattService,
        uuid: UUID
    ): BluetoothGattCharacteristic? {
        return service.characteristics?.firstOrNull { it.uuid == uuid }
    }

    // Kunin ang lahat ng suportadong operasyon ng katangian
    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
    }

    // I-log ang buong GATT hierarchy
    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}")
                }
            }
        }
    }
}

Ang klase na GattServiceExplorer ay nagbibigay ng mga utility para sa pag-navigate sa GATT hierarchy. Ang findService at findCharacteristic ay naghahanap ng mga serbisyo at katangian ayon sa UUID. Ang getCharacteristicProperties ay sumusuri ng bit masks ng mga property sa pamamagitan ng and(). Ang dumpGattTree ay naglalabas ng buong hierarchy sa log — kapaki-pakinabang sa pag-debug ng mga BLE device. Lahat ng operasyon sa BluetoothGatt ay dapat gawin pagkatapos ng matagumpay na onServicesDiscovered, kung hindi ang getServices() ay magbabalik ng walang laman na listahan.

Pagbasa ng mga katangian BLE: readCharacteristic at readDescriptor

readCharacteristic() — asynchronous na paraan ng BluetoothGatt para basahin ang halaga ng katangian mula sa remote BLE device. Ang resulta ay dumarating sa onCharacteristicRead() ng BluetoothGattCallback. Kung mayroong 2+ magkatugmang katangian sa device (hindi malamang ngunit posible), ang readCharacteristic() ay maaaring magbasa ng hindi target — mas ligtas na tawagan ang readCharacteristic() sa instance ng BluetoothGattCharacteristic, hindi batay sa UUID.

readDescriptor() — paraan para basahin ang halaga ng descriptor ng katangian. Isang tipikal na descriptor — CCCD (Client Characteristic Configuration Descriptor, UUID 0x2902) na tumutukoy kung ang mga notification ay naka-on. Resulta sa onDescriptorRead(). Ang pagbasa ng mga descriptor ay bihirang kailanganin sa praktika — ang CCCD ay pinamamahalaan ng setCharacteristicNotification(), ngunit para sa custom na mga descriptor (User Description 0x2901, Presentation Format 0x2904) ang readDescriptor() ay ang tanging paraan upang makakuha ng metadata.

MTU at pagbasa ng malaking data — kung ang halaga ng katangian ay lumampas sa MTU (23 byte para sa BLE 4.0), awtomatikong fina-fragment at ini-assemble ng Android ang data sa pamamagitan ng pagkakasunod-sunod ng read requests sa BLE stack. Para sa BLE 5.0+ na may extended MTU (hanggang 251 byte) hindi kailangan ang fragmentation — isang pagbasa ay nagbabalik ng kumpletong data. Bago magbasa, maaaring tawagan ang requestMtu() para mag-negotiate ng maximum MTU.

kotlin
// Pagbasa ng katangian at descriptor sa pamamagitan ng BluetoothGatt
class GattReader {

    fun readHeartRate(gatt: BluetoothGatt) {
        // Heart Rate Service UUID = 0x180D
        val service = gatt.getService(UUID.fromString("0000180D-0000-1000-8000-00805F9B34FB"))
            ?: return
        // Heart Rate Measurement 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) }
    }

    // I-process ang data sa onCharacteristicRead callback:
    fun parseHeartRate(value: ByteArray): Int {
        // BLE Heart Rate: bytes = flags, pangalawa = 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
    }
}

Ang klase na GattReader ay nagpapakita ng pagbasa ng Heart Rate characteristic. Ang serbisyo 0x180D ay naglalaman ng katangiang 0x2A37 (Heart Rate Measurement) — karaniwang BLE profile ng Bluetooth SIG. Bago magbasa, ang property na PROPERTY_READ ay sinusuri sa pamamagitan ng hasProperty. Ang parseHeartRate ay nagpe-parse ng BLE heart rate format: unang byte — flags (format ng data), pangalawa — halaga ng bpm. Ang CCCD descriptor (0x2902) ay binabasa para suriin ang status ng notification.

Pagsulat ng mga katangian: writeCharacteristic na may WriteType

writeCharacteristic() — paraan ng BluetoothGatt para magsulat ng data sa BLE peripheral. Sa Android API 33+, ang writeCharacteristic() ay pinalitan ng writeCharacteristic(request), kung saan ang BluetoothGattCharacteristicWriteRequest ay isang request object na naglalaman ng katangian, byte array, at WriteType. Ang lumang paraan na writeCharacteristic(characteristic) na may setValue() ay deprecated. Tinutukoy ng WriteType ang pag-uugali ng request: WRITE_TYPE_DEFAULT (depende sa mga property ng katangian), WRITE_TYPE_NO_RESPONSE (withoutResponse) at WRITE_TYPE_SIGNED (awtorisasyon).

Ang pagpili ng WriteType ay nakakaapekto sa bilis at pagiging maaasahan. Ang WRITE_TYPE_DEFAULT ay karaniwang tumutugma sa withResponse (kung ang katangian ay may PROPERTY_WRITE) o withoutResponse (kung may PROPERTY_WRITE_NO_RESPONSE). Para sa streaming data (OTA updates, logs) gamitin ang WRITE_TYPE_NO_RESPONSE — maximum bandwidth. Para sa mga command na may garantiya ng paghahatid (pag-activate, configuration) — WRITE_TYPE_DEFAULT na may kumpirmasyon sa pamamagitan ng onCharacteristicWrite.

kotlin
// Pagsulat ng BLE katangian sa Android API 33+
class GattWriter {

    // Sumulat na may tugon (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)
        }
    }

    // Sumulat nang walang tugon (max na bilis)
    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")
            }
        }
    }
}

Ang klase na GattWriter ay sumusuporta sa parehong WriteType para sa iba't ibang API level. Ang writeWithResponse ay gumagamit ng WRITE_TYPE_DEFAULT — kinukumpirma ng BLE device ang pagsulat sa pamamagitan ng onCharacteristicWrite. Ang writeWithoutResponse ay gumagamit ng WRITE_TYPE_NO_RESPONSE — data ay ipinapadala nang walang kumpirmasyon, maximum bandwidth. Sa API 33+ ginagamit ang bagong writeCharacteristic(request) na may BluetoothGattCharacteristicWriteRequest. Sa API < 33 — lumang setValue() + writeCharacteristic().

Pag-subscribe sa mga notification: setCharacteristicNotification at CCCD

setCharacteristicNotification() — paraan ng BluetoothGatt para mag-subscribe sa mga notification tungkol sa pagbabago ng katangian sa peripheral. Pagkatapos i-activate ang subscription, ang BLE device ay nagpapadala ng mga bagong halaga sa pamamagitan ng onCharacteristicChanged(). Gayunpaman, ang setCharacteristicNotification() ay nag-a-activate lamang ng lokal na notification ng Android — para i-on ang mga notification sa BLE device mismo, kailangan ding isulat ang halagang 0x0100 sa CCCD descriptor (0x2902).

CCCD (Client Characteristic Configuration Descriptor) — descriptor na namamahala sa pagpapadala ng mga notification mula sa BLE peripheral. Halaga 0x0000 — naka-off ang mga notification, 0x0100 — naka-on ang mga notification (notifications), 0x0200 — naka-on ang mga indication (indications). Ang pagsulat sa CCCD ay ginagawa sa pamamagitan ng writeDescriptor() sa BluetoothGatt pagkatapos tawagan ang setCharacteristicNotification(). Hindi awtomatikong isinusulat ng Android ang CCCD — ang responsibilidad na ito ay nasa developer.

kotlin
// Tamang BLE notification subscription
class GattNotificationManager {

    // 1. I-on ang mga notification
    fun enableNotification(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) {
        // Hakbang 1: lokal na Android subscription
        val success = gatt.setCharacteristicNotification(characteristic, true)
        if (!success) {
            print("Hindi naka-subscribe")
            return
        }

        // Hakbang 2: isulat ang CCCD (0x2902) sa BLE device
        val cccdDescriptor = characteristic.getDescriptor(
            UUID.fromString("00002902-0000-1000-8000-00805F9B34FB")
        ) ?: return

        // 0x0100 = notification, 0x0200 = indication
        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. Pag-discovery ng katangian
    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. Notification callback
    private val notificationCallback = object : BluetoothGattCallback() {
        override fun onCharacteristicChanged(
            gatt: BluetoothGatt,
            characteristic: BluetoothGattCharacteristic,
            value: ByteArray,
            callbackType: Int
        ) {
            // Bagong halaga mula sa BLE peripheral
            print("Notification: ${value.size} bytes")
        }
    }
}

Ang klase na GattNotificationManager ay nagpapatupad ng tamang two-step protocol para sa pag-subscribe sa BLE notification. Ang enableNotification ay unang tumatawag ng setCharacteristicNotification(true) sa Android, pagkatapos ay nagsusulat ng 0x0100 sa CCCD descriptor sa pamamagitan ng writeDescriptor. Ang disableNotification ay nagsasagawa ng mga kabaligtarang operasyon. Kung walang pagsulat ng CCCD, ang BLE device ay hindi nagpapadala ng mga notification — ito ang pinakakaraniwang pagkakamali ng mga BLE developer sa Android.

Halimbawa ng GATT-client sa Kotlin na may BluetoothGattCallback

Buong halimbawa ng GATT-client sa Kotlin, na pinagsasama ang paggawa ng BluetoothGatt, discovery, pagbasa at pag-subscribe sa mga notification sa iisang manager gamit ang coroutines para sa asynchronous processing.

kotlin
// Buong GATT client na may coroutines sa Kotlin
class GattClient(context: Context) {

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

    // Kumonekta gamit ang 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
            )
        }

    // Basahin ang katangian sa pamamagitan ng coroutine
    suspend fun readCharacteristicValue(char: BluetoothGattCharacteristic): ByteArray? =
        suspendCoroutine { continuation ->
            gatt?.let { gatt ->
                // I-save ang tag ng katangian para sa callback identification
                gatt.setCharacteristic(char, null)  // para sa API < 33
                gatt.readCharacteristic(char)
            }
        }

    // Isara ang connection
    fun release() {
        gatt?.disconnect()
        gatt?.close()
        gatt = null
    }
}

Ang GATT client na GattClient ay gumagamit ng coroutines (suspendCoroutine) para gawing sequential calls ang callback-based na BluetoothGatt API. Ang connect() ay naghihintay ng onServicesDiscovered, pagkatapos nito ay available na ang GATT hierarchy. Ang readCharacteristicValue() ay naghihintay ng onCharacteristicRead. Ang approach na ito ay nag-aalis ng nested callbacks at ginagawang linear ang BLE code. Ang release() ay ginagarantiyahan ang pagpapalaya ng resources — mandatoryong tawag sa onDestroy ng Activity o ViewModel.onCleared.

Mga madalas itanong

Ano ang BluetoothGatt sa Android?

BluetoothGatt — klase para sa GATT client ng Android na namamahala ng BLE connection sa peripheral device. Ginagawa sa pamamagitan ng BluetoothDevice.connectGatt(), nagbibigay ng mga pamamaraang discoverServices(), readCharacteristic(), writeCharacteristic(), setCharacteristicNotification(). Ang mga resulta ng lahat ng operasyon ay dumarating nang asynchronous sa pamamagitan ng BluetoothGattCallback. Kung walang BluetoothGatt, ang two-way BLE communication sa Android ay hindi posible.

Bakit nagbabalik ang onServicesDiscovered ng status 133?

Ang status 133 (GATT_ERROR) ay nangangahulugang internal error ng Android BLE stack. Mga dahilan: nadiskonekta ang device habang nade-detect, ang MTU ay mas maliit sa minimum (23 byte), o ang BLE stack ay overloaded. Solusyon: ulitin ang discoverServices() na may 500 ms na pagkaantala, suriin ang RSSI ng device, at tiyakin na sinusuportahan ng peripheral ang GATT discovery sa kasalukuyang estado.

Paano tamang magsulat ng katangian na may kumpirmasyon?

Para magsulat na may kumpirmasyon, tawagan ang writeCharacteristic() na may WRITE_TYPE_DEFAULT (API 33+: BluetoothGattCharacteristicWriteRequest). Sa tagumpay, nagpapadala ang BLE device ng kumpirmasyon at tinatawag ng Android ang onCharacteristicWrite na may GATT_SUCCESS. Kung hindi tumugon ang device sa loob ng 30 segundo (stack timeout), ang callback ay nagbabalik ng error status. Para sa watchdog, gumamit ng Handler na may postDelayed.

Paano magtrabaho sa BLE sa Android 33+?

Sa Android 13+ (API 33) nagbago ang mga pamamaraan ng BluetoothGatt: ang writeCharacteristic() ngayon ay tumatanggap ng BluetoothGattCharacteristicWriteRequest, ang readCharacteristic() — BluetoothGattCharacteristicReadRequest. Ang lumang setValue()/writeCharacteristic() ay deprecated. Nagbago din ang BluetoothGattCallback: ang onCharacteristicRead(), onCharacteristicWrite(), onCharacteristicChanged() ay tumatanggap ng ByteArray value at callbackType. Gamitin ang Build.VERSION.SDK_INT para sa branching.

Ilang BLE connections ang sinusuportahan ng Android?

Ang Android ay sumusuporta ng 4–8 sabay-sabay na BLE-GATT connections (depende sa manufacturer at bersyon ng Android). Pixel/Google: hanggang 7, Samsung: hanggang 5, Xiaomi: hanggang 4. Kapag lumampas sa limitasyon, ang connectGatt ay nagbabalik ng null o onConnectionStateChange na may error. Para sa pagtatrabaho na may maraming device, gumamit ng cyclical connection o Bluetooth Mesh.

Buod

  • BluetoothGatt — Android GATT client para sa BLE connection, ginagawa sa pamamagitan ng BluetoothDevice.connectGatt() na may BluetoothGattCallback
  • discoverServices() — mandatoryong hakbang pagkatapos kumonekta para makuha ang mga serbisyo, katangian at descriptor ng BLE device
  • Pagbasa — readCharacteristic() na may asynchronous na resulta sa onCharacteristicRead(); para sa malaking data kailangan ang MTU negotiation
  • Pagsulat — writeCharacteristic() na may WriteType: DEFAULT (withResponse) o NO_RESPONSE (walang kumpirmasyon)
  • Mga notification — two-step activation: setCharacteristicNotification() + pagsulat ng CCCD (0x2902) na may halagang 0x0100
  • API 33+ — mga bagong pamamaraan writeCharacteristic(request) at readCharacteristic(request) na may request objects
  • Pagpapalaya ng resources — mandatoryong pagtawag ng disconnect() at close() para maiwasan ang pagtagas ng BLE connections

Gagawa kami ng mobile application na turnkey

Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.

Pag-usapan ang proyekto

Basahin din