I am trying to enable notifications for more than one BLE characteristic using Xamarin/Android but seem unable to do so. The app seems to stop receiving any BLE events if I try and enable more than one at a time.
Can anyone confirm whether this is possible using Tamarin/Android. We have a native iOS app that works just fine with multiple notifications enabled. The basic steps we use are as follows:
Any time we try and enable notifications on more than one characteristic we no longer receive any events.
I have also been unable to find any examples where more than one characteristic is being enabled.
I hope I have simply missed something fundamental about using the Xamarin/Android APIs here.
public override void OnServicesDiscovered (BluetoothGatt gatt, GattStatus status)
{
base.OnServicesDiscovered (gatt, status);
foreach (BluetoothGattService service in gatt.Services) {
string uuid = service.Uuid.ToString ().ToUpper();
if (uuid.Equals (BLEServices.HRService.ToUpper())) {
_Adap.LogMessage ("HRService discovered");
foreach(BluetoothGattCharacteristic characteristic in service.Characteristics) {
string c_uuid = characteristic.Uuid.ToString ().ToUpper ();
_Adap.LogMessage (" HRCharacteristic: " + c_uuid);
if (c_uuid.Equals(_Adap.useCharacteristic.ToUpper())) {
_Adap.LogMessage (" enabling HRCharacteristic");
gatt.SetCharacteristicNotification(characteristic, true);
BluetoothGattDescriptor descriptor = new BluetoothGattDescriptor (Java.Util.UUID.FromString (BLEServices.CLIENT_CHARACTERISTIC_CONFIG), GattDescriptorPermission.Write | GattDescriptorPermission.Read);
characteristic.AddDescriptor (descriptor);
descriptor.SetValue (BluetoothGattDescriptor.EnableNotificationValue.ToArray ());
gatt.WriteDescriptor (descriptor);
_Adap.StartTimer ();
}
}
} else if (uuid.Equals (BLEServices.BatteryService.ToUpper())) {
_Adap.LogMessage ("BatteryService discovered");
foreach (BluetoothGattCharacteristic characteristic in service.Characteristics) {
string c_uuid = characteristic.Uuid.ToString ().ToUpper ();
_Adap.LogMessage (" BatteryService: " + c_uuid);
if (c_uuid.Equals (_Adap.useCharacteristic.ToUpper ())) {
_Adap.LogMessage (" reading batteryCharacteristic");
// This may only be reported when the battery level changes so get the level first by doing a read
gatt.ReadCharacteristic (characteristic);
//gatt.SetCharacteristicNotification (characteristic, true);
//BluetoothGattDescriptor descriptor = new BluetoothGattDescriptor (Java.Util.UUID.FromString (BLEServices.CLIENT_CHARACTERISTIC_CONFIG), GattDescriptorPermission.Write | GattDescriptorPermission.Read);
//characteristic.AddDescriptor (descriptor);
//descriptor.SetValue (BluetoothGattDescriptor.EnableNotificationValue.ToArray ());
//gatt.WriteDescriptor (descriptor);
}
}
} else if (uuid.Equals (BLEServices.DeviceInfoService.ToUpper())) {
_Adap.LogMessage ("DeviceInfoService discovered");
foreach (BluetoothGattCharacteristic characteristic in service.Characteristics) {
string c_uuid = characteristic.Uuid.ToString ().ToUpper ();
_Adap.LogMessage (" DeviceInfoService: " + c_uuid);
if (c_uuid.Equals (BLEServices.kModelNumberCharacteristicUuidString.ToUpper ())) {
//gatt.ReadCharacteristic (characteristic);
}
}
} else if (uuid.Equals (BLEServices.kHxM2CustomServiceUuidString.ToUpper())) {
_Adap.LogMessage ("HxM2CustomService discovered");
foreach (BluetoothGattCharacteristic characteristic in service.Characteristics) {
string c_uuid = characteristic.Uuid.ToString ().ToUpper ();
_Adap.LogMessage (" HxM2CustomCharacteristic: " + c_uuid);
if (c_uuid.Equals (_Adap.useCharacteristic.ToUpper ())) {
_Adap.LogMessage (" enabling HxM2 characteristic: "+_Adap.useCharacteristic);
gatt.SetCharacteristicNotification (characteristic, true);
BluetoothGattDescriptor descriptor = new BluetoothGattDescriptor (Java.Util.UUID.FromString (BLEServices.CLIENT_CHARACTERISTIC_CONFIG), GattDescriptorPermission.Write | GattDescriptorPermission.Read);
characteristic.AddDescriptor (descriptor);
descriptor.SetValue (BluetoothGattDescriptor.EnableNotificationValue.ToArray ());
gatt.WriteDescriptor (descriptor);
// Start a timer to make sure that we can recover if we never receive any data from the device
_Adap.StartTimer ();
}
}
} else {
_Adap.LogMessage ("Unknown Service "+uuid+" discovered");
}
}
}
Can anyone explain what the following lines are for
BluetoothGattDescriptor descriptor = new BluetoothGattDescriptor (Java.Util.UUID.FromString (BLEServices.CLIENT_CHARACTERISTIC_CONFIG), GattDescriptorPermission.Write | GattDescriptorPermission.Read);
characteristic.AddDescriptor (descriptor);
descriptor.SetValue (BluetoothGattDescriptor.EnableNotificationValue.ToArray ());
gatt.WriteDescriptor (descriptor);
Beside your found solution: Be aware, that you can't listen to an unlimited number of characteristics. The maximum is limited hardcoded in the android source to BTA_GATTC_NOTIF_REG_MAX
.
So your app should not rely on more than the maximum number of notifying characteristics of your minimum supported android version.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With