BluetoothGatt.writeCharacteristic() success for the first time but return false after





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







0















i'am building a Android application that read data from some BLE devices, the process of the application start by :




  • Discover the devices.

  • check if they are paired, if not paird them.

  • connect to the first devices then read data of this devices, then stop and
    stay connected (if the first time that i want to connect to the device, i
    call connectGatt(), else if already connected call
    gatt.discoverServices() )

  • switch to second devices (connect + read + write + stop reading)


  • when i acheive the last device, i stop the process for a while, and i reapet
    the process from the begining



    All the process work fine the first time for all devices, but when the
    process go back to the first device and i call gatt.discoverServices() ,
    instead of connectGatt(), i get all the Services and also the Characteristics
    but my gatt.writeCharacteristic() fail and return false.



    can anyone help to know why it fails and how o fix this issue.



    this is how my code look like



     if (DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getBluetoothGatt() == null) {
    // if(true){
    log4jfile.info(" BluetoothGATT = null : call connectGatt");
    BluetoothService.reading_device = device.getAddress();

    bluetoothGatt = device.connectGatt(this, false, bluetoothGattCallback)

    if (DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getBluetoothGatt() == null) {
    DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).setBluetoothGatt(bluetoothGatt);
    }
    } else {

    if (mBluetoothManager.getConnectedDevices(BluetoothProfile.GATT).contains(device)) {
    log4jfile.info(" BluetoothGATT != null : call discoverServices");

    DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getBluetoothGatt().discoverServices();
    } else {
    log4jfile.info(" BluetoothGATT != null : call connect");
    DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getBluetoothGatt().connect();
    }

    }



Note:




  • i don't call connectGatt() many time for the same device because the number
    of BluetoothGatt that we could create in android is 32.


  • i d'on't call bluetoothGatt.close() after i finish cause i want stay
    connected to my devices all the time.



EDIT



bluetoothGatt = device.connectGatt(this, false, new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {

log4jfile.info("onConnectionStateChange, status : " + status + " parseConnection : " + GattStatusParse.parseConnection(status) + " or " + GattStatusParse.parseConnection(status));
DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).setSuccess_Counter(DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getSuccess_Counter() + 1);
isConnected = BluetoothProfile.STATE_CONNECTED == newState;
if (status == BluetoothGatt.GATT_SUCCESS) {
for (BluetoothDeviceWrapper blw : DeviceListAdapter.devices) {
if (blw.getDevice().getAddress().equals(device.getAddress())) {
blw.setConnectionFailed(false);
}
}
if (isConnected) {
log4jfile.info(" GATT connected " + device.getAddress() + " state of the opération : " + status + " connexion state : " + newState);
if (!connectedBluethoothDevice.contains(device)) {
connectedBluethoothDevice.add(device);
}
Log.i(TAG, "GATT connected." + connectedBluethoothDevice.toString());

gatt.discoverServices();
//LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));
BluetoothService.reading_device = device.getAddress();
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));
} else {
log4jfile.info(" GATT disconnected " + device.getAddress() + " state of the opération : " + status + " connexion state : " + newState);
if (connectedBluethoothDevice.contains(device)) {
connectedBluethoothDevice.remove(device);
}
Log.i(TAG, "GATT disconnected." + connectedBluethoothDevice.toString());
//NotificationService_.intent(BluetoothService.this).stop();
notificationManager.notify(442, getNotification(device));
BluetoothService.reading_device = "";
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));

}
} else {

if (connectedBluethoothDevice.contains(device)) {
// mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
int mConnectionState = mBluetoothManager.getConnectionState(device, BluetoothProfile.GATT);
if (mConnectionState == BluetoothProfile.STATE_DISCONNECTED || mConnectionState == BluetoothProfile.STATE_DISCONNECTING) {
connectedBluethoothDevice.remove(device);
}
}

for (BluetoothDeviceWrapper blw : DeviceListAdapter.devices) {
if (blw.getDevice().getAddress().equals(device.getAddress())) {
blw.setConnectionFailed(true);
}
}
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));

BluetoothService.FAILED_CONNECTION = BluetoothService.FAILED_CONNECTION + 1;
DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).setFail_Counter(DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getFail_Counter() + 1);
log4jfile.info("connection _ Failed : " + BluetoothService.FAILED_CONNECTION);
if (1 <= BluetoothService.FAILED_CONNECTION && BluetoothService.FAILED_CONNECTION < Integer.parseInt(NombreDeTentativeDeConnexion)) {
if (MainActivity.current == 0) {
MainActivity.current = DeviceListAdapter.devicesFounder.size() - 1;
} else {
MainActivity.current = MainActivity.current - 1;
}

if (!MainActivity.stoppedServices) {
Log.e(TAG, "sendBroadcast DEVICE_READ_DONE 2");
final Intent myIntent = new Intent(DEVICE_READ_DONE);
sendBroadcast(myIntent);
stopSelf();
}

} else {
BluetoothService.FAILED_CONNECTION = 0;
if (!MainActivity.stoppedServices) {
Log.e(TAG, "sendBroadcast DEVICE_READ_DONE 3");
final Intent myIntent = new Intent(DEVICE_READ_DONE);
sendBroadcast(myIntent);
stopSelf();
}
}
}

}

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

startForeground(442, getNotification(device));
log4jfile.info("Services discovered. status : " + status + " , parse status : " + GattStatusParse.parse(status));
BluetoothService.reading_device = gatt.getDevice().getAddress();
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));
if (status == BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION) {
log4jfile.info("GATT_INSUFFICIENT_AUTHENTICATION");
handleAuthenticationError(gatt);
return;
}

discoverCharacteristics(gatt);
}

@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
System.gc();
log4jfile.info("Characteristic written, status: " + status + " , parse status : " + GattStatusParse.parse(status));
//BluetoothService.reading_device=gatt.getDevice().getAddress();
if (status == BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION) {
log4jfile.error("GATT_INSUFFICIENT_AUTHENTICATION");
handleAuthenticationError(gatt);
return;
}

final byte command = characteristic.getValue()[0];
switch (command) {
case WRITE_TIME:
log4jfile.info("Time written.");
final BluetoothGattCharacteristic batteryCharacteristic = readableCharacteristics.get(Characteristic.BATTERY.getUuid());
gatt.setCharacteristicNotification(batteryCharacteristic, true);
for (BluetoothGattDescriptor descriptor : batteryCharacteristic.getDescriptors()) {
if (descriptor.getUuid().toString().startsWith("00002904")) {
descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
gatt.writeDescriptor(descriptor);
}
}
break;
case WRITE_NOTIFICATION:
log4jfile.info("Notification sent.");
if (notificationsQueue.isEmpty()) {
log4jfile.info("Reading characteristics...");
//BluetoothService.reading_device=gatt.getDevice().getAddress();
readNextCharacteristics(gatt);
} else {
log4jfile.info("writing next notification...");
alertIn.setValue(notificationsQueue.poll());
gatt.writeCharacteristic(alertIn);
}
break;
default:
log4jfile.info("No such ALERT IN command: " + command);
break;
}
}

@Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
log4jfile.info("onDescriptorWrite write, status: " + status + " , parse status : " + GattStatusParse.parse(status));
readCharacteristic(gatt, Characteristic.MANUFACTURER);
}

