Reputation: 8988
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);
Upvotes: 11
Views: 3414
Reputation: 99
there is number of option re availble but i used to below logic to implement for this characteristics and it will realy working please try it:
public ConnectThread(BluetoothDevice device, BluetoothDeviceConnector deviceConnector)
{
_mmDevice = device;
BluetoothSocket tmp = null;
_deviceConnector = deviceConnector;
Log.Info(Tag, "calling device.createRfcommSocket with channel 1 ...");
try
{
//tmp = device.CreateRfcommSocketToServiceRecord(UUID.FromString("00001101-0000-1000-8000-00805F9B34FB"));
//tmp = device.CreateRfcommSocketToServiceRecord(device.GetUuids()[0].Uuid);
deviceConnector.BluetoothAdapter.CancelDiscovery();
var createRfcommSocket = JNIEnv.GetMethodID(device.Class.Handle, "createInsecureRfcommSocket", "(I)Landroid/bluetooth/BluetoothSocket;");
var socket = JNIEnv.CallObjectMethod(device.Handle, createRfcommSocket, new JValue(1));
tmp = GetObject<BluetoothSocket>(socket, JniHandleOwnership.TransferLocalRef);
var uuidList = device.GetUuids();
if (uuidList != null)
{
foreach (var uuid in uuidList)
{
try
{
tmp = device.CreateInsecureRfcommSocketToServiceRecord(uuid.Uuid);
tmp.Connect();
if (tmp.IsConnected)
break;
}
catch (Exception)
{
// ignored
}
}
}
Log.Info(Tag, "setting socket to result of createRfcommSocket");
}
catch (Exception e)
{
Log.Error(Tag, e.Message, e);
}
_mmSocket = tmp;
}
Upvotes: 0
Reputation: 14750
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.
Upvotes: 4