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:
- Scan for device
- Connect to device
- Discover services
- For each discovered service iterate through characteristics and enable the ones that are required
- Process each asynchronous callback event in the BLE callback
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);
1 Answers
Answers 1
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
.
- Android >= 4.3: 4 http://androidxref.com/4.3_r2.1/xref/external/bluetooth/bluedroid/bta/gatt/bta_gattc_int.h#301
- Android >= 4.4: 7 http://androidxref.com/4.4.4_r1/xref/external/bluetooth/bluedroid/bta/gatt/bta_gattc_int.h#333
- Android >= 5.0: 15 http://androidxref.com/5.0.0_r2/xref/external/bluetooth/bluedroid/bta/gatt/bta_gattc_int.h#345
So your app should not rely on more than the maximum number of notifying characteristics of your minimum supported android version.
0 comments:
Post a Comment