Bluetooth Low energy Chat Application Series

Overview of Chat application:

  1. How Bluetooth Low energy device works #Post 1
  2. Setting up Gatt Server
  3. Setting up Gatt Client #Post 3
  4. Sending Data over Bluetooth Low energy network

Post 2 - Setting up Gatt Server

  1. Add permissions
  2. Setup UUIDs for your service, Characteristics and meta-data
  3. Setup Gatt Server

Add permissions

<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>

Setup UUIDs

Use this url to generate UUID - (https://www.uuidgenerator.net/)

val SERVICE_ID = "364710c0-6359-4bdf-9946-9f54d07eb8d3"
val USER_META_DATA_ID = "770bf5dc-53f8-4d55-8506-15a51baee22d"
val SERVICE_UUID = UUID.fromString(SERVICE_ID)
val USER_META_DATA_UUID = UUID.fromString(USER_META_DATA_ID)

Setup Gatt Server

  1. Get BluetoothManager - Goto step 2 after some delay eg - 2 seconds
  2. Setup BluetoothLeAdvertiser
  3. Create GattServerCallback - in this callback you will receive message
  4. Open GattServer
  5. Add your service to the GATT server
  6. Create AdvertiseCallback - to know whether scan is started or not
  7. Start advertising your GATT server

Note - All above points are necessary

1. Get BluetoothManager

val bluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
# Goto to step 2 after some delay eg - 2 seconds
# Eg - Use a handler 
Handler.postDelayed({callStep2()}, 2000L)

2. Setup BluetoothLeAdvertiser

val mBluetoothLeAdvertiser = mBluetoothAdapter.bluetoothLeAdvertiser;

3. Create GattServerCallback

    inner class GattServerCallback : BluetoothGattServerCallback() {

        override fun onDescriptorReadRequest(device: BluetoothDevice?, requestId: Int, offset: Int, descriptor: BluetoothGattDescriptor?) {

        }

        override fun onConnectionStateChange(device: BluetoothDevice?, status: Int, newState: Int) {
            super.onConnectionStateChange(device, status, newState);
            
        }

        //RECEIVER END    
        override fun onCharacteristicWriteRequest(device: BluetoothDevice?, requestId: Int, characteristic: BluetoothGattCharacteristic?, preparedWrite: Boolean, responseNeeded: Boolean, offset: Int, value: ByteArray?) {        

        }

        override fun onCharacteristicReadRequest(device: BluetoothDevice?, requestId: Int, offset: Int, characteristic: BluetoothGattCharacteristic?) {
            super.onCharacteristicReadRequest(device, requestId, offset, characteristic)
        }

        override fun onDescriptorWriteRequest(device: BluetoothDevice?, requestId: Int, descriptor: BluetoothGattDescriptor?, preparedWrite: Boolean, responseNeeded: Boolean, offset: Int, value: ByteArray?) {
            super.onDescriptorWriteRequest(device, requestId, descriptor, preparedWrite, responseNeeded, offset, value)

        }
    }
    val gattServerCallback = GattServerCallback()

4. Open GATT Server

var mGattServer: BluetoothGattServer? = mBluetoothManager.openGattServer(context, gattServerCallback)

5. Add service to the GATT Server

val service = BluetoothGattService(SERVICE_UUID, BluetoothGattService.SERVICE_TYPE_PRIMARY)

service.addCharacteristic(BleMessageUtil.prepareCharateristic(USER_META_DATA_UUID, USER_META_DATA_DESCRIPTOR_UUID))

service.addCharacteristic(BleMessageUtil.prepareCharateristic(ONE_TO_ONE_MSG_UUID, ONE_TO_ONE_MSG_DESCRIPTOR_UUID))

mGattServer?.addService(service)

6. Create AdvertiseCallback

val mAdvertiseCallback = object : AdvertiseCallback() {
        override fun onStartSuccess(settingsInEffect: AdvertiseSettings) {
            sendLog("Peripheral advertising started.")
        }

        override fun onStartFailure(errorCode: Int) {
            sendLog("Peripheral advertising failed: $errorCode")
        }
    }

7. Start advertising your GATT server

if (mBluetoothLeAdvertiser == null) {
            return
        }
val settings = AdvertiseSettings.Builder()
                .setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_BALANCED)
                .setConnectable(true)
                .setTimeout(0)
                .setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_LOW)
                .build()

val parcelUuid = ParcelUuid(SERVICE_UUID)
val data = AdvertiseData.Builder()
                .setIncludeDeviceName(false)// because data is greater than 31 bytes
                .addServiceUuid(parcelUuid)
                .build()

mBluetoothLeAdvertiser?.startAdvertising(settings, data, mAdvertiseCallback);

Reference

  • https://developer.android.com/guide/topics/connectivity/bluetooth-le
  • https://www.bignerdranch.com/blog/bluetooth-low-energy-part-1/