@Override
public void onCharacteristicRead(BluetoothGatt gatt, final BluetoothGattCharacteristic gattCharacteristic, int status) {
log4jfile.info("onCharacteristicRead, device : " + gatt.getDevice().getAddress() + " status : " + status + " , parse status : " + GattStatusParse.parse(status));
System.gc();
if (!MainActivity.stoppedServices && gatt.getDevice().getAddress().equals(BluetoothService.reading_device)) {
if (status == BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION) {
handleAuthenticationError(gatt);
return;
}

final String characteristicUuid = gattCharacteristic.getUuid().toString();
final Characteristic characteristic = Characteristic.byUuid(characteristicUuid);
switch (characteristic) {
case MANUFACTURER:
manufacturerInfo.manufacturer = gattCharacteristic.getStringValue(0);
readCharacteristic(gatt, Characteristic.FW_REVISION);
break;
case FW_REVISION:
manufacturerInfo.firmwareRevision = gattCharacteristic.getStringValue(0);
readCharacteristic(gatt, Characteristic.MODE);
break;
default:
//BluetoothService.reading_device=gatt.getDevice().getAddress();
//LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));
log4jfile.info("Characteristic read: " + characteristic.name() + " device " + gatt.getDevice().getAddress() + " basculeTimer :" + BluetoothService.basculeTimer);
if (1 > BluetoothService.FAILED_CONNECTION || BluetoothService.FAILED_CONNECTION >= 3) {
BluetoothService.FAILED_CONNECTION = 0;
}
BluetoothService.basculeTimer++;
if (BluetoothService.basculeTimer == 0 || BluetoothService.basculeTimer == 10) {
// BluetoothService.reading_device=gatt.getDevice().getAddress();
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));
}
if (!gatt.getDevice().getAddress().equals(BluetoothService.reading_device)) {
// BluetoothService.reading_device = bluetoothGatt.getDevice().getAddress();
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));
}
//BluetoothService.reading_device=gatt.getDevice().getAddress();

if (characteristic == Characteristic.MODE) {
final Mode newMode = Mode.bySymbol(gattCharacteristic.getValue()[0]);
log4jfile.info("mode change : " + newMode.name());
if (mode != newMode) {
onModeChanged(newMode);
}
} else {
onBluetoothDataReceived(characteristic, gattCharacteristic.getValue());
}

// if (shouldUpdateTime) {
// updateTime(gatt.getDevice());
// }

if (notificationsQueue.isEmpty()) {
log4jfile.info(" notificationsQueue isEmpty ==> readNextCharacteristics");
readNextCharacteristics(gatt);
} else {
log4jfile.info(" notificationsQueue NotisEmpty ==> writeCharacteristic");
alertIn.setValue(notificationsQueue.poll());
gatt.writeCharacteristic(alertIn);
}

break;
}
}
}

@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic gattCharacteristic) {
System.gc();
final String characteristicUuid = gattCharacteristic.getUuid().toString();
final Characteristic characteristic = Characteristic.byUuid(characteristicUuid);
log4jfile.info("Characteristic changed: " + characteristic.name());

if (characteristic == Characteristic.BATTERY) {
onBluetoothDataReceived(Characteristic.BATTERY, gattCharacteristic.getValue());
}
}
});


private void discoverCharacteristics(final BluetoothGatt gatt) {
log4jfile.info("discoverCharacteristics. services length : " + gatt.getServices().size());
//BluetoothService.reading_device = gatt.getDevice().getAddress();
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));
if (gatt.getServices().size() == 0) {
log4jfile.info("No services found.");
//LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.DEVICE_READ_DONE));
}

for (BluetoothGattService gattService : gatt.getServices()) {
if(gatt.getDevice().getAddress().equals(BluetoothService.reading_device)){
storeCharacteristicsFromService(gattService,gatt.getDevice());

}
}
}

private void storeCharacteristicsFromService(BluetoothGattService gattService,BluetoothDevice device) {
log4jfile.info("storeCharacteristicsFromService , length : " + gattService.getCharacteristics().size());
for (BluetoothGattCharacteristic gattCharacteristic : gattService.getCharacteristics()) {
final String characteristicUuid = gattCharacteristic.getUuid().toString();
final Characteristic characteristic = Characteristic.byUuid(characteristicUuid);

if (characteristic == Characteristic.ALERT_IN) {
log4jfile.info( "ALERT_IN DISCOVERED");
DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).setAlertIn(null);
DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).setAlertIn(gattCharacteristic);

alertIn = gattCharacteristic;
setTime();
if(device.getAddress().equals(BluetoothService.reading_device)) {
updateTime(device);
}
NotificationService_.intent(BluetoothService.this).start();
} else if (characteristic != null) {
log4jfile.info("characteristic " + characteristic);
log4jfile.info(characteristic.getType() + ": " + characteristic.name());
readableCharacteristics.put(characteristicUuid, gattCharacteristic);
} else {
log4jfile.info("UNKNOWN: " + characteristicUuid);
}
}
}


public void setTime() {
Log.d(TAG, "Setting time...");
if (!isConnected || alertIn == null) {
Log.w(TAG, "Time not set.");
return;
}

shouldUpdateTime = true;
}

void updateTime(BluetoothDevice device) {
log4jfile.info("updateTime ..."+device.getAddress());
shouldUpdateTime = false;

final byte time = new byte[20];
final long currentTime = System.currentTimeMillis();
final long currentTimeWithTimeZoneOffset = (currentTime + TimeZone.getDefault().getOffset(currentTime)) / 1000;

final ByteBuffer buffer = ByteBuffer.allocate(8);
buffer.order(ByteOrder.LITTLE_ENDIAN).asLongBuffer().put(currentTimeWithTimeZoneOffset);
final byte utcBytes = buffer.array();

final byte length = 0x04;

time[0] = WRITE_TIME;
time[1] = length;
time[2] = utcBytes[0];
time[3] = utcBytes[1];
time[4] = utcBytes[2];
time[5] = utcBytes[3];
Boolean result=false;
DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getAlertIn().setValue(time);
DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getAlertIn().setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
log4jfile.info(DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getBluetoothGatt().getDevice().getAddress());
while (!result){
result=DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getBluetoothGatt().writeCharacteristic(DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getAlertIn());
log4jfile.info("write return "+result+" alertIn :"+DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getAlertIn().getStringValue(0));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}









share|improve this question

























  • After you call gatt.writeCharacteristic() are you waiting for the onCharacteristicWrite() callback to be called before you call gatt.writeCharacteristic() again?

    – Greg Moens
    Jan 3 at 21:46











  • Yes, i do, even i added i loop that if the writecharacteristics () return false wait for 1s and recall it but in vain

    – lotfi Raghib
    Jan 3 at 22:59











  • It's as if the BluetoothGatt object is in a bad state, not really connected perhaps?

    – Greg Moens
    Jan 3 at 23:57











  • i don't think so, because when i call gatt.discoverServices(), i get all my bluetooth services, also before calling the discoverServices(), i check if the device is connected. – lotfi Raghib 13 mins ago

    – lotfi Raghib
    Jan 4 at 8:00











  • Maybe you could post more of your code? Especially the BluetoothGattCallback and where you read/write your characteristics.

    – Emil
    Jan 4 at 11:47


















0















i'am building a Android application that read data from some BLE devices, the process of the application start by :




  • Discover the devices.

  • check if they are paired, if not paird them.

  • connect to the first devices then read data of this devices, then stop and
    stay connected (if the first time that i want to connect to the device, i
    call connectGatt(), else if already connected call
    gatt.discoverServices() )

  • switch to second devices (connect + read + write + stop reading)


  • when i acheive the last device, i stop the process for a while, and i reapet
    the process from the begining



    All the process work fine the first time for all devices, but when the
    process go back to the first device and i call gatt.discoverServices() ,
    instead of connectGatt(), i get all the Services and also the Characteristics
    but my gatt.writeCharacteristic() fail and return false.



    can anyone help to know why it fails and how o fix this issue.



    this is how my code look like



     if (DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getBluetoothGatt() == null) {
    // if(true){
    log4jfile.info(" BluetoothGATT = null : call connectGatt");
    BluetoothService.reading_device = device.getAddress();

    bluetoothGatt = device.connectGatt(this, false, bluetoothGattCallback)

    if (DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getBluetoothGatt() == null) {
    DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).setBluetoothGatt(bluetoothGatt);
    }
    } else {

    if (mBluetoothManager.getConnectedDevices(BluetoothProfile.GATT).contains(device)) {
    log4jfile.info(" BluetoothGATT != null : call discoverServices");

    DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getBluetoothGatt().discoverServices();
    } else {
    log4jfile.info(" BluetoothGATT != null : call connect");
    DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getBluetoothGatt().connect();
    }

    }



