BluetoothGatt — apa itu, metode dan protokol GATT BLE di Android

Penulis: IT Sectr Diterbitkan: 2026-07-16 Waktu membaca: 10 mnt

BluetoothGatt — kelas Android yang menyediakan API untuk kerja klien GATT (Generic Attribute Profile) melalui koneksi BLE. BluetoothGatt merangkum koneksi ke server GATT jarak jauh (perangkat BLE periferal) dan mengelola semua operasi profil: penemuan layanan, membaca dan menulis karakteristik, berlangganan notifikasi dan indikasi. Instance BluetoothGatt diperoleh melalui BluetoothDevice.connectGatt() dengan callback BluetoothGattCallback. Menurut Android Developers, 2026, BluetoothGatt adalah kelas pusat untuk komunikasi BLE dua arah, mendukung operasi GATT dari BLE 4.0 hingga BLE 5.4.

Poin utama

  • BluetoothGatt — kelas Android untuk klien GATT yang mengelola koneksi BLE dengan perangkat periferal
  • connectGatt() — metode BluetoothDevice untuk membuat BluetoothGatt; menerima konteks, autoConnect, callback, dan transport
  • discoverServices() — metode untuk mendapatkan hierarki GATT: layanan (BluetoothGattService), karakteristik (BluetoothGattCharacteristic)
  • readCharacteristic/writeCharacteristic — metode baca dan tulis dengan hasil asinkron melalui BluetoothGattCallback
  • setCharacteristicNotification — metode berlangganan notifikasi BLE dengan penulisan deskriptor CCCD wajib

Apa itu BluetoothGatt: esensi dan pembuatan koneksi

BluetoothGatt — adalah objek proxy yang mewakili koneksi GATT antara perangkat Android (pusat) dan periferal BLE (server). Setiap instance BluetoothGatt sesuai dengan satu koneksi BLE aktif. Melaluinya semua operasi profil GATT dilakukan: penemuan, pembacaan, penulisan, notifikasi. BluetoothGatt tidak dibuat langsung — dikembalikan oleh metode BluetoothDevice.connectGatt().

Pembuatan BluetoothGatt memerlukan empat parameter. Context — konteks aplikasi (Activity atau Application). autoConnect — jika false, Android segera memulai koneksi langsung; jika true, Android terhubung secara otomatis saat perangkat terdeteksi (berguna untuk koneksi latar belakang). BluetoothGattCallback — callback wajib untuk semua peristiwa GATT. transport — BluetoothDevice.TRANSPORT_LE (BLE) atau TRANSPORT_BREDR (Classic). Pada perangkat BLE selalu gunakan TRANSPORT_LE.

Siklus hidup BluetoothGatt terdiri dari lima keadaan. DISCONNECTED — keadaan awal. CONNECTING — setelah pemanggilan connectGatt, hingga konfirmasi. CONNECTED — setelah onConnectionStateChange dengan STATE_CONNECTED. Setelah terhubung, discoverServices() dipanggil untuk mendapatkan hierarki GATT. Setelah selesai bekerja — disconnect() dan close() untuk membebaskan sumber daya sistem. Tanpa pemanggilan close(), aplikasi dapat menghabiskan batas koneksi BLE Android (biasanya 4–8).

kotlin
// Membuat koneksi BluetoothGatt
import android.bluetooth.*

class GattConnector(private val context: Context) {

    private var bluetoothGatt: BluetoothGatt? = null

    fun connect(device: BluetoothDevice): BluetoothGatt? {
        // Tutup koneksi sebelumnya jika ada
        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. Koneksi terbentuk → Penemuan
                            gatt.discoverServices()
                        }
                        BluetoothProfile.STATE_DISCONNECTED -> {
                            // 3. Koneksi terputus
                            close()
                        }
                    }
                }

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

    private fun onGattReady(gatt: BluetoothGatt) {
        // GATT siap untuk operasi baca/tulis
    }

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

