Ble Gatt Server
A Bluetooth Low Energy (BLE) GATT server implementation that allows an Android device to act as a BLE peripheral.
This class provides functionality to:
Start and stop a GATT server with customizable services and characteristics
Advertise the device to nearby BLE centrals (scanners)
Handle read/write requests from connected central devices
Send notifications to subscribed devices
Manage characteristic values and notification subscriptions
GATT Server Overview
A GATT (Generic Attribute Profile) server hosts a hierarchy of services and characteristics that can be discovered and interacted with by connected clients (centrals). This implementation includes:
Automatic handling of the Client Characteristic Configuration Descriptor (CCCD) for notification subscriptions
Support for prepared (long) writes with offset handling
Proper response handling for read and write requests
Required Permissions
The following permissions must be declared in AndroidManifest.xml:
android.permission.BLUETOOTH(for API < 31)android.permission.BLUETOOTH_ADMIN(for API < 31)android.permission.BLUETOOTH_ADVERTISE(for API >= 31)android.permission.BLUETOOTH_CONNECT(for API >= 31)
Usage Example
Setting up a basic BLE peripheral with Heart Rate Service:
class MyPeripheralActivity : AppCompatActivity() {
private lateinit var gattServer: BleGattServer
private val heartRateMeasurementUUID = UUID.fromString("00002A37-0000-1000-8000-00805f9b34fb")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val bluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
val bluetoothAdapter = bluetoothManager.adapter
// Initialize the GATT server
gattServer = BleGattServer(this, bluetoothAdapter)
// Start the server (this also starts advertising)
gattServer.startServer()
}
// Send heart rate updates to subscribed clients
private fun sendHeartRateUpdate(heartRate: Int) {
val value = byteArrayOf(0x00, heartRate.toByte()) // Flags + Heart Rate
gattServer.sendNotification(heartRateMeasurementUUID, value)
}
override fun onDestroy() {
super.onDestroy()
// Always stop the server when done
gattServer.stopServer()
}
}Custom Services Example
To create a peripheral with custom services, you can extend this class or modify the addServices method:
// Define custom UUIDs
val CUSTOM_SERVICE_UUID = UUID.fromString("12345678-1234-1234-1234-123456789abc")
val CUSTOM_CHAR_UUID = UUID.fromString("12345678-1234-1234-1234-123456789abd")
// Create a service with read/write/notify capabilities
val service = BluetoothGattService(CUSTOM_SERVICE_UUID, BluetoothGattService.SERVICE_TYPE_PRIMARY)
val characteristic = BluetoothGattCharacteristic(
CUSTOM_CHAR_UUID,
BluetoothGattCharacteristic.PROPERTY_READ or
BluetoothGattCharacteristic.PROPERTY_WRITE or
BluetoothGattCharacteristic.PROPERTY_NOTIFY,
BluetoothGattCharacteristic.PERMISSION_READ or
BluetoothGattCharacteristic.PERMISSION_WRITE
)
// Add CCCD for notification support
val cccd = BluetoothGattDescriptor(
CLIENT_CHARACTERISTIC_CONFIG_UUID,
BluetoothGattDescriptor.PERMISSION_READ or BluetoothGattDescriptor.PERMISSION_WRITE
)
characteristic.addDescriptor(cccd)
service.addCharacteristic(characteristic)Thread Safety
This class is not thread-safe. All method calls should be made from the main thread or properly synchronized. The GATT server callbacks are delivered on an internal Binder thread, which this implementation handles appropriately.
See also
Functions
Gets the current stored value of a characteristic.
Sends a notification to all connected devices that have enabled notifications for the specified characteristic.
Sets the value for a characteristic without sending a notification.
Initializes and starts the GATT server with predefined services and characteristics.
Stops the GATT server and BLE advertising.