I have an Android app which can connect to a BLE device (using BMD-350), receive data from it via notifications and transmit data on a characteristic. I don't know why, but after a while the BLE device disconnects on its own, reporting error code 8 in the BondStateChanged callback. I can see data coming in to the phone right up until it disconnects. The BLE device sends data to the phone around 550 bytes/sec. The phone does not send any data to the BLE device in this time. Why is it disconnecting?
*note: This code is written in C# (Xamarin), but it's basically the same as its Java counterpart.
Connection Code:
_bleGatt = device.ConnectGatt(context, false, this);
Connection Callback:
if (newState == ProfileState.Connected)
{
if (status == GattStatus.Success)
{
gatt.DiscoverServices();
}
}
Service Discovery:
public override void OnServicesDiscovered(BluetoothGatt gatt, GattStatus status)
{
base.OnServicesDiscovered(gatt, status);
BluetoothGattService mService;
try
{
mService = gatt.GetService(UART_UUID);
}
catch
{
BluetoothConnectionError("UART service not found", gatt.Device);
return;
}
_tx = mService.GetCharacteristic(TX_UUID);
_rx = mService.GetCharacteristic(RX_UUID);
if (_tx == null)
{
BluetoothConnectionError("Tx characteristic not found", gatt.Device);
return;
}
if ((_tx.Properties | GattProperty.WriteNoResponse) == 0 && (_tx.Properties | GattProperty.Write) == 0)
{
BluetoothConnectionError("Tx characteristic not not in 'write' or 'write - no response' mode", gatt.Device);
return;
}
if (_rx == null)
{
BluetoothConnectionError("Rx characteristic not found", gatt.Device);
return;
}
if ((_rx.Properties | GattProperty.Notify) == 0)
{
BluetoothConnectionError("Rx characteristic not in 'notify' mode", gatt.Device);
return;
}
BluetoothGattDescriptor mDescriptor = _rx.GetDescriptor(CLIENT_UUID);
if (mDescriptor == null)
{
BluetoothConnectionError("Could not get descriptor", gatt.Device);
return;
}
mDescriptor.SetValue(BluetoothGattDescriptor.EnableNotificationValue.ToArray());
try
{
gatt.WriteDescriptor(mDescriptor);
}
catch
{
BluetoothConnectionError("Could not write descriptor", gatt.Device);
return;
}
ConnectionStatusChanged(ProfileState.Connected, gatt.Device);
}
Enabling Receive Notifications:
_bleGatt.SetCharacteristicNotification(_rx, true);
Reading Characteristic:
public override void OnCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic)
{
base.OnCharacteristicChanged(gatt, characteristic);
PublishNewData(characteristic.GetValue());
}
UUID's/CCCD:
private readonly UUID UART_UUID = UUID.FromString("6e400001-b5a3-f393-e0a9-e50e24dcca9e");
private readonly UUID RX_UUID = UUID.FromString("6e400003-b5a3-f393-e0a9-e50e24dcca9e");
private readonly UUID TX_UUID = UUID.FromString("6e400002-b5a3-f393-e0a9-e50e24dcca9e");
private readonly UUID CLIENT_UUID = UUID.FromString("00002902-0000-1000-8000-00805f9b34fb");
Related
I have a BLE device (smartwatch) in which i want to read all data from services and use in my application(Swift and Android), How can i access data from the custom services, but i cant see the UUID in the GATT services and characteristics
You can read data using this code. it's work for me.
When you Smartwatch connected then you needs to send request for service discover. So, Below callback method triggered. In this method get your service and characteristics.
#Override
public void onServicesDiscovered(final BluetoothGatt gatt, final int status) {
Log.e(TAG, "onServicesDiscovered: ");
if (status != BluetoothGatt.GATT_SUCCESS) {
Log.w(TAG, "onServicesDiscovered received: " + status);
return;
}
BluetoothGattService customService = gatt.getService(CUSTOM_SERVICE_UUID);
if (customService != null) {
customNotifyCharacteristic = customService.getCharacteristic(CUSTOM_CHARACTERISTICS_NOTIFY_UUID);
customWriteCharacteristic = customService.getCharacteristic(CUSTOM_CHARACTERISTICS_WRITE_UUID);
customReadCharacteristic = customService.getCharacteristic(CUSTOM_CHARACTERISTICS_READ_UUID);
}
}
After getting all characteristics and services send read request like below.
put below line where you need to read data.
readCharacteristic(customReadCharacteristic);
below explain readCharacteristic method.
public void readCharacteristic(BluetoothGattCharacteristic characteristic) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.readCharacteristic(characteristic);
}
So, onCharacteristicRead callback triggered.
#Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic,
int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
byte[] data = characteristic.getValue();
}
}
byte[] data = characteristic.getValue();
return your data which you want to read form device.
My CLIENT_CHARACTERISTIC_CONFIG is
public final static UUID CLIENT_CHARACTERISTIC_CONFIG = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
I do this to change CHARACTERISTIC:
BluetoothGatt mBluetoothGatt = device.connectGatt(this.context, false, mGattCallback);
mBluetoothGatt.connect();
BluetoothGattService mCustomService = bleScanner.getBluetoothGatt().getService(UUID.fromString(bleServiceUUID));
if(mCustomService == null){
return;
}
BluetoothGattCharacteristic mCharacteristic = mCustomService.getCharacteristic(UUID.fromString(bleCharacteristicUUID));
if(mReadCharacteristic == null){
return;
}
String message = "myMessage";
mCharacteristic.setValue(message.getBytes());
if (!mBluetoothGatt.writeCharacteristic(characteristic)) {
Log.e(TAG, "Failed to write characteristic");
} else {
Log.e(TAG, "Writed characteristic " + message);
}
After that characteristic is changed on sensor, onCharacteristicWrite is called in BluetoothGattCallback
#Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
if (!mBluetoothGatt.setCharacteristicNotification(characteristic, true)) {
DLog.e(TAG, "Notification Setup failed: "+characteristic.getUuid());
}
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(CLIENT_CHARACTERISTIC_CONFIG);
if (descriptor!=null){
descriptor.setValue( BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(descriptor1);
}
}
}
BUT descriptor is always NULL. And onCharacteristicChanged is never called.
Why? and is my CLIENT_CHARACTERISTIC_CONFIG right?
it was because some of devices (mine is Samsung E5 Android 4.3->updated to 5.1.1) are support BLE but doesn't support BluetoothGattDescriptor 0x2902 (see link)
to see all Descriptors which are supporter in device call this:
for (BluetoothGattDescriptor descriptor:characteristic.getDescriptors()){
Log.e(TAG, "BluetoothGattDescriptor: "+descriptor.getUuid().toString());
}
[UPDATE]
Some BLE devices doesn't support Writed characteristics, such as iBeacon
I currently have a method which writes to the BLE devices to beep it. My Bluetooth Callback goes as follows :
public class ReadWriteCharacteristic extends BluetoothGattCallback {
public ReadWriteCharacteristic(Context context, String macAddress, UUID service, UUID characteristic, Object tag, Activity activity) {
mMacAddress = macAddress;
mService = service;
mCharacteristic = characteristic;
mTag = tag;
mContext = context;
this.activity =activity;
final BluetoothManager bluetoothManager =
(BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
}
final private static String TAG = "ReadCharacteristic";
private Object mTag;
private String mMacAddress;
private UUID mService;
private BluetoothManager mBluetoothManager = null;
private BluetoothAdapter mBtAdapter = null;
private BluetoothGatt mBluetoothGatt = null;
private String mBluetoothDeviceAddress ="";
private UUID mCharacteristic;
BluetoothDevice device;
private Activity activity;
private BluetoothAdapter mBluetoothAdapter;
private Context mContext;
ReadWriteCharacteristic rc;
private int retry = 5;
public String getMacAddress() {
return mMacAddress;
}
public UUID getService() {
return mService;
}
public UUID getCharacteristic() {
return mCharacteristic;
}
public byte[] getValue() { return mValue; }
public void onError() {
Log.w(TAG, "onError");
}
public void readCharacteristic(){
if (retry == 0)
{
onError();
return;
}
retry--;
device = mBluetoothAdapter.getRemoteDevice(getMacAddress());
mBluetoothManager = (BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE);
int connectionState = mBluetoothManager.getConnectionState(device,
BluetoothProfile.GATT);
if (device != null) {
if (connectionState == BluetoothProfile.STATE_DISCONNECTED)
{
// Previously connected device. Try to reconnect.
if (mBluetoothDeviceAddress != null
&& getMacAddress().equals(mBluetoothDeviceAddress)
&& mBluetoothGatt != null) {
Log.w(TAG, "Re-use GATT connection");
if (mBluetoothGatt.connect()) {
Log.w(TAG, "Already connected, discovering services");
mBluetoothGatt.discoverServices();
//return ;
} else {
Log.w(TAG, "GATT re-connect failed.");
return;
}
}
if (device == null) {
Log.w(TAG, "Device not found. Unable to connect.");
return;
}
Log.w(TAG, "Create a new GATT connection.");
rc= ReadWriteCharacteristic.this;
Log.w(TAG, "Starting Read [" + getService() + "|" + getCharacteristic() + "]");
mBluetoothGatt = device.connectGatt(mContext, false, rc);
refreshDeviceCache(mBluetoothGatt);
mBluetoothDeviceAddress = getMacAddress();
} else {
Log.w(TAG, "Attempt to connect in state: " + connectionState);
if(mBluetoothGatt!=null)
mBluetoothGatt.close();
readCharacteristic();
}
}
}
#Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
super.onConnectionStateChange(gatt, status, newState);
Log.w(TAG,"onConnectionStateChange [" + status + "|" + newState + "]");
if ((newState == 2)&&(status ==0)) {
gatt.discoverServices();
}
else if(status == 133 )
{
//gatt.disconnect();
gatt.close();
mBluetoothGatt = null;
try
{
Thread.sleep(2000);
}
catch(Exception e)
{
}
readCharacteristic();
}
else{
if(mBluetoothGatt!=null)
mBluetoothGatt.close();
// gatt.close();
Log.w(TAG, "[" + status + "]");
//gatt.disconnect();
try
{
Thread.sleep(2000);
}
catch(Exception e)
{
}
mBluetoothGatt = null;
readCharacteristic();
}
}
#Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
Log.w(TAG,"onServicesDiscovered [" + status + "]");
BluetoothGattService bgs = gatt.getService(getService());
if (bgs != null) {
BluetoothGattCharacteristic bgc = bgs.getCharacteristic(getCharacteristic());
gatt.readCharacteristic(bgc);
}
}
#Override
public void onCharacteristicWrite(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic,
int status) {
Log.w(TAG,"onCharacteristicWrite [" + status + "]");
if (status == BluetoothGatt.GATT_SUCCESS) {
Log.w(TAG,"onCharacteristicWrite [" + getDataHex(characteristic.getValue()) + "]");
// gatt.disconnect();
if(mBluetoothGatt!=null)
mBluetoothGatt.close();
// gatt.close();
// mBluetoothGatt=null;
}
else if(status ==133)
{
gatt.close();
try
{
Thread.sleep(2000);
}
catch(Exception e)
{
}
readCharacteristic();
}
else{
//gatt.disconnect();
gatt.close();
}
}
#Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic,
int status) {
Log.w(TAG,"onCharacteristicRead [" + status + "]");
if (status == BluetoothGatt.GATT_SUCCESS) {
mValue = characteristic.getValue();
// Perform write operations
gatt.writeCharacteristic(bgc);
}
else if(status ==133)
{
gatt.close();
try
{
Thread.sleep(2000);
}
catch(Exception e)
{
}
readCharacteristic();
}
else {
// gatt.disconnect();
gatt.close();
}
}
}
This code works perfectly on device running Kitkat and below. But on Devices running Lollipop, this code works fine for the first instance. But from the next instance, irrespective of whether I disconnect or close the connection and try again, it just does not work. It keeps giving me a status code of 257 in onConnectionStateChange method. As far as I know, The Bluetooth GATT methods are the same for both kitkat and Lollipop devices.
What surprises me is that this code works fine on Lollipop devices when i use the old BLE API i.e startLeScan ( For eg - mBluetoothAdapter.startLeScan(mLeScanCallback);). This problem only arises when I use the new BLE API i.e BluetoothLeScanner ( scanner.startScan(filters, settings, new scancallback());). The scanning rate is really slow for Lollipop devices using the old BLE API, hence I cannot use it. I just don't understand how to solve this problem.Has anyone faced the same problem and found a solution? Any help would be deeply appreciated.
Quite a few things I would change here. Create a class variable for the data you want to read from the characteristic, such as private string heartRate;
1) You don't need the readCharacteristic() method. Instead, in the onConnectionStateChange once the device has connected properly, call mBluetoothGatt.discoverServices(). Then in the onServicesDiscovered() method I would call gatt.getServices(). Then use a foreach loop and loop through the returned services and compare the UUID of the service until you find the one you care about. Then if heartRate == null, call service.getCharacteristic(HeartRateUUID) and then read the characteristic. In onCharacteristicRead() check if the UUID is equal to the heart rate characteristic. If it is, assign the value of the characteristic to the heartRate variable. If you are interested, I can type out the methods or provide pseudocode.
2) I wouldn't call gatt.connect() followed by gatt.discoverServices(). gatt.connect() will reconnect to the current device as soon as it sees an advertisement packet from the device. I would call gatt.connect() and then call gatt.discoverServices() in the onConnectedStateChange() method.
3) In the onConnectedStateChange method don't use the gatt variable. Use mBluetoothGatt instead. mBluetoothGatt.disconnect() disconnects from the currently connected device. mBluetoothGatt.close() terminates the gatt instance. You cannot call mBluetoothGatt.connect() after calling mBluetoothGatt.Close(). This might not be needed, but if the device is connected I call mBluetoothGatt.disconnect() followed by mBluetoothGatt.close().
4) You can also chain characteristic readings together. In onCharacteristicRead(), after you get the value of the heartRate, you can immediately call characteristic.getService().getCharacteristic(UUIDTemperature) and then read that characteristic. It will call the OnCharacteristicRead method again.
Let me know if you want me to clarify anything; I'm typing on the crappy Surface Pro 3 keyboard. :)
I'm working on a Android project which is to connect Nexus 7 and a bio sensor through BLE link. The problem is that, I can successfully detect and get list of services and characteristics of the sensor. When I write some data to the specific characteristic, onCharacteristicWrite is automatically called and showed me writing operation is successful. However, the sensor never receive anything from the tablet. And if I use similar app on iPhone, everything works fine. So there's no problem with the device.
Does anyone have any idea of the problem?
Here is my code for write:
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
#Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
mConnected = true;
Log.i(TAG, "Connected to GATT server.");
// Attempts to discover services after successful connection.
Log.i(TAG, "Attempting to start service discovery:" +
mBluetoothGatt.discoverServices());
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
mConnected = false;
Log.i(TAG, "Disconnected from GATT server.");
}
}
#Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
//Once detected services, write to characteristic for 6 times.
int count =6;
while(count>0){
writeCharacteristic();
count--;
}
} else {
Log.w(TAG, "onServicesDiscovered received: " + status);
}
}
#Override
public void onCharacteristicWrite(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic,
int status){
if (status == BluetoothGatt.GATT_SUCCESS){
Log.d(TAG,"Write to Characteristic Success! !");
}
}
};
public boolean writeCharacteristic(){
//check mBluetoothGatt is available
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return false;
}
BluetoothGattService Service = mBluetoothGatt.getService(UUID_MY_SERVICE);
if (Service == null) {
Log.e(TAG, "service not found!");
return false;
}
BluetoothGattCharacteristic characteristic = Service
.getCharacteristic(UUID_MY_CHARACTERISTIC);
if (characteristic == null) {
Log.e(TAG, "char not found!");
return false;
}
byte[] value = {(byte)300,(byte)100,(byte)100};
characteristic.setValue(value);
boolean status = mBluetoothGatt.writeCharacteristic(characteristic);
return status;
}
The output shows "Write to Characteristic Success! !" for six times, thus the writing operation succeeded. However, the device shows that nothing been received from tablet. I also tried to write one byte at a time, or add a timer to let the tablet write to sensor every 2 seconds. But none of them worked. Any ideas?
(Answered by question edit. Converted to a community wiki answer. See What is the appropriate action when the answer to a question is added to the question itself? )
The OP wrote:
Follow Up:
The problem solved by manually pairing the tablet with the device first in the setting instead of pairing by code.
So only using the code snippet of connecting Gatt provided by Android is not good enough to pair the device. I should add another code I found online to pair the devices if I don't want to pair them manually every time:
private void pairDevice(BluetoothDevice device) {
try {
Log.d("pairDevice()", "Start Pairing...");
Method m = device.getClass()
.getMethod("createBond", (Class[]) null);
m.invoke(device, (Object[]) null);
Log.d("pairDevice()", "Pairing finished.");
} catch (Exception e) {
Log.e("pairDevice()", e.getMessage());
}
}
As I'm currently working on a little bluetooth library for Android, I'm trying to get all the service uuids of the devices I discovered in my surrounding.
When my broadcast receiver gets the BluetoothDevice.ACTION_FOUND intent, I'm extracting the device and call:
device.fetchUuidsWithSdp();
This will result BluetoothDevice.ACTION_UUID intents for each device found and I'm handling them with the same receiver:
BluetoothDevice d = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Parcelable[] uuidExtra = intent.getParcelableArrayExtra(BluetoothDevice.EXTRA_UUID);
if(uuidExtra == null) {
Log.e(TAG, "UUID = null");
}
if(d != null && uuidExtra != null)
Log.d(TAG, d.getName() + ": " + uuidExtra.toString());
The thing is, that uuidExtra is always null.
How can i get all the UUIDs of the surrounding devices?
EDIT:
Im working on a Nexus 7. I tried code i found on the internet and this also gives me a NullPointerException: http://digitalhacksblog.blogspot.de/2012/05/android-example-bluetooth-discover-and.html
Thank you.
The documentation on this states...
Always contains the extra field BluetoothDevice.EXTRA_UUID
However, just like you, I have found this not to be true.
If you call fetchUuidsWithSdp() while device discovery is still taking place BluetoothDevice.EXTRA_UUID can be null.
You should wait until you receive BluetoothAdapter.ACTION_DISCOVERY_FINISHED before you make any calls to fetchUuidsWithSdp().
NOTE: This solution applies to CLASSIC bluetooth and not BLE. For BLE check how to send
manufacturer specific Data in advertiser on the peripheral side
The problem with fetching Uuids is that you have only one bluetooth adapter, and we cannot have parallel api calls which uses adapter for its purpose.
As Eddie pointed out, wait for BluetoothAdapter.ACTION_DISCOVERY_FINISHED and then call fetchUuidsWithSdp().
Still this cannot guarantee uuids to be fetched for all devices. In addition to this one must wait for each subsequent call to fetchuuidsWithSdp() to complete, and then give a call to this method for another device.
See the code below --
ArrayList<BluetoothDevice> mDeviceList = new ArrayList<BluetoothDevice>();
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = (BluetoothDevice) intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
mDeviceList.add(device);
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
// discovery has finished, give a call to fetchUuidsWithSdp on first device in list.
if (!mDeviceList.isEmpty()) {
BluetoothDevice device = mDeviceList.remove(0);
boolean result = device.fetchUuidsWithSdp();
}
} else if (BluetoothDevice.ACTION_UUID.equals(action)) {
// This is when we can be assured that fetchUuidsWithSdp has completed.
// So get the uuids and call fetchUuidsWithSdp on another device in list
BluetoothDevice deviceExtra = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Parcelable[] uuidExtra = intent.getParcelableArrayExtra(BluetoothDevice.EXTRA_UUID);
System.out.println("DeviceExtra address - " + deviceExtra.getAddress());
if (uuidExtra != null) {
for (Parcelable p : uuidExtra) {
System.out.println("uuidExtra - " + p);
}
} else {
System.out.println("uuidExtra is still null");
}
if (!mDeviceList.isEmpty()) {
BluetoothDevice device = mDeviceList.remove(0);
boolean result = device.fetchUuidsWithSdp();
}
}
}
}
UPDATE: Latest android versions (mm & above) would result in triggering a pairing process with each device
Here is a good example of how to get UUIDs of service characteristics from a service that I did for getting heart rate devices:
private class HeartRateBluetoothGattCallback extends BluetoothGattCallback {
#Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
logMessage("CONNECTED TO " + gatt.getDevice().getName(), false, false);
gatt.discoverServices();
} else if(newState == BluetoothProfile.STATE_DISCONNECTED) {
logMessage("DISCONNECTED FROM " + gatt.getDevice().getName(), false, false);
if(mIsTrackingHeartRate)
handleHeartRateDeviceDisconnection(gatt);
}
}
#Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
logMessage("DISCOVERING SERVICES FOR " + gatt.getDevice().getName(), false, false);
if(mDesiredHeartRateDevice != null &&
gatt.getDevice().getAddress().equals(mDesiredHeartRateDevice.getBLEDeviceAddress())) {
if(subscribeToHeartRateGattServices(gatt)) {
mIsTrackingHeartRate = true;
setDeviceScanned(getDiscoveredBLEDevice(gatt.getDevice().getAddress()), DiscoveredBLEDevice.CONNECTED);
broadcastHeartRateDeviceConnected(gatt.getDevice());
} else
broadcastHeartRateDeviceFailedConnection(gatt.getDevice());
} else {
parseGattServices(gatt);
disconnectGatt(getDiscoveredBLEDevice(gatt.getDevice().getAddress()));
}
}
}
#Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
if(characteristic.getUuid().equals(UUID.fromString(HEART_RATE_VALUE_CHAR_READ_ID))) {
int flag = characteristic.getProperties();
int format = -1;
if ((flag & 0x01) != 0)
format = BluetoothGattCharacteristic.FORMAT_UINT16;
else
format = BluetoothGattCharacteristic.FORMAT_UINT8;
Integer heartRateValue = characteristic.getIntValue(format, 1);
if(heartRateValue != null)
broadcastHeartRateValue(heartRateValue);
else
Log.w(SERVICE_NAME, "UNABLE TO FORMAT HEART RATE DATA");
}
};
};
private void parseGattServices(BluetoothGatt gatt) {
boolean isHeartRate = false;
for(BluetoothGattService blueToothGattService : gatt.getServices()) {
logMessage("GATT SERVICE: " + blueToothGattService.getUuid().toString(), false, false);
if(blueToothGattService.getUuid().toString().contains(HEART_RATE_DEVICE_SERVICE_CHARACTERISTIC_PREFIX))
isHeartRate = true;
}
if(isHeartRate) {
setDeviceScanned(getDiscoveredBLEDevice(gatt.getDevice().getAddress()), DiscoveredBLEDevice.IS_HEART_RATE);
broadcastHeartRateDeviceFound(getDiscoveredBLEDevice(gatt.getDevice().getAddress()));
} else
setDeviceScanned(getDiscoveredBLEDevice(gatt.getDevice().getAddress()), DiscoveredBLEDevice.NOT_HEART_RATE);
}
private void handleHeartRateDeviceDisconnection(BluetoothGatt gatt) {
broadcastHeartRateDeviceDisconnected(gatt.getDevice());
gatt.close();
clearoutHeartRateData();
scanForHeartRateDevices();
}
private void disconnectGatt(DiscoveredBLEDevice device) {
logMessage("CLOSING GATT FOR " + device.getBLEDeviceName(), false, false);
device.getBlueToothGatt().close();
device.setBlueToothGatt(null);
mInDiscoveryMode = false;
}
private boolean subscribeToHeartRateGattServices(BluetoothGatt gatt) {
for(BluetoothGattService blueToothGattService : gatt.getServices()) {
if(blueToothGattService.getUuid().toString().contains(HEART_RATE_DEVICE_SERVICE_CHARACTERISTIC_PREFIX)) {
mHeartRateGattService = blueToothGattService;
for(BluetoothGattCharacteristic characteristic : mHeartRateGattService.getCharacteristics()) {
logMessage("CHARACTERISTIC UUID = " + characteristic.getUuid().toString(), false, false);
for(BluetoothGattDescriptor descriptor :characteristic.getDescriptors()) {
logMessage("DESCRIPTOR UUID = " + descriptor.getUuid().toString(), false, false);
}
if(characteristic.getUuid().equals(UUID.fromString(HEART_RATE_VALUE_CHAR_READ_ID))) {
gatt.setCharacteristicNotification(characteristic, true);
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString(HEART_RATE_VALUE_CHAR_DESC_ID));
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
return gatt.writeDescriptor(descriptor);
}
}
break; //break out of master for-loop
}
}
return false;
}
I suppose you need to be paired with the device in order to receive the uuids.
At least, this is what happened to me.
device.getUuids() use this to get all the uuid of that paired device in the form of ParcelUuid; Example code below:-
private void get_uuid_from_paired_devices(){
Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();
for (BluetoothDevice device: pairedDevices){
for (ParcelUuid uuid: device.getUuids()){
String uuid_string = uuid.toString();
Log.d(TAG, "uuid : "+uuid_string);
}
}
}
Below worked for me to fetch the records from the remote device
-0-
registerReceiver(..,
new IntentFilter(BluetoothDevice.ACTION_UUID));
-1-
device.fetchUuidsWithSdp();
-2-from within the broadcase receiver
if (BluetoothDevice.ACTION_UUID.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Parcelable[] uuids = intent.getParcelableArrayExtra(BluetoothDevice.EXTRA_UUID);
for (Parcelable ep : uuids) {
Utilities.print("UUID records : "+ ep.toString());
}
}
You can also fetch the offline cached UUID records with
BluetoothDevice.getUuids();