I'm developing Xamarin.Forms app that uses BLE communication with a specific BLE device that is in development in my company. The device needs bonding and can notify characteristics value changes.
I have BLE native implementations for iOS and Android smartphones. The BLE on iOS everything works: device scanning, service and characteristic discovery, reading/writing of characteristic and their notifications. The BLE on Android almost everything works: device scanning, service and characteristic discovery, reading/writing of characteristic. But I have problems with notifications.
This is a part of my BLE service, I think that all I need is implemented. Code of how I enable notifications:
[assembly: Dependency(typeof(MyApp.Droid.Services.BleManager))]
namespace MyApp.Droid.Services
{
public class BleManager : BluetoothGattCallback, IBleManager
{
private const string CCC_DESCRIPTOR_UUID = "00002902-0000-1000-8000-00805f9b34fb";
//...
public override void OnServicesDiscovered(BluetoothGatt gatt, [GeneratedEnum] GattStatus status)
{
this.discoverdServices = gatt.Services.ToList();
foreach (BluetoothGattService service in this.discoverdServices)
{
...
foreach (BluetoothGattCharacteristic characteristic in service.Characteristics)
{
...
// Enable BLE notifications
this.enableNotifications(gatt, characteristic);
}
}
}
private void enableNotifications(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic)
{
GattProperty properties = characteristic.Properties;
if ((properties & GattProperty.Notify) > 0)
{
gatt.SetCharacteristicNotification(characteristic, true);
BluetoothGattDescriptor descriptor = characteristic.GetDescriptor(UUID.FromString(CCC_DESCRIPTOR_UUID));
descriptor.SetValue(BluetoothGattDescriptor.EnableNotificationValue.ToArray());
// Create a task to write operation
Runnable runnable = new Runnable(() =>
{
try
{
bool writeResult = gatt.WriteDescriptor(descriptor);
if (writeResult)
Log.Debug(TAG, $"{characteristic.Uuid}: Writting descriptor.");
else
Log.Warn(TAG, $"{characteristic.Uuid}: Writting descriptor FAILED.");
}
catch (System.Exception exception)
{
Log.Error(TAG, $"ERROR: enableNotifications({characteristic.Uuid}): {exception.Message}");
}
});
// BLE commands queue to run tasks one by one
bool result;
lock (this.commandQueueSync)
{
result = this.commandQueue.Add(runnable);
}
if (result)
{
this.nextCommand();
}
else
{
Log.Error(TAG, $"{characteristic.Uuid}: ERROR. Could not enqueue write descriptor command.");
}
}
else
{
Log.Warn(TAG, $"{characteristic.Uuid}: Does not support notifications.");
}
}
public override void OnCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic)
{
Log.Debug(TAG, $"{characteristic.Uuid}: Notification received.");
this.processCharacteristicValue(characteristic, true);
}
}
}
In BLE device logs I can see how notification is sent and value read by the smartphone, but OnCharacteristicChanged is never fired. I tried in 2 Android smartphones one with Android 6.0 and another with Android 9.0 with the same result. I tried uninstalling the app and running again using Visual Studio and removing obj and debug folders, without success.
I'm using Microsoft Visual Studio Professional 2019 Version 16.10.4 and Xamarin.Forms 5.0.0.2083.