Kelas GattConnector mendemonstrasikan pembuatan BluetoothGatt yang benar. Parameter autoConnect=false — koneksi langsung (untuk perangkat yang dipindai). Pada onConnectionStateChange dengan STATE_CONNECTED, discoverServices() segera dipanggil. onServicesDiscovered menandakan kesiapan GATT. close() secara berurutan memanggil disconnect() dan close() — tanpa close() sumber daya sistem tidak dibebaskan, menyebabkan kebocoran koneksi BLE.

Penemuan layanan dan karakteristik melalui BluetoothGatt

discoverServices() — metode GATT pertama yang dipanggil setelah koneksi. Memulai pencarian asinkron semua layanan pada periferal BLE. Hasilnya datang di onServicesDiscovered() dengan kode status: GATT_SUCCESS (0) — berhasil, 133 — GATT_ERROR, 8 — GATT_CONNECTION_TIMEOUT. Setelah penemuan berhasil, BluetoothGatt mengisi daftar layanan yang tersedia melalui getServices().

Setiap BluetoothGattService berisi daftar BluetoothGattCharacteristic. Karakteristik memiliki UUID, properti (PROPERTY_READ, PROPERTY_WRITE, PROPERTY_NOTIFY) dan deskriptor opsional. Properti menentukan operasi mana yang diizinkan: jika karakteristik tidak memiliki PROPERTY_READ, pemanggilan readCharacteristic akan mengembalikan kesalahan. Untuk mendapatkan deskriptor karakteristik, gunakan getDescriptors().

kotlin
// Penemuan layanan dan pencarian karakteristik
class GattServiceExplorer {

    // Temukan layanan berdasarkan UUID
    fun findService(gatt: BluetoothGatt, uuid: UUID): BluetoothGattService? {
        return gatt.services?.firstOrNull { it.uuid == uuid }
    }

    // Temukan karakteristik dalam layanan
    fun findCharacteristic(
        service: BluetoothGattService,
        uuid: UUID
    ): BluetoothGattCharacteristic? {
        return service.characteristics?.firstOrNull { it.uuid == uuid }
    }

    // Dapatkan semua operasi karakteristik yang didukung
    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
    }

    // Catat seluruh hierarki 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}")
                }
            }
        }
    }
}

Kelas GattServiceExplorer menyediakan utilitas untuk navigasi hierarki GATT. findService dan findCharacteristic mencari layanan dan karakteristik berdasarkan UUID. getCharacteristicProperties memeriksa topeng bit properti melalui and(). dumpGattTree menampilkan hierarki lengkap ke log — berguna saat debugging perangkat BLE. Semua operasi pada BluetoothGatt harus dilakukan setelah onServicesDiscovered berhasil, jika tidak getServices() akan mengembalikan daftar kosong.

Membaca karakteristik BLE: readCharacteristic dan readDescriptor

readCharacteristic() — metode asinkron BluetoothGatt untuk membaca nilai karakteristik dari perangkat BLE jarak jauh. Hasilnya datang di onCharacteristicRead() dari BluetoothGattCallback. Jika ada 2+ karakteristik yang cocok di perangkat (tidak mungkin tetapi mungkin), readCharacteristic() dapat membaca yang tidak ditargetkan — lebih aman memanggil readCharacteristic() pada instance BluetoothGattCharacteristic, bukan berdasarkan UUID.

readDescriptor() — metode untuk membaca nilai deskriptor karakteristik. Deskriptor tipikal — CCCD (Client Characteristic Configuration Descriptor, UUID 0x2902) yang menentukan apakah notifikasi diaktifkan. Hasil di onDescriptorRead(). Membaca deskriptor jarang diperlukan dalam praktik — CCCD dikelola oleh setCharacteristicNotification(), tetapi untuk deskriptor kustom (User Description 0x2901, Presentation Format 0x2904) readDescriptor() adalah satu-satunya cara mendapatkan metadata.