Note:




  • i don't call connectGatt() many time for the same device because the number
    of BluetoothGatt that we could create in android is 32.


  • i d'on't call bluetoothGatt.close() after i finish cause i want stay
    connected to my devices all the time.



EDIT



bluetoothGatt = device.connectGatt(this, false, new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {

log4jfile.info("onConnectionStateChange, status : " + status + " parseConnection : " + GattStatusParse.parseConnection(status) + " or " + GattStatusParse.parseConnection(status));
DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).setSuccess_Counter(DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getSuccess_Counter() + 1);
isConnected = BluetoothProfile.STATE_CONNECTED == newState;
if (status == BluetoothGatt.GATT_SUCCESS) {
for (BluetoothDeviceWrapper blw : DeviceListAdapter.devices) {
if (blw.getDevice().getAddress().equals(device.getAddress())) {
blw.setConnectionFailed(false);
}
}
if (isConnected) {
log4jfile.info(" GATT connected " + device.getAddress() + " state of the opération : " + status + " connexion state : " + newState);
if (!connectedBluethoothDevice.contains(device)) {
connectedBluethoothDevice.add(device);
}
Log.i(TAG, "GATT connected." + connectedBluethoothDevice.toString());

gatt.discoverServices();
//LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));
BluetoothService.reading_device = device.getAddress();
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));
} else {
log4jfile.info(" GATT disconnected " + device.getAddress() + " state of the opération : " + status + " connexion state : " + newState);
if (connectedBluethoothDevice.contains(device)) {
connectedBluethoothDevice.remove(device);
}
Log.i(TAG, "GATT disconnected." + connectedBluethoothDevice.toString());
//NotificationService_.intent(BluetoothService.this).stop();
notificationManager.notify(442, getNotification(device));
BluetoothService.reading_device = "";
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));

}
} else {

if (connectedBluethoothDevice.contains(device)) {
// mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
int mConnectionState = mBluetoothManager.getConnectionState(device, BluetoothProfile.GATT);
if (mConnectionState == BluetoothProfile.STATE_DISCONNECTED || mConnectionState == BluetoothProfile.STATE_DISCONNECTING) {
connectedBluethoothDevice.remove(device);
}
}

for (BluetoothDeviceWrapper blw : DeviceListAdapter.devices) {
if (blw.getDevice().getAddress().equals(device.getAddress())) {
blw.setConnectionFailed(true);
}
}
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));

BluetoothService.FAILED_CONNECTION = BluetoothService.FAILED_CONNECTION + 1;
DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).setFail_Counter(DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getFail_Counter() + 1);
log4jfile.info("connection _ Failed : " + BluetoothService.FAILED_CONNECTION);
if (1 <= BluetoothService.FAILED_CONNECTION && BluetoothService.FAILED_CONNECTION < Integer.parseInt(NombreDeTentativeDeConnexion)) {
if (MainActivity.current == 0) {
MainActivity.current = DeviceListAdapter.devicesFounder.size() - 1;
} else {
MainActivity.current = MainActivity.current - 1;
}

if (!MainActivity.stoppedServices) {
Log.e(TAG, "sendBroadcast DEVICE_READ_DONE 2");
final Intent myIntent = new Intent(DEVICE_READ_DONE);
sendBroadcast(myIntent);
stopSelf();
}

} else {
BluetoothService.FAILED_CONNECTION = 0;
if (!MainActivity.stoppedServices) {
Log.e(TAG, "sendBroadcast DEVICE_READ_DONE 3");
final Intent myIntent = new Intent(DEVICE_READ_DONE);
sendBroadcast(myIntent);
stopSelf();
}
}
}

}

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

startForeground(442, getNotification(device));
log4jfile.info("Services discovered. status : " + status + " , parse status : " + GattStatusParse.parse(status));
BluetoothService.reading_device = gatt.getDevice().getAddress();
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));
if (status == BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION) {
log4jfile.info("GATT_INSUFFICIENT_AUTHENTICATION");
handleAuthenticationError(gatt);
return;
}

discoverCharacteristics(gatt);
}

@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
System.gc();
log4jfile.info("Characteristic written, status: " + status + " , parse status : " + GattStatusParse.parse(status));
//BluetoothService.reading_device=gatt.getDevice().getAddress();
if (status == BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION) {
log4jfile.error("GATT_INSUFFICIENT_AUTHENTICATION");
handleAuthenticationError(gatt);
return;
}

final byte command = characteristic.getValue()[0];
switch (command) {
case WRITE_TIME:
log4jfile.info("Time written.");
final BluetoothGattCharacteristic batteryCharacteristic = readableCharacteristics.get(Characteristic.BATTERY.getUuid());
gatt.setCharacteristicNotification(batteryCharacteristic, true);
for (BluetoothGattDescriptor descriptor : batteryCharacteristic.getDescriptors()) {
if (descriptor.getUuid().toString().startsWith("00002904")) {
descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
gatt.writeDescriptor(descriptor);
}
}
break;
case WRITE_NOTIFICATION:
log4jfile.info("Notification sent.");
if (notificationsQueue.isEmpty()) {
log4jfile.info("Reading characteristics...");
//BluetoothService.reading_device=gatt.getDevice().getAddress();
readNextCharacteristics(gatt);
} else {
log4jfile.info("writing next notification...");
alertIn.setValue(notificationsQueue.poll());
gatt.writeCharacteristic(alertIn);
}
break;
default:
log4jfile.info("No such ALERT IN command: " + command);
break;
}
}

@Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
log4jfile.info("onDescriptorWrite write, status: " + status + " , parse status : " + GattStatusParse.parse(status));
readCharacteristic(gatt, Characteristic.MANUFACTURER);
}

