GATT (Generic Attribute Profile) é um perfil Bluetooth Low Energy (BLE) que define a estrutura de dados e as regras de troca de informações entre dispositivos BLE. O GATT é construído sobre o Protocolo de Atributos (ATT) e organiza os dados em uma hierarquia: serviços, características e descritores. De acordo com a Bluetooth SIG (2025), o perfil GATT é usado em 98% de todas as aplicações BLE — desde rastreadores de fitness até fechaduras inteligentes e sensores médicos.
Pontos principais
GATT (Generic Attribute Profile) é um perfil Bluetooth Low Energy (BLE) que define como dois dispositivos BLE trocam dados através do Protocolo de Atributos (ATT). O GATT padroniza a estrutura de dados: todos os dados são organizados em uma hierarquia “serviço → característica → descritor”. O perfil foi introduzido na especificação Bluetooth 4.0 (2010) juntamente com o BLE e desde então continua sendo o principal mecanismo de transferência de dados para dispositivos Bluetooth de baixo consumo. Ao contrário do Bluetooth clássico, onde os dados são transmitidos através de uma porta serial (SPP), o GATT fornece acesso estruturado aos dados através de operações de leitura, escrita e notificações.
A pilha BLE consiste em várias camadas: Camada Física (rádio), Camada de Enlace (gerenciamento de conexão), L2CAP (controle de canal lógico), ATT (Protocolo de Atributos — acesso a atributos) e GATT (perfil baseado em ATT). O GATT é a camada mais alta com a qual os desenvolvedores de aplicativos trabalham. O ATT subjacente fornece operações básicas: leitura, escrita, notificação e indicação de atributos. O GATT adiciona semântica: define o que são um serviço e uma característica, como eles são agrupados e quais regras se aplicam ao lê-los e escrevê-los. De acordo com a Bluetooth Core Specification 5.4 (2023), o GATT suporta até 65.535 atributos (serviços + características + descritores) em um único dispositivo.
A hierarquia GATT consiste em três níveis. Um Serviço é um grupo lógico de características que resolve uma tarefa (por exemplo, “Serviço de Bateria” ou “Serviço de Frequência Cardíaca”). Uma Característica é uma unidade de dados com um tipo conhecido: nível de bateria atual, leitura de sensor, estado de interruptor. Cada característica tem um valor e um ou mais Descritores que descrevem metadados: unidades de medida, configurações de notificação, faixa de valores. UUID (Identificador Único Universal) identifica exclusivamente cada serviço e cada característica.
GATT suporta quatro tipos de operações para interagir com características. Read — o cliente solicita o valor atual de uma característica ao servidor. Write — o cliente envia um novo valor para o servidor. Notify — o servidor envia um valor ao cliente sem confirmação (mais rápido, mas menos confiável). Indicate — o servidor envia um valor com confirmação de recebimento (mais confiável, mas mais lento). O desenvolvedor escolhe o tipo com base no cenário: para leituras de sensor de frequência cardíaca, Notify é suficiente; para escrever a configuração de uma fechadura inteligente, Write com confirmação é necessário.
// Estrutura de dados GATT no código Android
data class BleService(
val uuid: UUID,
val characteristics: List<BleCharacteristic>
)
data class BleCharacteristic(
val uuid: UUID,
val properties: Int, // READ, WRITE, NOTIFY, INDICATE
val descriptors: List<BleDescriptor>,
var value: ByteArray?
)
A especificação BLE define dois perfis principais: GAP (Generic Access Profile) e GATT (Generic Attribute Profile). O GAP é responsável pela descoberta de dispositivos, estabelecimento de conexão e gerenciamento de visibilidade — é a “camada de rede” do BLE. O GATT é responsável pela troca de dados após o estabelecimento da conexão — a “camada de aplicação”. O desenvolvedor usa o GAP para escanear e conectar a um dispositivo, e o GATT para ler, escrever e receber notificações do dispositivo conectado.
| Característica | GAP | GATT |
|---|---|---|
| Propósito | Descoberta e conexão | Troca de dados |
| Funções | Central / Periférico | Cliente / Servidor |
| Protocolo | HCI, Camada de Enlace | ATT (Protocolo de Atributos) |
| Fase | Antes da conexão | Após a conexão |
| Classe principal | BluetoothAdapter | BluetoothGatt |
O GATT define duas funções: Servidor GATT e Cliente GATT. O Servidor é um dispositivo que fornece dados (por exemplo, um rastreador de fitness enviando leituras de frequência cardíaca). O Cliente é um dispositivo que solicita dados (por exemplo, um smartphone lendo as leituras). Na maioria dos cenários, o aplicativo Android atua como Cliente GATT e o periférico BLE atua como Servidor GATT. No entanto, o Android também pode ser um Servidor GATT — por exemplo, quando um aplicativo emula um dispositivo BLE para outros dispositivos. A função é determinada na fase de configuração da conexão GATT e não muda durante a sessão.
O processo de comunicação GATT começa após o estabelecimento da conexão BLE entre os dispositivos. Primeiro, o Cliente GATT descobre os serviços no Servidor GATT através da Descoberta de Serviços — o Android faz isso automaticamente ao conectar através de BluetoothGatt.discoverServices(). Após a descoberta, o cliente obtém uma lista de serviços, características e descritores disponíveis. Em seguida, o cliente pode ler valores de características (Read), escrever novos valores (Write) ou se inscrever em notificações (Set Notify/Indicate). O Servidor GATT pode enviar Notify/Indicate ao cliente a qualquer momento após o estabelecimento da conexão.
Por padrão, o tamanho de um único pacote GATT (MTU) no BLE é de 23 bytes, dos quais 3 bytes são o cabeçalho ATT e 20 bytes são dados úteis. Se o aplicativo precisar transmitir mais dados (por exemplo, atualização OTA de firmware), é possível solicitar um aumento do MTU para até 517 bytes através de requestMtu() no Android. Um MTU maior reduz o número de pacotes necessários para transmitir um bloco de dados — em vez de 50 pacotes pequenos, você pode enviar 2 grandes, o que reduz o consumo de energia e acelera a transmissão. O MTU máximo depende da versão do BLE e das capacidades do chip — Bluetooth 5.0 suporta até 517 bytes, versões mais antigas até 247 bytes.
// Inscrever-se em notificações de características
fun enableNotifications(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) {
gatt.setCharacteristicNotification(characteristic, true)
// Ativar CCCD (Descritor de Configuração de Característica do Cliente)
val cccdUuid = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb")
val descriptor = characteristic.getDescriptor(cccdUuid)
descriptor?.let {
it.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE)
gatt.writeDescriptor(it)
}
}
Para receber notificações do Servidor GATT no Android, você precisa implementar o callback BluetoothGattCallback.onCharacteristicChanged(). Neste método, o aplicativo recebe o valor atualizado da característica cada vez que o servidor envia Notify ou Indicate. Para processamento de dados em tempo real, use um buffer e corrotinas Kotlin — isso evita bloquear a thread de UI durante notificações intensivas (por exemplo, mais de 100 leituras de frequência cardíaca por segundo). Para Indicações, você deve chamar gatt.sendResponse() no lado do servidor — no cliente Android, isso é tratado automaticamente.
No Android, o trabalho com GATT é implementado através das classes do pacote android.bluetooth: BluetoothGatt (conexão), BluetoothGattService (serviço), BluetoothGattCharacteristic (característica) e BluetoothGattDescriptor (descritor). A conexão a um dispositivo BLE começa chamando BluetoothDevice.connectGatt() — este método retorna um BluetoothGatt através do qual todas as operações subsequentes são realizadas. Todos os callbacks GATT chegam em BluetoothGattCallback — esta é uma interface assíncrona que é chamada na mesma thread onde o BluetoothGatt foi criado. Importante: todas as operações GATT devem ser executadas sequencialmente — chamar várias operações simultaneamente no mesmo BluetoothGatt causa erros.
O gerenciamento adequado do ciclo de vida da conexão GATT é crítico para a estabilidade do aplicativo BLE. Após chamar connectGatt(), o aplicativo aguarda o callback onConnectionStateChange() com o estado STATE_CONNECTED. Em seguida, o sistema inicia automaticamente a Descoberta de Serviços, após a qual onServicesDiscovered() é chamado. Só então você pode realizar leitura, escrita e inscrição. Ao finalizar, sempre chame gatt.close() em onDestroy() ou onPause() — conexões GATT não fechadas consomem bateria e podem bloquear a reconexão ao mesmo dispositivo no Android.
// Conectar ao dispositivo BLE via GATT
private val gattCallback = object : BluetoothGattCallback() {
override fun onConnectionStateChange(
gatt: BluetoothGatt, status: Int, newState: Int
) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
gatt.discoverServices()
}
}
override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) {
val service = gatt.getService(UUID.fromString("180D"))
val characteristic = service?.getCharacteristic(
UUID.fromString("2A37")
)
characteristic?.let { enableNotifications(gatt, it) }
}
}
Bluetooth SIG define dezenas de perfis e serviços GATT padrão com UUIDs fixos de 16 bits. Os mais comuns: Battery Service (UUID 180F, característica Battery Level 2A19), serviço Heart Rate (UUID 180D, característica Heart Rate Measurement 2A37), serviço Device Information (UUID 180A, características Manufacturer Name e Serial Number). O uso de serviços padrão garante compatibilidade entre dispositivos de diferentes fabricantes — qualquer pulseira de fitness com um serviço Heart Rate deve funcionar com qualquer aplicativo Android que o suporte.
Se os serviços padrão não cobrirem a tarefa, o desenvolvedor pode criar serviços GATT personalizados com UUIDs de 128 bits. Ao projetar um serviço personalizado, você precisa: definir um grupo lógico de características (por exemplo, “Serviço de Controle de Fechadura”), atribuir a cada característica as propriedades corretas (Read, Write, Notify), definir valores permitidos e unidades de medida através do descritor Characteristic Presentation Format. Para protocolos complexos, recomenda-se incluir uma característica Command com propriedade Write e uma característica Status com Notify — isso segue o padrão Command/Status adotado em aplicações BLE industriais.
// Criar serviço GATT personalizado (Android como Servidor GATT)
private fun createCustomService(): BluetoothGattService {
val serviceUuid = UUID.fromString("12345678-1234-5678-1234-56789abcdef0")
val service = BluetoothGattService(
serviceUuid, BluetoothGattService.SERVICE_TYPE_PRIMARY
)
val charUuid = UUID.fromString("12345678-1234-5678-1234-56789abcdef1")
val characteristic = BluetoothGattCharacteristic(
charUuid,
BluetoothGattCharacteristic.PROPERTY_READ or
BluetoothGattCharacteristic.PROPERTY_NOTIFY,
BluetoothGattCharacteristic.PERMISSION_READ
)
service.addCharacteristic(characteristic)
return service
}
Perguntas frequentes
GATT (Generic Attribute Profile) é um perfil Bluetooth Low Energy que define a estrutura de troca de dados entre dispositivos. É necessário para padronizar o acesso à informação: todos os dispositivos BLE organizam dados em serviços e características, permitindo que qualquer cliente leia leituras de sensores, controle dispositivos e receba notificações.
GAP é responsável pela descoberta e conexão de dispositivos BLE (escaneamento, publicidade, configuração de conexão). GATT é responsável pela troca de dados após a conexão (leitura, escrita, notificações). GAP funciona antes da conexão, GATT depois. Ambos os perfis são obrigatórios para BLE, mas desempenham funções diferentes: GAP é a “camada de rede”, GATT é a “camada de aplicação”.
Os serviços padrão incluem Battery Service (180F, nível de bateria), Heart Rate (180D, pulso), Device Information (180A, dados do dispositivo). Cada serviço contém várias características com UUIDs de 16 bits. Os desenvolvedores podem criar serviços personalizados com UUIDs de 128 bits para tarefas específicas — como controle de fechadura inteligente ou transmissão de dados de rastreador de fitness.
No Android, o GATT é implementado através de BluetoothGatt (conexão), BluetoothGattService (serviço), BluetoothGattCharacteristic (característica) e BluetoothGattDescriptor (descritor). A conexão é feita via connectGatt(), após o qual os eventos chegam através de BluetoothGattCallback: onConnectionStateChange, onServicesDiscovered, onCharacteristicChanged (para notificações). Todas as operações GATT devem ser executadas sequencialmente.
UUID (Identificador Único Universal) é um identificador de 16 ou 128 bits que identifica exclusivamente um serviço ou característica no GATT. Os serviços padrão Bluetooth SIG usam UUIDs de 16 bits (por exemplo, 180D para Heart Rate). Os serviços personalizados do desenvolvedor usam UUIDs de 128 bits (por exemplo, 12345678-1234-5678-1234-56789abcdef0). O UUID permite que o cliente encontre os dados necessários no Servidor GATT.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também