I was quite surprised when I started digging into getting a Bluetooth BLE device connected to my Xamarin/iOS application to find myself looking at a bunch of fairly uninspiring nuget packages. Bluetooth is standard and common, and I would have expected Xamarin to have at least some basic support by now, perhaps in Xamarin.Essentials.
The nuget packages I found all seemed to be either old or to carry way too much baggage. To go through a couple of examples:
The promising Plugin.BluetoothLE has a big message saying that it is migrating into the Shiny framework. Throughout my whole project, I have made a big effort to avoid frameworks that force you to do things a certain way and I don't really want to start now.
XamarinBluetoothLE also looked promising but I can't get any of it to build and so far am struggling to figure out the best way of getting it into my project without unwanted dependencies across my projects.
I guess it will be too late for me but is Xamarin planning any Bluetooth support? Or can anyone recommend a lightweight Bluetooth library?
Any advice would be very welcome.
Kind wishes - Patrick
I guess it will be too late for me but is Xamarin planning any Bluetooth support?
Yes, you can see following github thread, jamesmontemagno asks for the features for xamarin bluetooth support.
https://github.com/xamarin/Essentials/issues/242
Before the xamarin ble offical api release, I think xamarin-bluetooth-le is a good choice.
so far am struggling to figure out the best way of getting it into my project without unwanted dependencies across my projects.
You can create same demo to test this ble plugin. Then get it into your project.
In answer to my own question above, I have worked out how to do this. This may not be the best method but does what is required.
The following code uses nuget package https://github.com/xabre/xamarin-bluetooth-le to search for nearby BluetoothLE heart-rate devices. Note that the code is nowhere near complete; it just shows the main steps. And it is important always to do something with exceptions with Bluetooth because you will get some.
// These are the main entry points to the API. Plugin.BLE.Abstractions.Contracts.IBluetoothLE BLE; Plugin.BLE.Abstractions.Contracts.IAdapter BLEAdapter; // These event handlers need to be attached. BLE.StateChanged += BLE_OnStateChanged; BLEAdapter.ScanTimeoutElapsed += BLEAdapter_ScanTimeoutElapsed; BLEAdapter.DeviceDiscovered += BLEAdapter_OnDeviceDiscovered; BLEAdapter.DeviceDisconnected += BLEAdapter_OnDeviceDisconnected; BLEAdapter.DeviceConnectionLost += BLEAdapter_OnDeviceConnectionLost; // My own simple class to hold records detailing discovered devices. class BLEDeviceRecord { public BLEDeviceRecord( IDevice device ) { Device = device; } public IDevice Device { get; private set; } public Guid UniqueId => Device.Id; public bool IsConnected => Device.State == DeviceState.Connected; public int Rssi => Device.Rssi; public string Name => Device.Name; } // A collection of the discovered devices. ObservableCollection<BLEDeviceRecord> BluetoothDevices { get; private set; } = new ObservableCollection<BLEDeviceRecord>(); // Start the scan; results come via the event handlers. void BuildListOfBluetoothDevices() { BluetoothDevices.Clear(); CancellationTokenSource cts = new CancellationTokenSource(); BLEAdapter.ScanMode = ScanMode.LowLatency; await BLEAdapter.StartScanningForDevicesAsync( cts.Token ); } // Once you have devices in the above collection, look for the heart-rate ones like this. void SearchForHeartRateCharacteristic() { // Obtain this from the Bluetooth GATT Specifications: const int HeartRateUuid = 0x2A37; Guid heartRateMeasurementGuid = HeartRateUuid.UuidFromPartial(); foreach( IService service in services ) { var characteristics = await service.GetCharacteristicsAsync(); foreach( ICharacteristic characteristic in characteristics ) { if( characteristic.Id == heartRateGuid ) { // The current IService contains an ICharacteristic that is a heart-rate measurement. } } } }
The Bluetooth GATT Specifications can be found here: [https://bluetooth.com/specifications/gatt/characteristics/]( GATT
Characteristics)
This could easily be generalised to search for any other Characteristic in the Bluetooth Specification.
Hope it helps someone.
Answers
Yes, you can see following github thread, jamesmontemagno asks for the features for xamarin bluetooth support.
https://github.com/xamarin/Essentials/issues/242
Before the xamarin ble offical api release, I think xamarin-bluetooth-le is a good choice.
You can create same demo to test this ble plugin. Then get it into your project.
@LeonLu Yes, xamarin-bluetooth-le does indeed look like an excellent choice. It's a shame they chose to tangle their example code with MvvmCross, a framework I am not using, but otherwise I am making good progress with it so far.
You have saved me a lot of time messing about trying to understand the other packages I had found, so thank you for the suggestion!
@LeonLu
I'm doing okay with the xamarin-bluetooth-le package that you recommended but I seem to have hit a chicken-or-egg situation. I am wanting to get a connected heart-rate service. I can get a specific Service using its GUID by calling...
var service = await connectedDevice.GetServiceAsync(Guid.Parse("ffe0ecd2-3d16-4f8d-90de-e89e7fc396a5"));
Or I can get all services by calling...
var services = await connectedDevice.GetServicesAsync();
I can then follow exactly the same pattern for characteristics - either get all Characteristics or pick a specific one by using its GUID.
In the example code for xamarin-bluetooth-le, there are classes for KnownServices and KnownCharacteristics. The problem is that these lists are private to their respective classes and only way to do a look-up is by passing the GUID.
I'm obviously missing something but this seems like the wrong way round. What I need is some way to say something like this...
var BluetoothAdapter.FindAllServicesThatContainCharacteristic( KnownCharacteristic.HeartRate );
This is obviously not real code but hopefully you can see what I am getting at.
How do I find out these mysterious GUIDs?
In answer to my own question above, I have worked out how to do this. This may not be the best method but does what is required.
The following code uses nuget package https://github.com/xabre/xamarin-bluetooth-le to search for nearby BluetoothLE heart-rate devices. Note that the code is nowhere near complete; it just shows the main steps. And it is important always to do something with exceptions with Bluetooth because you will get some.
The Bluetooth GATT Specifications can be found here: [https://bluetooth.com/specifications/gatt/characteristics/]( GATT
Characteristics)
This could easily be generalised to search for any other Characteristic in the Bluetooth Specification.
Hope it helps someone.