@Override
public void onCharacteristicRead(BluetoothGatt gatt, final BluetoothGattCharacteristic gattCharacteristic, int status) {
log4jfile.info("onCharacteristicRead, device : " + gatt.getDevice().getAddress() + " status : " + status + " , parse status : " + GattStatusParse.parse(status));
System.gc();
if (!MainActivity.stoppedServices && gatt.getDevice().getAddress().equals(BluetoothService.reading_device)) {
if (status == BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION) {
handleAuthenticationError(gatt);
return;
}

final String characteristicUuid = gattCharacteristic.getUuid().toString();
final Characteristic characteristic = Characteristic.byUuid(characteristicUuid);
switch (characteristic) {
case MANUFACTURER:
manufacturerInfo.manufacturer = gattCharacteristic.getStringValue(0);
readCharacteristic(gatt, Characteristic.FW_REVISION);
break;
case FW_REVISION:
manufacturerInfo.firmwareRevision = gattCharacteristic.getStringValue(0);
readCharacteristic(gatt, Characteristic.MODE);
break;
default:
//BluetoothService.reading_device=gatt.getDevice().getAddress();
//LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));
log4jfile.info("Characteristic read: " + characteristic.name() + " device " + gatt.getDevice().getAddress() + " basculeTimer :" + BluetoothService.basculeTimer);
if (1 > BluetoothService.FAILED_CONNECTION || BluetoothService.FAILED_CONNECTION >= 3) {
BluetoothService.FAILED_CONNECTION = 0;
}
BluetoothService.basculeTimer++;
if (BluetoothService.basculeTimer == 0 || BluetoothService.basculeTimer == 10) {
// BluetoothService.reading_device=gatt.getDevice().getAddress();
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));
}
if (!gatt.getDevice().getAddress().equals(BluetoothService.reading_device)) {
// BluetoothService.reading_device = bluetoothGatt.getDevice().getAddress();
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));
}
//BluetoothService.reading_device=gatt.getDevice().getAddress();

if (characteristic == Characteristic.MODE) {
final Mode newMode = Mode.bySymbol(gattCharacteristic.getValue()[0]);
log4jfile.info("mode change : " + newMode.name());
if (mode != newMode) {
onModeChanged(newMode);
}
} else {
onBluetoothDataReceived(characteristic, gattCharacteristic.getValue());
}

// if (shouldUpdateTime) {
// updateTime(gatt.getDevice());
// }

if (notificationsQueue.isEmpty()) {
log4jfile.info(" notificationsQueue isEmpty ==> readNextCharacteristics");
readNextCharacteristics(gatt);
} else {
log4jfile.info(" notificationsQueue NotisEmpty ==> writeCharacteristic");
alertIn.setValue(notificationsQueue.poll());
gatt.writeCharacteristic(alertIn);
}

break;
}
}
}

@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic gattCharacteristic) {
System.gc();
final String characteristicUuid = gattCharacteristic.getUuid().toString();
final Characteristic characteristic = Characteristic.byUuid(characteristicUuid);
log4jfile.info("Characteristic changed: " + characteristic.name());

if (characteristic == Characteristic.BATTERY) {
onBluetoothDataReceived(Characteristic.BATTERY, gattCharacteristic.getValue());
}
}
});


private void discoverCharacteristics(final BluetoothGatt gatt) {
log4jfile.info("discoverCharacteristics. services length : " + gatt.getServices().size());
//BluetoothService.reading_device = gatt.getDevice().getAddress();
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));
if (gatt.getServices().size() == 0) {
log4jfile.info("No services found.");
//LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.DEVICE_READ_DONE));
}

for (BluetoothGattService gattService : gatt.getServices()) {
if(gatt.getDevice().getAddress().equals(BluetoothService.reading_device)){
storeCharacteristicsFromService(gattService,gatt.getDevice());

}
}
}

private void storeCharacteristicsFromService(BluetoothGattService gattService,BluetoothDevice device) {
log4jfile.info("storeCharacteristicsFromService , length : " + gattService.getCharacteristics().size());
for (BluetoothGattCharacteristic gattCharacteristic : gattService.getCharacteristics()) {
final String characteristicUuid = gattCharacteristic.getUuid().toString();
final Characteristic characteristic = Characteristic.byUuid(characteristicUuid);

if (characteristic == Characteristic.ALERT_IN) {
log4jfile.info( "ALERT_IN DISCOVERED");
DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).setAlertIn(null);
DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).setAlertIn(gattCharacteristic);

alertIn = gattCharacteristic;
setTime();
if(device.getAddress().equals(BluetoothService.reading_device)) {
updateTime(device);
}
NotificationService_.intent(BluetoothService.this).start();
} else if (characteristic != null) {
log4jfile.info("characteristic " + characteristic);
log4jfile.info(characteristic.getType() + ": " + characteristic.name());
readableCharacteristics.put(characteristicUuid, gattCharacteristic);
} else {
log4jfile.info("UNKNOWN: " + characteristicUuid);
}
}
}


public void setTime() {
Log.d(TAG, "Setting time...");
if (!isConnected || alertIn == null) {
Log.w(TAG, "Time not set.");
return;
}

shouldUpdateTime = true;
}

void updateTime(BluetoothDevice device) {
log4jfile.info("updateTime ..."+device.getAddress());
shouldUpdateTime = false;

final byte time = new byte[20];
final long currentTime = System.currentTimeMillis();
final long currentTimeWithTimeZoneOffset = (currentTime + TimeZone.getDefault().getOffset(currentTime)) / 1000;

final ByteBuffer buffer = ByteBuffer.allocate(8);
buffer.order(ByteOrder.LITTLE_ENDIAN).asLongBuffer().put(currentTimeWithTimeZoneOffset);
final byte utcBytes = buffer.array();

final byte length = 0x04;

time[0] = WRITE_TIME;
time[1] = length;
time[2] = utcBytes[0];
time[3] = utcBytes[1];
time[4] = utcBytes[2];
time[5] = utcBytes[3];
Boolean result=false;
DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getAlertIn().setValue(time);
DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getAlertIn().setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
log4jfile.info(DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getBluetoothGatt().getDevice().getAddress());
while (!result){
result=DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getBluetoothGatt().writeCharacteristic(DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getAlertIn());
log4jfile.info("write return "+result+" alertIn :"+DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getAlertIn().getStringValue(0));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}









share|improve this question

























  • After you call gatt.writeCharacteristic() are you waiting for the onCharacteristicWrite() callback to be called before you call gatt.writeCharacteristic() again?

    – Greg Moens
    Jan 3 at 21:46











  • Yes, i do, even i added i loop that if the writecharacteristics () return false wait for 1s and recall it but in vain

    – lotfi Raghib
    Jan 3 at 22:59











  • It's as if the BluetoothGatt object is in a bad state, not really connected perhaps?

    – Greg Moens
    Jan 3 at 23:57











  • i don't think so, because when i call gatt.discoverServices(), i get all my bluetooth services, also before calling the discoverServices(), i check if the device is connected. – lotfi Raghib 13 mins ago

    – lotfi Raghib
    Jan 4 at 8:00











  • Maybe you could post more of your code? Especially the BluetoothGattCallback and where you read/write your characteristics.

    – Emil
    Jan 4 at 11:47














0












0








0








i'am building a Android application that read data from some BLE devices, the process of the application start by :




  • Discover the devices.

  • check if they are paired, if not paird them.

  • connect to the first devices then read data of this devices, then stop and
    stay connected (if the first time that i want to connect to the device, i
    call connectGatt(), else if already connected call
    gatt.discoverServices() )

  • switch to second devices (connect + read + write + stop reading)


  • when i acheive the last device, i stop the process for a while, and i reapet
    the process from the begining



    All the process work fine the first time for all devices, but when the
    process go back to the first device and i call gatt.discoverServices() ,
    instead of connectGatt(), i get all the Services and also the Characteristics
    but my gatt.writeCharacteristic() fail and return false.



    can anyone help to know why it fails and how o fix this issue.



    this is how my code look like



     if (DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getBluetoothGatt() == null) {
    // if(true){
    log4jfile.info(" BluetoothGATT = null : call connectGatt");
    BluetoothService.reading_device = device.getAddress();

    bluetoothGatt = device.connectGatt(this, false, bluetoothGattCallback)

    if (DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getBluetoothGatt() == null) {
    DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).setBluetoothGatt(bluetoothGatt);
    }
    } else {

    if (mBluetoothManager.getConnectedDevices(BluetoothProfile.GATT).contains(device)) {
    log4jfile.info(" BluetoothGATT != null : call discoverServices");

    DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getBluetoothGatt().discoverServices();
    } else {
    log4jfile.info(" BluetoothGATT != null : call connect");
    DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getBluetoothGatt().connect();
    }

    }



