AndroidDeveloperJJ
AndroidDeveloperJJ

Reputation: 25

BLE bluetooth data sent after device disconnected on Android

BLE device gets the data when it is disconnected from the gatt server. I am trying to send data to the BLE device through the GATT server. When I try to send data which is command (string) to the BLE device, gattscancallback is called and it says write successful but nothing happens to the BLE device. But when I exit the application, the BLE device gets the data. I found that BLE device gets the data when it is disconnected to the gatt server. How do I solve this problem? this is my GattCallback

private val gattCallback: BluetoothGattCallback = object : BluetoothGattCallback() {
    override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {
        super.onConnectionStateChange(gatt, status, newState)
        if( status == BluetoothGatt.GATT_FAILURE ) {
            disconnect()
            return
        } else if( status != BluetoothGatt.GATT_SUCCESS ) {
            disconnect()
            return
        }
        if( newState == BluetoothProfile.STATE_CONNECTED ) {
            // update the connection status message

            Log.d(TAG, "Connected to the GATT server")
            gatt.discoverServices()
        } else if ( newState == BluetoothProfile.STATE_DISCONNECTED ) {
            disconnect()
        }
    }
    override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) {
        super.onServicesDiscovered(gatt, status)

        // check if the discovery failed
        if (status != BluetoothGatt.GATT_SUCCESS) {
            Log.e(TAG, "Device service discovery failed, status: $status")
            return
        }
        // log for successful discovery
        Log.d(TAG, "Services discovery is successful")
        isStatuschanged = "connected"

        // find command characteristics from the GATT server
        val respCharacteristic = gatt?.let { BluetoothUtils.findResponseCharacteristic(it) }
        // disconnect if the characteristic is not found
        if( respCharacteristic == null ) {
            Log.e(TAG, "Unable to find cmd characteristic")
            disconnect()
            return
        }
        gatt.setCharacteristicNotification(respCharacteristic, true)
        // UUID for notification
        val descriptor: BluetoothGattDescriptor = respCharacteristic.getDescriptor(
            UUID.fromString(CLIENT_CHARACTERISTIC_CONFIG)
        )
        descriptor.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
        gatt.writeDescriptor(descriptor)
    }

    override fun onCharacteristicChanged(
        gatt: BluetoothGatt?,
        characteristic: BluetoothGattCharacteristic
    ) {
        super.onCharacteristicChanged(gatt, characteristic)
        //Log.d(TAG, "characteristic changed: " + characteristic.uuid.toString())
        readCharacteristic(characteristic)
    }

    override fun onCharacteristicWrite(
        gatt: BluetoothGatt?,
        characteristic: BluetoothGattCharacteristic?,
        status: Int
    ) {
        super.onCharacteristicWrite(gatt, characteristic, status)
        if (status == BluetoothGatt.GATT_SUCCESS) {
            Log.d(TAG, "Characteristic written successfully")
        } else {
            Log.e(TAG, "Characteristic write unsuccessful, status: $status")
            disconnect()
        }
    }

    override fun onCharacteristicRead(
        gatt: BluetoothGatt?,
        characteristic: BluetoothGattCharacteristic,
        status: Int
    ) {
        super.onCharacteristicRead(gatt, characteristic, status)
        if (status == BluetoothGatt.GATT_SUCCESS) {
            Log.d(TAG, "Characteristic read successfully")
            readCharacteristic(characteristic)
        } else {
            Log.e(TAG, "Characteristic read unsuccessful, status: $status")
            // Trying to read from the Time Characteristic? It doesnt have the property or permissions
            // set to allow this. Normally this would be an error and you would want to:
            // disconnectGattServer()
        }
    }

    /**
     * Log the value of the characteristic
     * @param characteristic
     */

}

this is my write function

fun write(message: String) {

    val cmdCharacteristic = BluetoothUtils.findCommandCharacteristic(bluetoothGatt!!)
    if (cmdCharacteristic == null) {
        Log.e(TAG, "Unable to find cmd characteristic")
        disconnect()
        return
    }

    cmdCharacteristic?.value = message.toByteArray()
    //bluetoothGatt!!.writeCharacteristic(cmdCharacteristic)
    val success: Boolean = bluetoothGatt!!.writeCharacteristic(cmdCharacteristic)
    if (!success) {
        Log.d("jay", "failed to write command")
    }
    Log.d("jay", "write succesful")
    //disconnect()
}

this is my disconnect function

fun disconnect() {
    Log.d("jay", "disconnect: bluetoothGatt is null? ${bluetoothGatt == null}")
    bluetoothDeviceAddress = null
    bluetoothGatt?.disconnect()
    isStatuschanged = "disconnected"
    bluetoothGatt = null
}

Upvotes: 2

Views: 421

Answers (1)

genzo
genzo

Reputation: 24

Can you show the disconnect() method? Because if you wrote that your central device sends data to the ble device when the application closes, it means that gattCallback's onConnectionState is triggered with a call to newState == BluetoothProfile.STATE_DISCONNECTED and a call to the disconnet() method.

Perhaps the problem is that you explicitly need to specify the record type for the characteristic for example: BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT or BluetoothGattCharacteristic.WRITE_TYPE_WITHOUT_RESPONSE.

Also, there may be an error in the calling code, for example, if you use coroutines and manage them incorrectly

I recently had a similar problem when I solved it by specifying the feature write type and adding the setCharacteristicNotification() method

I had a similar problem recently, but I solved it by specifying the feature record type, and adding the setCharacteristicNotification method

Upvotes: 0

Related Questions