Android BLE characteristics getValue is no any response? - android

I am trying to configure READ characteristic with notification attribute. At the moment I can see this characteristic on android app with properties READ and NOTIFY.
here is my device's uuid info :
UUID info
YES, I need to notification attribute first , then second I send command , that will be receive value, but ,
in fact , I don't receive any value , I don't even know what's wrong, here is my code :
public void onServicesDiscovered(BluetoothGatt gatt, int status){
if (status == gatt.GATT_SUCCESS){
runOnUiThread(new Runnable(){
public void run() {
BluetoothGattService gattService = gatt.getService(SERVICE_UUID);
if(gattService != null){
BluetoothGattCharacteristic gattCharacteristic = gattService.getCharacteristic(NOTIF_UUID);
if (gattCharacteristic != null ){
for (BluetoothGattDescriptor descriptor : gattCharacteristic.getDescriptors()){
descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
boolean sucess = gatt.writeDescriptor(descriptor);
}
gatt.setCharacteristicNotification(gattCharacteristic, true);
}
characteristic = gattService.getCharacteristic(WRITE_DATA);
if (characteristic != null){
sendCommand(characteristic, gatt); //send command
}
now , I have already send command , and it's return success , because onCharacteristicWrite() has response,
but onCharacteristicRead() and onCharacteristicChanged() is not any response? Why ?
which part I missing?

descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
instead of
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);

Related

bluetooth ble writecharacteristics return write_empty ondeviceresult

I have just connected to ble device successfully, and enabled the notifications for read and write. but after i set value true and call writecharacteristics method i can write to device and get write empty response from bledevice..
What should be the flow of a write request to ble device?
public void onServicesDiscovered(BluetoothGatt bluetoothGatt, int i) {
BLEService.this.f8468j = BLEService.this.f8466h.getCharacteristic(BLEService.this.f8462d);//readchar.
BLEService.this.f8467i = BLEService.this.f8466h.getCharacteristic(BLEService.this.f8460b);//writechar.
setcharacteristicnotification(true, bluetoothgat, BLEService.this.f8467i);
// i need to writechar right now in here. but ondeviceresult returns "write_empty"... what is wrong?
bArr = new byte[]{97,48,24,69,96,27,79,91,55,7,30,63,87,84,7,87}
this.BluetoothGattCharacteristicwrite.setValue(bArr);
this.BluetoothGatt.writeCharacteristic(this.BluetoothGattCharacteristicwrite);
super.onServicesDiscovered(bluetoothGatt, i);
}
};
-
private void setcharacteristicnotification(boolean z, BluetoothGatt bluetoothGatt, BluetoothGattCharacteristic bluetoothGattCharacteristic) {
if (bluetoothGatt != null && bluetoothGattCharacteristic != null) {
bluetoothGatt.setCharacteristicNotification(bluetoothGattCharacteristic, z);
BluetoothGattDescriptor descriptor = bluetoothGattCharacteristic.getDescriptor(BLEService.this.f8463e);
if (descriptor != null) {
descriptor.setValue(z ? BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE : BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
BLEService.this.f8465g.writeDescriptor(descriptor);
}
//("BLEService", "=== enableNotification isWriting = true ===");
BLEService.this.m11448a(7);
}
}
You can't have multiple outstanding GATT requests at a time. Now you call writeDescriptor followed by writeCharacteristic without waiting for onDescriptorWrite.

Android - Getting null descriptors from a Characteristic

I am trying to interface with an Red Bear Labs nRF8001 Arduino Shield via Android Studio. I am succesfully able to send a command via Android and recieve it on my Arduino.
However I wish to read the response from my Arduino, using "OnCharacteristicChange" - however research showed a descriptor is required.
This is my code sample:
#Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
super.onServicesDiscovered(gatt, status);
if(status != BluetoothGatt.GATT_SUCCESS){
Log.i("BtServiceCallback","OnServicesDiscovered Failed!");
}
BluetoothGattService service = gatt.getService(RBLService.UUID_BLE_SHIELD_SERVICE);
BluetoothGattCharacteristic characteristic = service.getCharacteristic(RBLService.UUID_BLE_SHIELD_TX);
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString(RBLGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
gatt.writeDescriptor(descriptor);
byte[] val = readSetPoint.getBytes();
characteristic.setValue(val);
gatt.setCharacteristicNotification(characteristic,true);
gatt.writeCharacteristic(characteristic);
Log.i("Sent = ", characteristic.getStringValue(0));
}
Whenever I try to create a descriptor from the characteristic, I get the following error:
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.bluetooth.BluetoothGattDescriptor.setValue(byte[])' on a null object reference
at uk.ac.as988brighton.bluecontroller.MainActivity$1.onServicesDiscovered(MainActivity.java:160)
at android.bluetooth.BluetoothGatt$1.onSearchComplete(BluetoothGatt.java:286)
at android.bluetooth.IBluetoothGattCallback$Stub.onTransact(IBluetoothGattCallback.java:103)
at android.os.Binder.execTransact(Binder.java:573)
I am using the UUIDs from RBL's Github:
public static String CLIENT_CHARACTERISTIC_CONFIG = "00002902-0000-1000-8000-00805f9b34fb";
public static String BLE_SHIELD_TX = "713d0003-503e-4c75-ba94-3148f18d941e";
public static String BLE_SHIELD_RX = "713d0002-503e-4c75-ba94-3148f18d941e";
public static String BLE_SHIELD_SERVICE = "713d0000-503e-4c75-ba94-3148f18d941e";
I am unsure as to what is causing the null descriptor.
Edit
I have used different combinations for the descriptor - such as using
BluetoothGattDescriptor characteristic.getDescriptor(RBLService.UUID_BLE_SHIELD_TX);
But still receiving the same error.
It looks like you need to make sure you're naming things the same. Both your service and characteristic uuid are declared as BLE_SHIELD_SERVICE and BLE_SHIELD_TX but you're trying to access them with UUID_BLE_SHIELD_SERVICE and UUID_BLE_SHIELD_TX.
So change
BluetoothGattService service = gatt.getService(RBLService.UUID_BLE_SHIELD_SERVICE); to
BluetoothGattService service = gatt.getService(RBLService.BLE_SHIELD_SERVICE);
and
BluetoothGattCharacteristic characteristic = service.getCharacteristic(RBLService.UUID_BLE_SHIELD_TX); to
BluetoothGattCharacteristic characteristic = service.getCharacteristic(RBLService.BLE_SHIELD_TX);
and I believe it should work. Also make sure you are broadcasting those exact service and characteristic uuid's from your peripheral.
Good luck!

Android Ble status code 14 in onCharacteristicwrite

I am developing an app using BLE where i have to send some commands to peripheral device to get response. Write characteristics code is written below:
public void writeCustomCharacteristic(String value) {
this.value = "";
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
/*check if the service is available on the device*/
BluetoothGattService mCustomService = mBluetoothGatt.getService(SERVICE_UUID);
if (mCustomService == null) {
Log.w(TAG, "Custom BLE Service not found");
return;
}
/*get the read characteristic from the service*/
BluetoothGattCharacteristic mWriteCharacteristic = mCustomService.getCharacteristic(CHARACTERSTICS_UUID);
mWriteCharacteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
mWriteCharacteristic.setValue(value.getBytes());
if (!mBluetoothGatt.writeCharacteristic(mWriteCharacteristic)) {
Log.w(TAG, "Failed to write characteristic");
}
}
And after write characteristics i got response in following method here it returns status code 14, which is not mentioned in official document as well:
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
System.out.println("BluetoothLeService.onCharacteristicWrite");
System.out.println(BluetoothGatt.GATT_SUCCESS + " :status: " + status);
}
Status code 14 probably means ATT error code 14, which is defined in Bluetooth Core specification v5.0, Vol 3, Part F, section 3.4.1.1 Table 3.3.
This error code is sent from the remote device so it's most likely no error on the Android side. Error code 14 in ATT means "Unlikely Error". You need to investigate why the remote device sends this error code.

Reading from a BluetoothGattCharacteristic is failing

Im trying to read the value stored in a BluetoothGattCharacteristic. The following is my BluetoothGattCallback code, where most of the action takes place:
private final BluetoothGattCallback mGattCallback =
new BluetoothGattCallback() {
#Override
public void onConnectionStateChange(BluetoothGatt gatt, int status,
int newState) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
Log.i(TAG, "Connected to GATT server.");
Log.i(TAG, "Getting services....");
gatt.discoverServices();
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
Log.i(TAG, "Disconnected from GATT server.");
}
}
#Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
BluetoothGattService serv = gatt.getService(Constants.MY_UUID);
if (serv != null) {
BluetoothGattCharacteristic characteristic = serv.getCharacteristic(Constants.ANOTHER_UUID);
boolean res = gatt.readCharacteristic(characteristic);
if (res) {
Log.d(TAG, "res was true");
} else {
Log.d(TAG, "res was false");
}
}
} else {
Log.w(TAG, "onServicesDiscovered received: " + status);
}
}
#Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic,
int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
Log.d(TAG, "Succesfully read characteristic: " + characteristic.getValue().toString());
} else {
Log.d(TAG, "Characteristic read not successful");
}
}
};
So to read from the characteristic, i'm attempting to use the gatt.readCharacteristic() method, which takes a characteristic and returns a boolean indicating a successful operation or not. Here, this method is returning false (printing "res was false"), indicating it failed.
There is no error message being printed. What is the proper way to read a characteristic? Why would this method be returning false?
EDIT:
As suggested by Inferno, went ahead and downloaded the needed sources and then set a breakpoint in the BluetoothGatt readCharacteristic() method:
Here is the readCharacteristic() method in android-23..\BluetoothGatt
public boolean readCharacteristic(BluetoothGattCharacteristic characteristic) {
if ((characteristic.getProperties() &
BluetoothGattCharacteristic.PROPERTY_READ) == 0) return false;
(characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_READ) is returning 0 so false is being immediately returned. Now according to the debugger characteristic.getProperties() is returning a value of 8, while BluetoothGattCharacteristic.PROPERTY_READ has a static int value of 0x02.
As I understand, 0x08 & 0x02 == 0. Since the PROPERTY_READ is a hardcoded value, I assume something is wrong with the value returned from characteristic.getProperties(). What could be going wrong here?
What is the proper way to read a characteristic?
First of all, you call gatt.readCharacteristic(characteristic) from inside of the onServicesDiscovered() callback, which is alright. I can't see any serious flaws in your code.
What you could add in onConnectionStateChange() is an additional check before you verify newState == BluetoothProfile.STATE_CONNECTED:
if (status == BluetoothGatt.GATT_SUCCESS) { ...
Why would this method be returning false?
I checked the android source of BluetoothGatt here and it turns out, the return value of false is returned in many different cases as you can see in the code below:
public boolean readCharacteristic(BluetoothGattCharacteristic characteristic) {
if ((characteristic.getProperties() &
BluetoothGattCharacteristic.PROPERTY_READ) == 0) return false;
if (VDBG) Log.d(TAG, "readCharacteristic() - uuid: " + characteristic.getUuid());
if (mService == null || mClientIf == 0) return false;
BluetoothGattService service = characteristic.getService();
if (service == null) return false;
BluetoothDevice device = service.getDevice();
if (device == null) return false;
synchronized(mDeviceBusy) {
if (mDeviceBusy) return false;
mDeviceBusy = true;
}
try {
mService.readCharacteristic(mClientIf, device.getAddress(),
characteristic.getInstanceId(), AUTHENTICATION_NONE);
} catch (RemoteException e) {
Log.e(TAG,"",e);
mDeviceBusy = false;
return false;
}
return true;
}
So what I recommend you to do is, start the debugger in Android Studio and set a breakpoint inside the readCharacteristic() method (in BluetoothGatt.java) and carefully step through the code to see where false gets returned. That way you will hopefully be able to localize the issue. Besides that, anything else would be wild guessing.
Of course you need to have the sources downloaded to be able to view BluetoothGatt.java. But Android Studio will give you a small yellow bar at the top of the editor which asks you if you want to download and install. Just do it and restart Android Studio after the download is complete. Then you should be able to set a breakpoint in BluetoothGatt.java.
UPDATE:
As I understand, 0x08 & 0x02 == 0. Since the PROPERTY_READ is a
hardcoded value, I assume something is wrong with the value returned
from characteristic.getProperties(). What could be going wrong here?
According to BLUETOOTH SPECIFICATION Version 4.2 [Vol 3, Part G] page 533, the value of 0x8 which is returned by characteristic.getProperties() means, that your characteristic has write only permissions. Not a surprise that all reading attempts fail. In other words: your bluetooth device does not allow you to read that particular characteristic.
Quote from the specification:
The Characteristic Properties bit field determines how the Characteristic Value
can be used, or how the characteristic descriptors (see Section 3.3.3) can be
accessed.
I was trying to read data back from a cow brush scratcher that had BLE chip.
It was under a read characteristic on a BLE module.
The data was coming back in hex i.e. 0x00 for BRUSH_OFF & 0x01 for BRUSH_ON
I was trying to read in this data in my android app and it kept coming back as blank.
Problem is 0x00 = NUll in ascii and 0x01 = SOH ascii it cannot be displayed on the screen.
0x30 = 0 in ascii 0x31 = 1 in ascii
Maybe you have escape characters coming back in hex and they cannot be read.
I spent months trying to figure out why i couldn't read back the values.
Hope this might help you.

Android BLE: onCharacteristicChanged never fires

I'm trying to write an Android app that mimics functionality already present in an iOS app I wrote. I am interfacing with 2 different BLE devices:
Blood Pressure Cuff
Weight Scale
On iOS, I have both devices working well and reporting data. On Android, I can't get it to work. After hours of research and testing, I think the basic issue I'm trying to solve is this:
On iOS, I call the following code to enable the BLE device to notify my iOS device when it has data to report:
#pragma mark - CBPeripheralDelegate Protocol methods
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error {
for (CBCharacteristic *characteristic in [service characteristics]) {
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
}
}
That's it. The notes for this method in iOS say the following:
If the specified characteristic is configured to allow both notifications and indications, calling this method enables notifications only.
Based on that (and the fact that it works in iOS), I'm figuring that the configuration descriptor for the characteristic for which I want notifications should be configured like this:
descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
gatt.writeDescriptor(descriptor);
With that in mind, my BLEDevice class looks like this:
public abstract class BLEDevice {
protected BluetoothAdapter.LeScanCallback mLeScanCallback;
protected BluetoothGattCallback mBluetoothGattCallback;
protected byte[] mBytes;
protected Context mContext;
protected GotReadingCallback mGotReadingCallback;
protected String mDeviceName;
public final static UUID UUID_WEIGHT_SCALE_SERVICE
= UUID.fromString(GattAttributes.WEIGHT_SCALE_SERVICE);
public final static UUID UUID_WEIGHT_SCALE_READING_CHARACTERISTIC
= UUID.fromString(GattAttributes.WEIGHT_SCALE_READING_CHARACTERISTIC);
public final static UUID UUID_WEIGHT_SCALE_CONFIGURATION_CHARACTERISTIC
= UUID.fromString(GattAttributes.WEIGHT_SCALE_CONFIGURATION_CHARACTERISTIC);
public final static UUID UUID_WEIGHT_SCALE_CONFIGURATION_DESCRIPTOR
= UUID.fromString(GattAttributes.WEIGHT_SCALE_CONFIGURATION_DESCRIPTOR);
abstract void processReading();
interface GotReadingCallback {
void gotReading(Object reading);
}
public BLEDevice(Context context, String deviceName, GotReadingCallback gotReadingCallback) {
mContext = context;
BluetoothManager btManager = (BluetoothManager)mContext.getSystemService(Context.BLUETOOTH_SERVICE);
final BluetoothAdapter btAdapter = btManager.getAdapter();
if (btAdapter != null && !btAdapter.isEnabled()) {
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
mContext.startActivity(enableIntent);
}
mDeviceName = deviceName;
mBluetoothGattCallback = new BluetoothGattCallback() {
#Override
public void onCharacteristicChanged(BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
byte[] data = characteristic.getValue();
mBytes = data;
Log.d("BluetoothGattCallback.onCharacteristicChanged", "data: " + data.toString());
}
#Override
public void onConnectionStateChange(final BluetoothGatt gatt, final int status, final int newState) {
// this will get called when a device connects or disconnects
if (newState == BluetoothProfile.STATE_CONNECTED) {
gatt.discoverServices();
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
if (mBytes != null) {
processReading();
}
}
}
#Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
super.onDescriptorWrite(gatt, descriptor, status);
Log.d("onDescriptorWrite", "descriptor: " + descriptor.getUuid() + ". characteristic: " + descriptor.getCharacteristic().getUuid() + ". status: " + status);
}
#Override
public void onServicesDiscovered(final BluetoothGatt gatt, final int status) {
// this will get called after the client initiates a BluetoothGatt.discoverServices() call
BluetoothGattService service = gatt.getService(UUID_WEIGHT_SCALE_SERVICE);
if (service != null) {
BluetoothGattCharacteristic characteristic;
characteristic = service.getCharacteristic(UUID_WEIGHT_SCALE_READING_CHARACTERISTIC);
if (characteristic != null) {
gatt.setCharacteristicNotification(characteristic, true);
}
characteristic = service.getCharacteristic(UUID_WEIGHT_SCALE_CONFIGURATION_CHARACTERISTIC);
if (characteristic != null) {
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID_WEIGHT_SCALE_CONFIGURATION_DESCRIPTOR);
if (descriptor != null) {
descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
gatt.writeDescriptor(descriptor);
}
}
}
}
};
mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
#Override
public void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord) {
Log.d("LeScanCallback", device.toString());
if (device.getName().contains("{Device Name}")) {
BluetoothGatt bluetoothGatt = device.connectGatt(mContext, false, mBluetoothGattCallback);
btAdapter.stopLeScan(mLeScanCallback);
}
}
};
btAdapter.startLeScan(mLeScanCallback);
}
}
NOTE: It might be important to know that these 2 devices function in the following way:
The BLE device is turned on an a measurement is initiated on the device.
Once the measurement has been taken, the BLE device attempts to initiate a BLE connection.
Once the BLE connection is made, the device pretty much immediately sends the data, sometimes sending a couple of data packets. (If previous data measurements haven't been successfully sent over BLE, it keeps them in memory and sends all of them, so I only really care about the final data packet.)
Once the final data packet is sent, the BLE device disconnects rapidly.
If the BLE device fails to send data (as is currently happening on the Android app), the BLE device disconnects pretty rapidly.
In my LogCat, I see a lot of output that's exactly like I'd expect.
I see a list of services like I expect, including the data service I want.
I see a list of characteristics like I expect, including the data characteristic I want.
I see a list of descriptors like I expect, including the "configuration" (0x2902) descriptor.
The most recent failure I'm experiencing is a status of "128" being reported in onCharacteristicWrite. The comments to question #3 (below) seem to indicate this is a resource issue.
I've looked at the following questions:
Android BLE onCharacteristicChanged not called
Android BLE, read and write characteristics
Android 4.3 onDescriptorWrite returns status 128
Here's why they don't give me what I need:
This question's answer was not to read the descriptor's value. I'm not doing that, so that can't be what's getting in the way.
This is basically an overview of the various methods that are available, which I think I now understand. The big key in this question/answer is not to write multiple times to different descriptors, but I'm also not doing that. I only care about the one characteristic.
This question/answer seems to be related to BLE resource limitations, but I don't think this applies. I'm only connecting this one device and I'm trying to do a very, very simple data transfer. I don't think I'm hitting resource ceilings.
I've tried a bunch of examples and tutorials, including Google's Android sample code. None of them seem to enable the BLE device to notify my Android device of data updates. It's obviously not the device, since the iOS version works. So, what is the iOS code doing in the background to get the notifications to work and what code on the Android side will mimic that functionality?
EDIT/UPDATE
Based on #yonran's comments, I updated my code by changing the onServicesDiscovered implementation to this:
#Override
public void onServicesDiscovered(final BluetoothGatt gatt, final int status) {
// this will get called after the client initiates a BluetoothGatt.discoverServices() call
BluetoothGattService service = gatt.getService(UUID_WEIGHT_SCALE_SERVICE);
if (service != null) {
BluetoothGattCharacteristic characteristic = service.getCharacteristic(UUID_WEIGHT_SCALE_READING_CHARACTERISTIC);
if (characteristic != null) {
if (gatt.setCharacteristicNotification(characteristic, true) == true) {
Log.d("gatt.setCharacteristicNotification", "SUCCESS!");
} else {
Log.d("gatt.setCharacteristicNotification", "FAILURE!");
}
BluetoothGattDescriptor descriptor = characteristic.getDescriptors().get(0);
if (0 != (characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_INDICATE)) {
// It's an indicate characteristic
Log.d("onServicesDiscovered", "Characteristic (" + characteristic.getUuid() + ") is INDICATE");
if (descriptor != null) {
descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
gatt.writeDescriptor(descriptor);
}
} else {
// It's a notify characteristic
Log.d("onServicesDiscovered", "Characteristic (" + characteristic.getUuid() + ") is NOTIFY");
if (descriptor != null) {
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
gatt.writeDescriptor(descriptor);
}
}
}
}
}
That does seem to have changed some things a little bit. Here's the current Logcat, following that code change:
D/BluetoothGatt﹕ setCharacteristicNotification() - uuid: <UUID> enable: true
D/gatt.setCharacteristicNotification﹕ SUCCESS!
D/onServicesDiscovered﹕ Characteristic (<UUID>) is INDICATE
D/BluetoothGatt﹕ writeDescriptor() - uuid: 00002902-0000-1000-8000-00805f9b34fb
D/BluetoothGatt﹕ onDescriptorWrite() - Device=D0:5F:B8:01:6C:9E UUID=<UUID>
D/onDescriptorWrite﹕ descriptor: 00002902-0000-1000-8000-00805f9b34fb. characteristic: <UUID>. status: 0
D/BluetoothGatt﹕ onClientConnectionState() - status=0 clientIf=6 device=D0:5F:B8:01:6C:9E
So, it would appear that I'm now setting everything up properly (since setCharacteristicNotification returns true and the onDescriptorWrite status is 0). However, onCharacteristicChanged still never fires.
I've been able to successfully catch onCharacteristicChanged() with multiple services and characteristics by:
Writing descriptor values in the broadcastReceiver() in the main loop after service discovery is finished.
private final BroadcastReceiver UARTStatusChangeReceiver = new BroadcastReceiver() {
//more code...
if (action.equals(uartservice.ACTION_GATT_SERVICES_DISCOVERED)) {
mService.enableTXNotification();
}
and
By adding a delay between descriptor value settings
public void enableTXNotification(){
/*
if (mBluetoothGatt == null) {
showMessage("mBluetoothGatt null" + mBluetoothGatt);
broadcastUpdate(DEVICE_DOES_NOT_SUPPORT_UART);
return;
}
*/
/**
* Enable Notifications for the IO service and characteristic
*
*/
BluetoothGattService IOService = mBluetoothGatt.getService(IO_SERVICE_UUID);
if (IOService == null) {
showMessage("IO service not found!");
broadcastUpdate(DEVICE_DOES_NOT_SUPPORT_IO);
return;
}
BluetoothGattCharacteristic IOChar = IOService.getCharacteristic(IO_CHAR_UUID);
if (IOChar == null) {
showMessage("IO charateristic not found!");
broadcastUpdate(DEVICE_DOES_NOT_SUPPORT_IO);
return;
}
mBluetoothGatt.setCharacteristicNotification(IOChar,true);
BluetoothGattDescriptor descriptorIO = IOChar.getDescriptor(CCCD);
descriptorIO.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(descriptorIO);
/**
* For some reason android (or the device) can't handle
* writing one descriptor after another properly. Without
* the delay only the first characteristic can be caught in
* onCharacteristicChanged() method.
*/
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
/**
* Enable Indications for the RXTX service and characteristic
*/
BluetoothGattService RxService = mBluetoothGatt.getService(RXTX_SERVICE_UUID);
if (RxService == null) {
showMessage("Rx service not found!");
broadcastUpdate(DEVICE_DOES_NOT_SUPPORT_UART);
return;
}
BluetoothGattCharacteristic RxChar = RxService.getCharacteristic(RXTX_CHAR_UUID);
if (RxChar == null) {
showMessage("Tx charateristic not found!");
broadcastUpdate(DEVICE_DOES_NOT_SUPPORT_UART);
return;
}
mBluetoothGatt.setCharacteristicNotification(RxChar,true);
BluetoothGattDescriptor descriptor = RxChar.getDescriptor(CCCD);
descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE );
mBluetoothGatt.writeDescriptor(descriptor);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
/**
* Enable Notifications for the Battery service and Characteristic?
*/
BluetoothGattService batteryService = mBluetoothGatt.getService(BATTERY_SERVICE_UUID);
if (batteryService == null) {
showMessage("Battery service not found!");
broadcastUpdate(DEVICE_DOES_NOT_SUPPORT_BATTERY);
return;
}
BluetoothGattCharacteristic batteryChar = batteryService.getCharacteristic(BATTERY_CHAR_UUID);
if (batteryChar == null) {
showMessage("Battery charateristic not found!");
broadcastUpdate(DEVICE_DOES_NOT_SUPPORT_BATTERY);
return;
}
}
I was facing the same problem.
that's because when the device is sending the indicate value, your application is charged in another process and that's why you never get the indicate value which make the onCharacteristicChanged never fires.
to resolve your problem try to put all traitement in a service. and just call functions from your activity.

Categories

Resources