Note:




  • i don't call connectGatt() many time for the same device because the number
    of BluetoothGatt that we could create in android is 32.


  • i d'on't call bluetoothGatt.close() after i finish cause i want stay
    connected to my devices all the time.



EDIT



bluetoothGatt = device.connectGatt(this, false, new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {

log4jfile.info("onConnectionStateChange, status : " + status + " parseConnection : " + GattStatusParse.parseConnection(status) + " or " + GattStatusParse.parseConnection(status));
DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).setSuccess_Counter(DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getSuccess_Counter() + 1);
isConnected = BluetoothProfile.STATE_CONNECTED == newState;
if (status == BluetoothGatt.GATT_SUCCESS) {
for (BluetoothDeviceWrapper blw : DeviceListAdapter.devices) {
if (blw.getDevice().getAddress().equals(device.getAddress())) {
blw.setConnectionFailed(false);
}
}
if (isConnected) {
log4jfile.info(" GATT connected " + device.getAddress() + " state of the opération : " + status + " connexion state : " + newState);
if (!connectedBluethoothDevice.contains(device)) {
connectedBluethoothDevice.add(device);
}
Log.i(TAG, "GATT connected." + connectedBluethoothDevice.toString());

gatt.discoverServices();
//LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));
BluetoothService.reading_device = device.getAddress();
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));
} else {
log4jfile.info(" GATT disconnected " + device.getAddress() + " state of the opération : " + status + " connexion state : " + newState);
if (connectedBluethoothDevice.contains(device)) {
connectedBluethoothDevice.remove(device);
}
Log.i(TAG, "GATT disconnected." + connectedBluethoothDevice.toString());
//NotificationService_.intent(BluetoothService.this).stop();
notificationManager.notify(442, getNotification(device));
BluetoothService.reading_device = "";
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));

}
} else {

if (connectedBluethoothDevice.contains(device)) {
// mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
int mConnectionState = mBluetoothManager.getConnectionState(device, BluetoothProfile.GATT);
if (mConnectionState == BluetoothProfile.STATE_DISCONNECTED || mConnectionState == BluetoothProfile.STATE_DISCONNECTING) {
connectedBluethoothDevice.remove(device);
}
}

for (BluetoothDeviceWrapper blw : DeviceListAdapter.devices) {
if (blw.getDevice().getAddress().equals(device.getAddress())) {
blw.setConnectionFailed(true);
}
}
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));

BluetoothService.FAILED_CONNECTION = BluetoothService.FAILED_CONNECTION + 1;
DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).setFail_Counter(DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getFail_Counter() + 1);
log4jfile.info("connection _ Failed : " + BluetoothService.FAILED_CONNECTION);
if (1 <= BluetoothService.FAILED_CONNECTION && BluetoothService.FAILED_CONNECTION < Integer.parseInt(NombreDeTentativeDeConnexion)) {
if (MainActivity.current == 0) {
MainActivity.current = DeviceListAdapter.devicesFounder.size() - 1;
} else {
MainActivity.current = MainActivity.current - 1;
}

if (!MainActivity.stoppedServices) {
Log.e(TAG, "sendBroadcast DEVICE_READ_DONE 2");
final Intent myIntent = new Intent(DEVICE_READ_DONE);
sendBroadcast(myIntent);
stopSelf();
}

} else {
BluetoothService.FAILED_CONNECTION = 0;
if (!MainActivity.stoppedServices) {
Log.e(TAG, "sendBroadcast DEVICE_READ_DONE 3");
final Intent myIntent = new Intent(DEVICE_READ_DONE);
sendBroadcast(myIntent);
stopSelf();
}
}
}

}

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

startForeground(442, getNotification(device));
log4jfile.info("Services discovered. status : " + status + " , parse status : " + GattStatusParse.parse(status));
BluetoothService.reading_device = gatt.getDevice().getAddress();
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));
if (status == BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION) {
log4jfile.info("GATT_INSUFFICIENT_AUTHENTICATION");
handleAuthenticationError(gatt);
return;
}

discoverCharacteristics(gatt);
}

@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
System.gc();
log4jfile.info("Characteristic written, status: " + status + " , parse status : " + GattStatusParse.parse(status));
//BluetoothService.reading_device=gatt.getDevice().getAddress();
if (status == BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION) {
log4jfile.error("GATT_INSUFFICIENT_AUTHENTICATION");
handleAuthenticationError(gatt);
return;
}

final byte command = characteristic.getValue()[0];
switch (command) {
case WRITE_TIME:
log4jfile.info("Time written.");
final BluetoothGattCharacteristic batteryCharacteristic = readableCharacteristics.get(Characteristic.BATTERY.getUuid());
gatt.setCharacteristicNotification(batteryCharacteristic, true);
for (BluetoothGattDescriptor descriptor : batteryCharacteristic.getDescriptors()) {
if (descriptor.getUuid().toString().startsWith("00002904")) {
descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
gatt.writeDescriptor(descriptor);
}
}
break;
case WRITE_NOTIFICATION:
log4jfile.info("Notification sent.");
if (notificationsQueue.isEmpty()) {
log4jfile.info("Reading characteristics...");
//BluetoothService.reading_device=gatt.getDevice().getAddress();
readNextCharacteristics(gatt);
} else {
log4jfile.info("writing next notification...");
alertIn.setValue(notificationsQueue.poll());
gatt.writeCharacteristic(alertIn);
}
break;
default:
log4jfile.info("No such ALERT IN command: " + command);
break;
}
}

@Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
log4jfile.info("onDescriptorWrite write, status: " + status + " , parse status : " + GattStatusParse.parse(status));
readCharacteristic(gatt, Characteristic.MANUFACTURER);
}

@Override
public void onCharacteristicRead(BluetoothGatt gatt, final BluetoothGattCharacteristic gattCharacteristic, int status) {
log4jfile.info("onCharacteristicRead, device : " + gatt.getDevice().getAddress() + " status : " + status + " , parse status : " + GattStatusParse.parse(status));
System.gc();
if (!MainActivity.stoppedServices && gatt.getDevice().getAddress().equals(BluetoothService.reading_device)) {
if (status == BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION) {
handleAuthenticationError(gatt);
return;
}

final String characteristicUuid = gattCharacteristic.getUuid().toString();
final Characteristic characteristic = Characteristic.byUuid(characteristicUuid);
switch (characteristic) {
case MANUFACTURER:
manufacturerInfo.manufacturer = gattCharacteristic.getStringValue(0);
readCharacteristic(gatt, Characteristic.FW_REVISION);
break;
case FW_REVISION:
manufacturerInfo.firmwareRevision = gattCharacteristic.getStringValue(0);
readCharacteristic(gatt, Characteristic.MODE);
break;
default:
//BluetoothService.reading_device=gatt.getDevice().getAddress();
//LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));
log4jfile.info("Characteristic read: " + characteristic.name() + " device " + gatt.getDevice().getAddress() + " basculeTimer :" + BluetoothService.basculeTimer);
if (1 > BluetoothService.FAILED_CONNECTION || BluetoothService.FAILED_CONNECTION >= 3) {
BluetoothService.FAILED_CONNECTION = 0;
}
BluetoothService.basculeTimer++;
if (BluetoothService.basculeTimer == 0 || BluetoothService.basculeTimer == 10) {
// BluetoothService.reading_device=gatt.getDevice().getAddress();
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));
}
if (!gatt.getDevice().getAddress().equals(BluetoothService.reading_device)) {
// BluetoothService.reading_device = bluetoothGatt.getDevice().getAddress();
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));
}
//BluetoothService.reading_device=gatt.getDevice().getAddress();