MTU dan membaca data besar — jika nilai karakteristik melebihi MTU (23 byte untuk BLE 4.0), Android secara otomatis memfragmentasi dan merakit data melalui urutan permintaan baca melalui tumpukan BLE. Untuk BLE 5.0+ dengan MTU yang diperluas (hingga 251 byte) fragmentasi tidak diperlukan — satu pembacaan mengembalikan data lengkap. Sebelum membaca, requestMtu() dapat dipanggil untuk menegosiasikan MTU maksimum.

kotlin
// Membaca karakteristik dan deskriptor melalui BluetoothGatt
class GattReader {

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

    // Proses data di callback onCharacteristicRead:
    fun parseHeartRate(value: ByteArray): Int {
        // BLE Heart Rate: byte = flags, kedua = 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
    }
}

Kelas GattReader mendemonstrasikan pembacaan karakteristik Heart Rate. Layanan 0x180D berisi karakteristik 0x2A37 (Heart Rate Measurement) — profil BLE standar Bluetooth SIG. Sebelum membaca, properti PROPERTY_READ diperiksa melalui hasProperty. parseHeartRate mem-parsing format BLE detak jantung: byte pertama — flags (format data), kedua — nilai bpm. Deskriptor CCCD (0x2902) dibaca untuk memeriksa status notifikasi.

Menulis karakteristik: writeCharacteristic dengan WriteType

writeCharacteristic() — metode BluetoothGatt untuk menulis data ke periferal BLE. Pada Android API 33+, writeCharacteristic() digantikan oleh writeCharacteristic(request), di mana BluetoothGattCharacteristicWriteRequest adalah objek permintaan yang berisi karakteristik, array byte, dan WriteType. Metode lama writeCharacteristic(characteristic) dengan setValue() sudah tidak digunakan lagi. WriteType menentukan perilaku permintaan: WRITE_TYPE_DEFAULT (tergantung properti karakteristik), WRITE_TYPE_NO_RESPONSE (withoutResponse) dan WRITE_TYPE_SIGNED (otorisasi).

Pemilihan WriteType mempengaruhi kecepatan dan keandalan. WRITE_TYPE_DEFAULT biasanya sesuai dengan withResponse (jika karakteristik memiliki PROPERTY_WRITE) atau withoutResponse (jika memiliki PROPERTY_WRITE_NO_RESPONSE). Untuk data aliran (pembaruan OTA, log) gunakan WRITE_TYPE_NO_RESPONSE — bandwidth maksimal. Untuk perintah dengan jaminan pengiriman (aktivasi, konfigurasi) — WRITE_TYPE_DEFAULT dengan konfirmasi melalui onCharacteristicWrite.

kotlin
// Penulisan karakteristik BLE di Android API 33+
class GattWriter {

    // Menulis dengan respons (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)
        }
    }

    // Menulis tanpa respons (kecepatan maksimal)
    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)
        }
    }

    // Callback 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")
            }
        }
    }
}

Kelas GattWriter mendukung kedua WriteType untuk tingkat API yang berbeda. writeWithResponse menggunakan WRITE_TYPE_DEFAULT — perangkat BLE mengonfirmasi penulisan melalui onCharacteristicWrite. writeWithoutResponse menggunakan WRITE_TYPE_NO_RESPONSE — data dikirim tanpa konfirmasi, bandwidth maksimal. Pada API 33+ digunakan writeCharacteristic(request) baru dengan BluetoothGattCharacteristicWriteRequest. Pada API < 33 — setValue() lama + writeCharacteristic().

Berlangganan notifikasi: setCharacteristicNotification dan CCCD

