I am new to android studio and creating apps and this is part of a project I am doing.
I am able to connect to the Bluetooth device and be able to get it into onServicesDiscovered function with the status GATT_SUCCESS.
I am not sure where to go from here since I am not receiving data from the device. Do I need a broadcast update or broadcast receiver or is the code below fine but needs to be fixed?
If anyone can help that would be great!
@Override
//New services discovered
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
Log.i("onServicesDiscovered", "Status: " + status);
if(status == GATT_SUCCESS) {
List<BluetoothGattService> services = gatt.getServices();
for(BluetoothGattService service : services){
if(!service.getUuid().equals("49535343-FE7D-4AE5-8FA9-9FAFD205E455"))
continue;
List<BluetoothGattCharacteristic> gattCharacteristics = service.getCharacteristics();
// Loops through available Characteristics
for(BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics){
if(!gattCharacteristic.getUuid().equals("49535343-1E4D-4BD9-BA61-23C647249616"))
continue;
final int charaProp = gattCharacteristic.getProperties();
if((charaProp | BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0){
setCharacteristicNotification(gattCharacteristic, true);
Log.w(TAG, "Working");
}else{
Log.w(TAG, "Characteristic does not support notify");
}
}
}
}else{
Log.w(TAG, "onServicesDiscovered receive: " + status);
}
//List<BluetoothGattService> services = gatt.getServices();
//Log.i("onServicesDiscovered", services.toString());
//gatt.readCharacteristic(services.get(1).getCharacteristics().get(0));
}
@Override
//Result of a characteristic read operation
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
Log.i("onCharacteristicRead", characteristic.toString());
if(status != GATT_SUCCESS){
Log.e(TAG, String.format(Locale.ENGLISH, "ERROR: Read failed for characteristic: %s, status %d", characteristic.getUuid(), status));
completedCommand();
return;
}
//gatt.disconnect();
}
@Override
public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
if (status == GATT_SUCCESS) {
if (descriptor.getCharacteristic().getUuid().equals(UUID_TARGET_CHARACTERISTIC)) {
Log.i(TAG, "Successfully subscribed");
}
byte[] data = {1, 1};
BluetoothGattService Service = mGatt.getService(UUID_TARGET_SERVICE);
BluetoothGattCharacteristic charac = Service.getCharacteristic(UUID_TARGET_CHARACTERISTIC);
charac.setValue(data);
mGatt.readCharacteristic(charac);
} else {
Log.e(TAG, "Error subscribing");
}
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicChanged(gatt, characteristic);
byte[] value = characteristic.getValue();
Log.i("BLE", "receive value ----------------------------");
for (int i = 0; i < value.length; i++) {
Log.w("BLE", "character_value = " + value[i]);
}
//processData(characteristic.getValue());
}
};
public boolean readCharacteristic(final BluetoothGattCharacteristic characteristic) {
if(mGatt == null) {
Log.e(TAG, "ERROR: Gatt is 'null', ignoring read request");
return false;
}
// Check if characteristic is valid
if(characteristic == null) {
Log.e(TAG, "ERROR: Characteristic is 'null', ignoring read request");
return false;
}
// Check if this characteristic actually has READ property
if((characteristic.getProperties() & PROPERTY_READ) == 0 ) {
Log.e(TAG, "ERROR: Characteristic cannot be read");
return false;
}
// Enqueue the read command now that all checks have been passed
boolean result = commandQueue.add(new Runnable() {
@Override
public void run() {
if(!mGatt.readCharacteristic(characteristic)) {
Log.e(TAG, String.format("ERROR: readCharacteristic failed for characteristic: %s", characteristic.getUuid()));
completedCommand();
} else {
Log.d(TAG, String.format("reading characteristic <%s>", characteristic.getUuid()));
nrTries++;
}
}
});
if(result) {
nextCommand();
} else {
Log.e(TAG, "ERROR: Could not enqueue read characteristic command");
}
return result;
}
private void nextCommand() {
// If there is still a command being executed then bail out
if(commandQueueBusy) {
return;
}
// Check if we still have a valid gatt object
if (mGatt == null) {
Log.e(TAG, String.format("ERROR: GATT is 'null' for peripheral '%s', clearing command queue", device.getAddress()));
commandQueue.clear();
commandQueueBusy = false;
return;
}
// Execute the next command in the queue
if (commandQueue.size() > 0) {
final Runnable bluetoothCommand = commandQueue.peek();
commandQueueBusy = true;
nrTries = 0;
mHandler.post(new Runnable() {
@Override
public void run() {
try {
bluetoothCommand.run();
} catch (Exception ex) {
Log.e(TAG, String.format("ERROR: Command exception for device '%s'", device.getName()), ex);
}
}
});
}
}
private void retryCommand() {
commandQueueBusy = false;
Runnable currentCommand = commandQueue.peek();
if(currentCommand != null) {
if (nrTries >= MAX_TRIES) {
// Max retries reached, give up on this one and proceed
Log.v(TAG, "Max number of tries reached");
commandQueue.poll();
} else {
//isRetrying = true;
}
}
nextCommand();
}
private void completedCommand() {
commandQueueBusy = false;
//isRetrying = false;
commandQueue.poll();
nextCommand();
}
public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled) {
if (bluetoothAdapter == null || mGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mGatt.setCharacteristicNotification(characteristic, enabled);
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(BTMODULEUUID);
descriptor.setValue(enabled?BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE :BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
mGatt.writeDescriptor(descriptor);
}
It looks like you want to turn on notifications to receive data from your BLE device and you used setCharacteristicNotification(gattCharacteristic, true);
for that purpose. But this is not enough. It will only tell the Bluetooth Stack that this characteristic will send notifications, but you also want to subscribe to the notifications on your device.
For that you need the so called CCC descriptor and write ENABLE_NOTIFICATION_VALUE to it:
private final String CCC_DESCRIPTOR_UUID = "00002902-0000-1000-8000-00805f9b34fb";
final BluetoothGattDescriptor descriptor = gattCharacteristic.getDescriptor(UUID.fromString(CCC_DESCRIPTOR_UUID));
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
bluetoothGatt.writeDescriptor(descriptor);
Doing both will enable notifications for this device. Have a look at this awesome Guide from PunchTrough for more informations on using BLE.