if (characteristic == Characteristic.MODE) {
final Mode newMode = Mode.bySymbol(gattCharacteristic.getValue()[0]);
log4jfile.info("mode change : " + newMode.name());
if (mode != newMode) {
onModeChanged(newMode);
}
} else {
onBluetoothDataReceived(characteristic, gattCharacteristic.getValue());
}

// if (shouldUpdateTime) {
// updateTime(gatt.getDevice());
// }

if (notificationsQueue.isEmpty()) {
log4jfile.info(" notificationsQueue isEmpty ==> readNextCharacteristics");
readNextCharacteristics(gatt);
} else {
log4jfile.info(" notificationsQueue NotisEmpty ==> writeCharacteristic");
alertIn.setValue(notificationsQueue.poll());
gatt.writeCharacteristic(alertIn);
}

break;
}
}
}

@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic gattCharacteristic) {
System.gc();
final String characteristicUuid = gattCharacteristic.getUuid().toString();
final Characteristic characteristic = Characteristic.byUuid(characteristicUuid);
log4jfile.info("Characteristic changed: " + characteristic.name());

if (characteristic == Characteristic.BATTERY) {
onBluetoothDataReceived(Characteristic.BATTERY, gattCharacteristic.getValue());
}
}
});


private void discoverCharacteristics(final BluetoothGatt gatt) {
log4jfile.info("discoverCharacteristics. services length : " + gatt.getServices().size());
//BluetoothService.reading_device = gatt.getDevice().getAddress();
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));
if (gatt.getServices().size() == 0) {
log4jfile.info("No services found.");
//LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.DEVICE_READ_DONE));
}

for (BluetoothGattService gattService : gatt.getServices()) {
if(gatt.getDevice().getAddress().equals(BluetoothService.reading_device)){
storeCharacteristicsFromService(gattService,gatt.getDevice());

}
}
}

private void storeCharacteristicsFromService(BluetoothGattService gattService,BluetoothDevice device) {
log4jfile.info("storeCharacteristicsFromService , length : " + gattService.getCharacteristics().size());
for (BluetoothGattCharacteristic gattCharacteristic : gattService.getCharacteristics()) {
final String characteristicUuid = gattCharacteristic.getUuid().toString();
final Characteristic characteristic = Characteristic.byUuid(characteristicUuid);

if (characteristic == Characteristic.ALERT_IN) {
log4jfile.info( "ALERT_IN DISCOVERED");
DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).setAlertIn(null);
DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).setAlertIn(gattCharacteristic);

alertIn = gattCharacteristic;
setTime();
if(device.getAddress().equals(BluetoothService.reading_device)) {
updateTime(device);
}
NotificationService_.intent(BluetoothService.this).start();
} else if (characteristic != null) {
log4jfile.info("characteristic " + characteristic);
log4jfile.info(characteristic.getType() + ": " + characteristic.name());
readableCharacteristics.put(characteristicUuid, gattCharacteristic);
} else {
log4jfile.info("UNKNOWN: " + characteristicUuid);
}
}
}


public void setTime() {
Log.d(TAG, "Setting time...");
if (!isConnected || alertIn == null) {
Log.w(TAG, "Time not set.");
return;
}

shouldUpdateTime = true;
}

void updateTime(BluetoothDevice device) {
log4jfile.info("updateTime ..."+device.getAddress());
shouldUpdateTime = false;

final byte time = new byte[20];
final long currentTime = System.currentTimeMillis();
final long currentTimeWithTimeZoneOffset = (currentTime + TimeZone.getDefault().getOffset(currentTime)) / 1000;

final ByteBuffer buffer = ByteBuffer.allocate(8);
buffer.order(ByteOrder.LITTLE_ENDIAN).asLongBuffer().put(currentTimeWithTimeZoneOffset);
final byte utcBytes = buffer.array();

final byte length = 0x04;

time[0] = WRITE_TIME;
time[1] = length;
time[2] = utcBytes[0];
time[3] = utcBytes[1];
time[4] = utcBytes[2];
time[5] = utcBytes[3];
Boolean result=false;
DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getAlertIn().setValue(time);
DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getAlertIn().setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
log4jfile.info(DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getBluetoothGatt().getDevice().getAddress());
while (!result){
result=DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getBluetoothGatt().writeCharacteristic(DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getAlertIn());
log4jfile.info("write return "+result+" alertIn :"+DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getAlertIn().getStringValue(0));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}









share|improve this question
















i'am building a Android application that read data from some BLE devices, the process of the application start by :




  • Discover the devices.

  • check if they are paired, if not paird them.

  • connect to the first devices then read data of this devices, then stop and
    stay connected (if the first time that i want to connect to the device, i
    call connectGatt(), else if already connected call
    gatt.discoverServices() )

  • switch to second devices (connect + read + write + stop reading)


  • when i acheive the last device, i stop the process for a while, and i reapet
    the process from the begining



    All the process work fine the first time for all devices, but when the
    process go back to the first device and i call gatt.discoverServices() ,
    instead of connectGatt(), i get all the Services and also the Characteristics
    but my gatt.writeCharacteristic() fail and return false.



    can anyone help to know why it fails and how o fix this issue.



    this is how my code look like



     if (DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getBluetoothGatt() == null) {
    // if(true){
    log4jfile.info(" BluetoothGATT = null : call connectGatt");
    BluetoothService.reading_device = device.getAddress();

    bluetoothGatt = device.connectGatt(this, false, bluetoothGattCallback)

    if (DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getBluetoothGatt() == null) {
    DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).setBluetoothGatt(bluetoothGatt);
    }
    } else {

    if (mBluetoothManager.getConnectedDevices(BluetoothProfile.GATT).contains(device)) {
    log4jfile.info(" BluetoothGATT != null : call discoverServices");

    DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getBluetoothGatt().discoverServices();
    } else {
    log4jfile.info(" BluetoothGATT != null : call connect");
    DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getBluetoothGatt().connect();
    }

    }



Note:




  • i don't call connectGatt() many time for the same device because the number
    of BluetoothGatt that we could create in android is 32.


  • i d'on't call bluetoothGatt.close() after i finish cause i want stay
    connected to my devices all the time.



EDIT



