问题
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?
回答1:
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.
回答2:
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.
来源:https://stackoverflow.com/questions/39736475/reading-from-a-bluetoothgattcharacteristic-is-failing