1

I am writing an Android app to talk with an BLE meter. I have been able to scan devices, connect to the target, discover services, get characteristics. However, when I try to write a write_no_reponse characteristics the method always returns false. I am sure the characteristics is writeable, i use others app do it. When I debugged into the android.bluetooth code, the following sequence occurs failure, maybe it return a null service, debug run to this step and then step out the method:

BluetoothGattService service = characteristic.getService(); 

which causes the writeCharacteristic return false. But before writeCharacteristic, I have a log

Log.d(TAG, "onServicesDiscovered: writeType" + mCharacteristic.getService());
bluetoothGatt.writeCharacteristic(mCharacteristic);

and the log is correct and does not return null;

Any help is greatly appreciated!

And I use the same code to write to a WRITE characteristics, it worked. And I try use the

mCharacteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);

to set the write type, but it also failed.

the write data code:

public void writeReadDataCommand() {
    if (null != bluetoothGatt) {
        mCharacteristic.setValue("123123");
        bluetoothGatt.setCharacteristicNotification(mCharacteristic, true);
        mCharacteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
        Log.d(TAG, "onServicesDiscovered: writeType" + mCharacteristic.getService());
        boolean isWrite = bluetoothGatt.writeCharacteristic(mCharacteristic);
        if (isWrite) {
            Log.d(TAG, "writeReadDataCommand: write data to BLE");
        }
    }
}

the onServiceDiscovered code:

@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
    super.onServicesDiscovered(gatt, status);

    if (status == BluetoothGatt.GATT_SUCCESS) {
        bluetoothGatt = gatt;
        BluetoothGattService service = gatt.getService(UUID.fromString(SERVICE_UUID));
        BluetoothGattCharacteristic characteristic = service.getCharacteristic(UUID.fromString(CHARACTERISTIC_UUID));
        Log.d(TAG, "onServicesDiscovered: writeType" + characteristic.getWriteType());

        boolean isSuccess = gatt.setCharacteristicNotification(characteristic, true);
        if (isSuccess) {
            mCharacteristic = characteristic;
            List<BluetoothGattDescriptor> descriptors = characteristic.getDescriptors();
            if (null != descriptors && descriptors.size() > 0) {
                for (BluetoothGattDescriptor descriptor : descriptors) {
                    descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                    gatt.writeDescriptor(descriptor);
                }
            }
        }
        connectCallback.findService();
    } else {
        Log.d(TAG, "onServicesDiscovered received: " + status);
    }
}

and the onCharacteristicWrite callback does not trigger

public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
    Log.d(TAG, "onCharacteristicWrite: " + Arrays.toString(characteristic.getValue()));
}

I have this bug for a long time, thanks so much if someone could help.

syjsyj
  • 11
  • 4
  • 1
    Do you wait for onDescriptorWrite until you call writeReadDataCommand? – Emil Aug 07 '19 at 07:49
  • yes, connectCallback.findService() do this, i use a dialog waiting for it, and cancel this dialog when the code run to the end of onServicesDiscovered() method, and then i can click a button to do writeReadDataCommand() method – syjsyj Aug 07 '19 at 08:59
  • @Emil Thanks for Providing such a valuable Hint , It was helpful – vinay shetty Jan 26 '21 at 13:32

2 Answers2

0

characteristics

as the pic can see, I have 2 characteristic in my service -- 0 and 1. The characteristics have the same uuid. The first I do is

BluetoothGattCharacteristic characteristic = service.getCharacteristic(UUID.fromString(CHARACTERISTIC_UUID));

This code find the 0 characteristic, and I write data to it.Obviously, I failed. Because the 0 characteristic can only READ and NOTIFY. So I do the follow step to write date to BLE

                characteristics = service.getCharacteristics();
                for(BluetoothGattCharacteristic characteristic : characteristics){
                    if(characteristic.getUuid().equals(UUID.fromString(CHARACTERISTIC_UUID))){
                        enableNotification(characteristic);
                    }
                }
            for(BluetoothGattCharacteristic characteristic : characteristics){
                if(characteristic.getUuid().equals(UUID.fromString(CHARACTERISTIC_UUID))){
                    characteristic.setValue("123123");
                    characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);

                    boolean isWrite = bluetoothGatt.writeCharacteristic(characteristic);
                    if (isWrite) {
                        Log.d(TAG, "writeReadDataCommand: write data to ble");
                    }
                }
            }

I try notify the two characteristics and write data to the two characteristics, althoght they have the same UUID, they have different function. Obviously, one characteristic will notify failed, one will write failed. But finally I successful write my data.

syjsyj
  • 11
  • 4
0

After onDescriptorWrite() send Data to BLE Device.

 private final BluetoothGattCallback getGattCallback1=new BluetoothGattCallback() {
        @Override
        public void onPhyUpdate(BluetoothGatt gatt, int txPhy, int rxPhy, int status) {
            super.onPhyUpdate(gatt, txPhy, rxPhy, status);
        }

        @Override
        public void onPhyRead(BluetoothGatt gatt, int txPhy, int rxPhy, int status) {
            super.onPhyRead(gatt, txPhy, rxPhy, status);
        }

        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            super.onConnectionStateChange(gatt, status, newState);
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            super.onServicesDiscovered(gatt, status);
        }

        @Override
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            super.onCharacteristicRead(gatt, characteristic, status);
        }

        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            super.onCharacteristicWrite(gatt, characteristic, status);
        }

        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            super.onCharacteristicChanged(gatt, characteristic);
        }

        @Override
        public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            super.onDescriptorRead(gatt, descriptor, status);
        }

        @Override
        public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            super.onDescriptorWrite(gatt, descriptor, status);
            // here send broadcast to MainActivity.That u are ready to write Data To the device.
        }

        @Override
        public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {
            super.onReliableWriteCompleted(gatt, status);
        }

        @Override
        public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
            super.onReadRemoteRssi(gatt, rssi, status);
        }

        @Override
        public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
            super.onMtuChanged(gatt, mtu, status);
        }
    };

 @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    public void setCharacteristicNotifications(BluetoothGatt bluetoothGatt,BluetoothGattCharacteristic characteristic,
                                               boolean enabled,String bleAddress) {
        if (mBluetoothAdapter == null || bluetoothGatt == null) {
            return;
        }
        bluetoothGatt.setCharacteristicNotification(characteristic, enabled);
        BluetoothGattDescriptor descriptor = null;
        descriptor = characteristic.getDescriptor(UUID.fromString(CLIENT_CHARACTERISTIC_CONFIG));
        if (descriptor == null) {
            enableNotiticationToFirmwareCompleted(false,bleAddress);
            return;
        }
        descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
        bluetoothGatt.writeDescriptor(descriptor);

     }
vinay shetty
  • 895
  • 1
  • 9
  • 15