setCharacteristicNotification() — metode BluetoothGatt untuk berlangganan notifikasi perubahan karakteristik pada periferal. Setelah aktivasi langganan, perangkat BLE mengirim nilai baru melalui onCharacteristicChanged(). Namun setCharacteristicNotification() hanya mengaktifkan notifikasi lokal Android — untuk mengaktifkan notifikasi pada perangkat BLE itu sendiri, perlu juga menulis nilai 0x0100 ke deskriptor CCCD (0x2902).

CCCD (Client Characteristic Configuration Descriptor) — deskriptor yang mengelola pengiriman notifikasi dari periferal BLE. Nilai 0x0000 — notifikasi dinonaktifkan, 0x0100 — notifikasi diaktifkan (notifications), 0x0200 — indikasi diaktifkan (indications). Penulisan ke CCCD dilakukan melalui writeDescriptor() pada BluetoothGatt setelah pemanggilan setCharacteristicNotification(). Android tidak menulis CCCD secara otomatis — tanggung jawab ini ada pada pengembang.

kotlin
// Langganan notifikasi BLE yang benar
class GattNotificationManager {

    // 1. Aktifkan notifikasi
    fun enableNotification(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) {
        // Langkah 1: langganan lokal Android
        val success = gatt.setCharacteristicNotification(characteristic, true)
        if (!success) {
            print("Gagal berlangganan")
            return
        }

        // Langkah 2: tulis CCCD (0x2902) di perangkat BLE
        val cccdDescriptor = characteristic.getDescriptor(
            UUID.fromString("00002902-0000-1000-8000-00805F9B34FB")
        ) ?: return

        // 0x0100 = notifikasi, 0x0200 = indikasi
        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. Penemuan karakteristik
    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. Callback notifikasi
    private val notificationCallback = object : BluetoothGattCallback() {
        override fun onCharacteristicChanged(
            gatt: BluetoothGatt,
            characteristic: BluetoothGattCharacteristic,
            value: ByteArray,
            callbackType: Int
        ) {
            // Nilai baru dari periferal BLE
            print("Notification: ${value.size} bytes")
        }
    }
}

Kelas GattNotificationManager mengimplementasikan protokol dua langkah yang benar untuk berlangganan notifikasi BLE. enableNotification pertama memanggil setCharacteristicNotification(true) pada Android, kemudian menulis 0x0100 ke deskriptor CCCD melalui writeDescriptor. disableNotification melakukan operasi sebaliknya. Tanpa penulisan CCCD, perangkat BLE tidak mengirim notifikasi — ini adalah kesalahan paling umum pengembang BLE di Android.

Contoh klien GATT di Kotlin dengan BluetoothGattCallback

Contoh lengkap klien GATT di Kotlin, yang menggabungkan pembuatan BluetoothGatt, penemuan, pembacaan, dan berlangganan notifikasi dalam satu manajer menggunakan coroutine untuk pemrosesan asinkron.

kotlin
// Klien GATT lengkap dengan coroutine di Kotlin
class GattClient(context: Context) {

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

    // Hubungkan dengan 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
            )
        }

    // Baca karakteristik melalui coroutine
    suspend fun readCharacteristicValue(char: BluetoothGattCharacteristic): ByteArray? =
        suspendCoroutine { continuation ->
            gatt?.let { gatt ->
                // Simpan tag karakteristik untuk identifikasi callback
                gatt.setCharacteristic(char, null)  // untuk API < 33
                gatt.readCharacteristic(char)
            }
        }

    // Tutup koneksi
    fun release() {
        gatt?.disconnect()
        gatt?.close()
        gatt = null
    }
}

Klien GATT GattClient menggunakan coroutine (suspendCoroutine) untuk mengubah API BluetoothGatt berbasis callback menjadi panggilan sekuensial. connect() menunggu onServicesDiscovered, setelah itu hierarki GATT tersedia. readCharacteristicValue() menunggu onCharacteristicRead. Pendekatan ini menghilangkan callback bersarang dan membuat kode BLE linier. release() menjamin pembebasan sumber daya — panggilan wajib di onDestroy Activity atau ViewModel.onCleared.