bluetoothGatt = device.connectGatt(this, false, new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {

log4jfile.info("onConnectionStateChange, status : " + status + " parseConnection : " + GattStatusParse.parseConnection(status) + " or " + GattStatusParse.parseConnection(status));
DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).setSuccess_Counter(DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getSuccess_Counter() + 1);
isConnected = BluetoothProfile.STATE_CONNECTED == newState;
if (status == BluetoothGatt.GATT_SUCCESS) {
for (BluetoothDeviceWrapper blw : DeviceListAdapter.devices) {
if (blw.getDevice().getAddress().equals(device.getAddress())) {
blw.setConnectionFailed(false);
}
}
if (isConnected) {
log4jfile.info(" GATT connected " + device.getAddress() + " state of the opération : " + status + " connexion state : " + newState);
if (!connectedBluethoothDevice.contains(device)) {
connectedBluethoothDevice.add(device);
}
Log.i(TAG, "GATT connected." + connectedBluethoothDevice.toString());

gatt.discoverServices();
//LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));
BluetoothService.reading_device = device.getAddress();
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));
} else {
log4jfile.info(" GATT disconnected " + device.getAddress() + " state of the opération : " + status + " connexion state : " + newState);
if (connectedBluethoothDevice.contains(device)) {
connectedBluethoothDevice.remove(device);
}
Log.i(TAG, "GATT disconnected." + connectedBluethoothDevice.toString());
//NotificationService_.intent(BluetoothService.this).stop();
notificationManager.notify(442, getNotification(device));
BluetoothService.reading_device = "";
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));

}
} else {

if (connectedBluethoothDevice.contains(device)) {
// mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
int mConnectionState = mBluetoothManager.getConnectionState(device, BluetoothProfile.GATT);
if (mConnectionState == BluetoothProfile.STATE_DISCONNECTED || mConnectionState == BluetoothProfile.STATE_DISCONNECTING) {
connectedBluethoothDevice.remove(device);
}
}

for (BluetoothDeviceWrapper blw : DeviceListAdapter.devices) {
if (blw.getDevice().getAddress().equals(device.getAddress())) {
blw.setConnectionFailed(true);
}
}
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));

BluetoothService.FAILED_CONNECTION = BluetoothService.FAILED_CONNECTION + 1;
DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).setFail_Counter(DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getFail_Counter() + 1);
log4jfile.info("connection _ Failed : " + BluetoothService.FAILED_CONNECTION);
if (1 <= BluetoothService.FAILED_CONNECTION && BluetoothService.FAILED_CONNECTION < Integer.parseInt(NombreDeTentativeDeConnexion)) {
if (MainActivity.current == 0) {
MainActivity.current = DeviceListAdapter.devicesFounder.size() - 1;
} else {
MainActivity.current = MainActivity.current - 1;
}

if (!MainActivity.stoppedServices) {
Log.e(TAG, "sendBroadcast DEVICE_READ_DONE 2");
final Intent myIntent = new Intent(DEVICE_READ_DONE);
sendBroadcast(myIntent);
stopSelf();
}

} else {
BluetoothService.FAILED_CONNECTION = 0;
if (!MainActivity.stoppedServices) {
Log.e(TAG, "sendBroadcast DEVICE_READ_DONE 3");
final Intent myIntent = new Intent(DEVICE_READ_DONE);
sendBroadcast(myIntent);
stopSelf();
}
}
}

}

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

startForeground(442, getNotification(device));
log4jfile.info("Services discovered. status : " + status + " , parse status : " + GattStatusParse.parse(status));
BluetoothService.reading_device = gatt.getDevice().getAddress();
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));
if (status == BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION) {
log4jfile.info("GATT_INSUFFICIENT_AUTHENTICATION");
handleAuthenticationError(gatt);
return;
}

discoverCharacteristics(gatt);
}

@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
System.gc();
log4jfile.info("Characteristic written, status: " + status + " , parse status : " + GattStatusParse.parse(status));
//BluetoothService.reading_device=gatt.getDevice().getAddress();
if (status == BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION) {
log4jfile.error("GATT_INSUFFICIENT_AUTHENTICATION");
handleAuthenticationError(gatt);
return;
}

final byte command = characteristic.getValue()[0];
switch (command) {
case WRITE_TIME:
log4jfile.info("Time written.");
final BluetoothGattCharacteristic batteryCharacteristic = readableCharacteristics.get(Characteristic.BATTERY.getUuid());
gatt.setCharacteristicNotification(batteryCharacteristic, true);
for (BluetoothGattDescriptor descriptor : batteryCharacteristic.getDescriptors()) {
if (descriptor.getUuid().toString().startsWith("00002904")) {
descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
gatt.writeDescriptor(descriptor);
}
}
break;
case WRITE_NOTIFICATION:
log4jfile.info("Notification sent.");
if (notificationsQueue.isEmpty()) {
log4jfile.info("Reading characteristics...");
//BluetoothService.reading_device=gatt.getDevice().getAddress();
readNextCharacteristics(gatt);
} else {
log4jfile.info("writing next notification...");
alertIn.setValue(notificationsQueue.poll());
gatt.writeCharacteristic(alertIn);
}
break;
default:
log4jfile.info("No such ALERT IN command: " + command);
break;
}
}

@Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
log4jfile.info("onDescriptorWrite write, status: " + status + " , parse status : " + GattStatusParse.parse(status));
readCharacteristic(gatt, Characteristic.MANUFACTURER);
}

@Override
public void onCharacteristicRead(BluetoothGatt gatt, final BluetoothGattCharacteristic gattCharacteristic, int status) {
log4jfile.info("onCharacteristicRead, device : " + gatt.getDevice().getAddress() + " status : " + status + " , parse status : " + GattStatusParse.parse(status));
System.gc();
if (!MainActivity.stoppedServices && gatt.getDevice().getAddress().equals(BluetoothService.reading_device)) {
if (status == BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION) {
handleAuthenticationError(gatt);
return;
}

final String characteristicUuid = gattCharacteristic.getUuid().toString();
final Characteristic characteristic = Characteristic.byUuid(characteristicUuid);
switch (characteristic) {
case MANUFACTURER:
manufacturerInfo.manufacturer = gattCharacteristic.getStringValue(0);
readCharacteristic(gatt, Characteristic.FW_REVISION);
break;
case FW_REVISION:
manufacturerInfo.firmwareRevision = gattCharacteristic.getStringValue(0);
readCharacteristic(gatt, Characteristic.MODE);
break;
default:
//BluetoothService.reading_device=gatt.getDevice().getAddress();
//LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));
log4jfile.info("Characteristic read: " + characteristic.name() + " device " + gatt.getDevice().getAddress() + " basculeTimer :" + BluetoothService.basculeTimer);
if (1 > BluetoothService.FAILED_CONNECTION || BluetoothService.FAILED_CONNECTION >= 3) {
BluetoothService.FAILED_CONNECTION = 0;
}
BluetoothService.basculeTimer++;
if (BluetoothService.basculeTimer == 0 || BluetoothService.basculeTimer == 10) {
// BluetoothService.reading_device=gatt.getDevice().getAddress();
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));
}
if (!gatt.getDevice().getAddress().equals(BluetoothService.reading_device)) {
// BluetoothService.reading_device = bluetoothGatt.getDevice().getAddress();
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));
}
//BluetoothService.reading_device=gatt.getDevice().getAddress();

if (characteristic == Characteristic.MODE) {
final Mode newMode = Mode.bySymbol(gattCharacteristic.getValue()[0]);
log4jfile.info("mode change : " + newMode.name());
if (mode != newMode) {
onModeChanged(newMode);
}
} else {
onBluetoothDataReceived(characteristic, gattCharacteristic.getValue());
}

// if (shouldUpdateTime) {
// updateTime(gatt.getDevice());
// }

if (notificationsQueue.isEmpty()) {
log4jfile.info(" notificationsQueue isEmpty ==> readNextCharacteristics");
readNextCharacteristics(gatt);
} else {
log4jfile.info(" notificationsQueue NotisEmpty ==> writeCharacteristic");
alertIn.setValue(notificationsQueue.poll());
gatt.writeCharacteristic(alertIn);
}

break;
}
}
}

@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic gattCharacteristic) {
System.gc();
final String characteristicUuid = gattCharacteristic.getUuid().toString();
final Characteristic characteristic = Characteristic.byUuid(characteristicUuid);
log4jfile.info("Characteristic changed: " + characteristic.name());

if (characteristic == Characteristic.BATTERY) {
onBluetoothDataReceived(Characteristic.BATTERY, gattCharacteristic.getValue());
}
}
});