Pertanyaan yang sering diajukan

Apa itu BluetoothGatt di Android?

BluetoothGatt — kelas untuk klien GATT Android yang mengelola koneksi BLE dengan perangkat periferal. Dibuat melalui BluetoothDevice.connectGatt(), menyediakan metode discoverServices(), readCharacteristic(), writeCharacteristic(), setCharacteristicNotification(). Hasil semua operasi datang secara asinkron melalui BluetoothGattCallback. Tanpa BluetoothGatt, komunikasi BLE dua arah di Android tidak mungkin dilakukan.

Mengapa onServicesDiscovered mengembalikan status 133?

Status 133 (GATT_ERROR) berarti kesalahan internal tumpukan BLE Android. Penyebab: perangkat terputus selama penemuan, MTU lebih kecil dari minimum (23 byte), atau tumpukan BLE kelebihan beban. Solusi: ulangi discoverServices() dengan penundaan 500 md, periksa RSSI perangkat, dan pastikan periferal mendukung penemuan GATT dalam keadaan saat ini.

Bagaimana cara menulis karakteristik dengan konfirmasi yang benar?

Untuk menulis dengan konfirmasi, panggil writeCharacteristic() dengan WRITE_TYPE_DEFAULT (API 33+: BluetoothGattCharacteristicWriteRequest). Saat berhasil, perangkat BLE mengirim konfirmasi dan Android memanggil onCharacteristicWrite dengan GATT_SUCCESS. Jika perangkat tidak merespons dalam 30 detik (waktu habis tumpukan), callback mengembalikan status kesalahan. Untuk watchdog, gunakan Handler dengan postDelayed.

Bagaimana cara bekerja dengan BLE di Android 33+?

Di Android 13+ (API 33) metode BluetoothGatt berubah: writeCharacteristic() sekarang menerima BluetoothGattCharacteristicWriteRequest, readCharacteristic() — BluetoothGattCharacteristicReadRequest. Metode lama setValue()/writeCharacteristic() sudah tidak digunakan lagi. BluetoothGattCallback juga berubah: onCharacteristicRead(), onCharacteristicWrite(), onCharacteristicChanged() menerima ByteArray value dan callbackType. Gunakan Build.VERSION.SDK_INT untuk percabangan.

Berapa banyak koneksi BLE yang didukung Android?

Android mendukung 4–8 koneksi BLE-GATT simultan (tergantung produsen dan versi Android). Pixel/Google: hingga 7, Samsung: hingga 5, Xiaomi: hingga 4. Saat melampaui batas, connectGatt mengembalikan null atau onConnectionStateChange dengan kesalahan. Untuk bekerja dengan banyak perangkat, gunakan koneksi siklik atau Bluetooth Mesh.

Ringkasan

  • BluetoothGatt — klien GATT Android untuk koneksi BLE, dibuat melalui BluetoothDevice.connectGatt() dengan BluetoothGattCallback
  • discoverServices() — langkah wajib setelah koneksi untuk mendapatkan layanan, karakteristik, dan deskriptor perangkat BLE
  • Membaca — readCharacteristic() dengan hasil asinkron di onCharacteristicRead(); untuk data besar diperlukan negosiasi MTU
  • Menulis — writeCharacteristic() dengan WriteType: DEFAULT (withResponse) atau NO_RESPONSE (tanpa konfirmasi)
  • Notifikasi — aktivasi dua langkah: setCharacteristicNotification() + menulis CCCD (0x2902) dengan nilai 0x0100
  • API 33+ — metode baru writeCharacteristic(request) dan readCharacteristic(request) dengan objek permintaan
  • Pembebasan sumber daya — panggilan wajib disconnect() dan close() untuk mencegah kebocoran koneksi BLE

Kami akan mengembangkan aplikasi seluler turnkey

IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.

Diskusikan proyek

Baca juga