private void discoverCharacteristics(final BluetoothGatt gatt) {
log4jfile.info("discoverCharacteristics. services length : " + gatt.getServices().size());
//BluetoothService.reading_device = gatt.getDevice().getAddress();
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.REFRESH_ADAPTER));
if (gatt.getServices().size() == 0) {
log4jfile.info("No services found.");
//LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(BluetoothService.DEVICE_READ_DONE));
}

for (BluetoothGattService gattService : gatt.getServices()) {
if(gatt.getDevice().getAddress().equals(BluetoothService.reading_device)){
storeCharacteristicsFromService(gattService,gatt.getDevice());

}
}
}

private void storeCharacteristicsFromService(BluetoothGattService gattService,BluetoothDevice device) {
log4jfile.info("storeCharacteristicsFromService , length : " + gattService.getCharacteristics().size());
for (BluetoothGattCharacteristic gattCharacteristic : gattService.getCharacteristics()) {
final String characteristicUuid = gattCharacteristic.getUuid().toString();
final Characteristic characteristic = Characteristic.byUuid(characteristicUuid);

if (characteristic == Characteristic.ALERT_IN) {
log4jfile.info( "ALERT_IN DISCOVERED");
DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).setAlertIn(null);
DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).setAlertIn(gattCharacteristic);

alertIn = gattCharacteristic;
setTime();
if(device.getAddress().equals(BluetoothService.reading_device)) {
updateTime(device);
}
NotificationService_.intent(BluetoothService.this).start();
} else if (characteristic != null) {
log4jfile.info("characteristic " + characteristic);
log4jfile.info(characteristic.getType() + ": " + characteristic.name());
readableCharacteristics.put(characteristicUuid, gattCharacteristic);
} else {
log4jfile.info("UNKNOWN: " + characteristicUuid);
}
}
}


public void setTime() {
Log.d(TAG, "Setting time...");
if (!isConnected || alertIn == null) {
Log.w(TAG, "Time not set.");
return;
}

shouldUpdateTime = true;
}

void updateTime(BluetoothDevice device) {
log4jfile.info("updateTime ..."+device.getAddress());
shouldUpdateTime = false;

final byte time = new byte[20];
final long currentTime = System.currentTimeMillis();
final long currentTimeWithTimeZoneOffset = (currentTime + TimeZone.getDefault().getOffset(currentTime)) / 1000;

final ByteBuffer buffer = ByteBuffer.allocate(8);
buffer.order(ByteOrder.LITTLE_ENDIAN).asLongBuffer().put(currentTimeWithTimeZoneOffset);
final byte utcBytes = buffer.array();

final byte length = 0x04;

time[0] = WRITE_TIME;
time[1] = length;
time[2] = utcBytes[0];
time[3] = utcBytes[1];
time[4] = utcBytes[2];
time[5] = utcBytes[3];
Boolean result=false;
DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getAlertIn().setValue(time);
DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getAlertIn().setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
log4jfile.info(DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getBluetoothGatt().getDevice().getAddress());
while (!result){
result=DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getBluetoothGatt().writeCharacteristic(DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getAlertIn());
log4jfile.info("write return "+result+" alertIn :"+DeviceListAdapter.devicesState.getDeviceState(device.getAddress()).getAlertIn().getStringValue(0));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}






android bluetooth-lowenergy android-bluetooth gatt bluetooth-gatt






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jan 4 at 14:33







lotfi Raghib

















asked Jan 3 at 20:26









lotfi Raghiblotfi Raghib

3618




3618













  • After you call gatt.writeCharacteristic() are you waiting for the onCharacteristicWrite() callback to be called before you call gatt.writeCharacteristic() again?

    – Greg Moens
    Jan 3 at 21:46











  • Yes, i do, even i added i loop that if the writecharacteristics () return false wait for 1s and recall it but in vain

    – lotfi Raghib
    Jan 3 at 22:59











  • It's as if the BluetoothGatt object is in a bad state, not really connected perhaps?

    – Greg Moens
    Jan 3 at 23:57











  • i don't think so, because when i call gatt.discoverServices(), i get all my bluetooth services, also before calling the discoverServices(), i check if the device is connected. – lotfi Raghib 13 mins ago

    – lotfi Raghib
    Jan 4 at 8:00











  • Maybe you could post more of your code? Especially the BluetoothGattCallback and where you read/write your characteristics.

    – Emil
    Jan 4 at 11:47



















  • After you call gatt.writeCharacteristic() are you waiting for the onCharacteristicWrite() callback to be called before you call gatt.writeCharacteristic() again?

    – Greg Moens
    Jan 3 at 21:46











  • Yes, i do, even i added i loop that if the writecharacteristics () return false wait for 1s and recall it but in vain

    – lotfi Raghib
    Jan 3 at 22:59











  • It's as if the BluetoothGatt object is in a bad state, not really connected perhaps?

    – Greg Moens
    Jan 3 at 23:57











  • i don't think so, because when i call gatt.discoverServices(), i get all my bluetooth services, also before calling the discoverServices(), i check if the device is connected. – lotfi Raghib 13 mins ago

    – lotfi Raghib
    Jan 4 at 8:00











  • Maybe you could post more of your code? Especially the BluetoothGattCallback and where you read/write your characteristics.

    – Emil
    Jan 4 at 11:47

















After you call gatt.writeCharacteristic() are you waiting for the onCharacteristicWrite() callback to be called before you call gatt.writeCharacteristic() again?

– Greg Moens
Jan 3 at 21:46





After you call gatt.writeCharacteristic() are you waiting for the onCharacteristicWrite() callback to be called before you call gatt.writeCharacteristic() again?

– Greg Moens
Jan 3 at 21:46













Yes, i do, even i added i loop that if the writecharacteristics () return false wait for 1s and recall it but in vain

– lotfi Raghib
Jan 3 at 22:59





Yes, i do, even i added i loop that if the writecharacteristics () return false wait for 1s and recall it but in vain

– lotfi Raghib
Jan 3 at 22:59













It's as if the BluetoothGatt object is in a bad state, not really connected perhaps?

– Greg Moens
Jan 3 at 23:57





It's as if the BluetoothGatt object is in a bad state, not really connected perhaps?

– Greg Moens
Jan 3 at 23:57













i don't think so, because when i call gatt.discoverServices(), i get all my bluetooth services, also before calling the discoverServices(), i check if the device is connected. – lotfi Raghib 13 mins ago

– lotfi Raghib
Jan 4 at 8:00





i don't think so, because when i call gatt.discoverServices(), i get all my bluetooth services, also before calling the discoverServices(), i check if the device is connected. – lotfi Raghib 13 mins ago

– lotfi Raghib
Jan 4 at 8:00













Maybe you could post more of your code? Especially the BluetoothGattCallback and where you read/write your characteristics.

– Emil
Jan 4 at 11:47





Maybe you could post more of your code? Especially the BluetoothGattCallback and where you read/write your characteristics.

– Emil
Jan 4 at 11:47












0






active

oldest

votes












Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54029319%2fbluetoothgatt-writecharacteristic-success-for-the-first-time-but-return-false%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























0






active

oldest

votes








0






active

oldest

votes









active

oldest

votes






active

oldest

votes
















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54029319%2fbluetoothgatt-writecharacteristic-success-for-the-first-time-but-return-false%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Monofisismo

Angular Downloading a file using contenturl with Basic Authentication

Olmecas