"Knowledge has no value unless you use it and share it"



Here at Greenfinch we were recently given the opportunity to work with a client on building a mobile application, the primary function of which was to communicate with a Bluetooth Low Energy (Bluetooth LE/BLE) device. The communication was simple, nothing more than sending a few bytes of data between the phone and the remote device.

We planned to build an app to target an Android device with a minimum OS version of 4.3 (API Level 18) which would be able to communicate over Bluetooth LE to another device.

This problem may seem simple, however, for the uninitiated in Bluetooth technology and the nuances of its implementation within Xamarin; there are many factors which need to be addressed.

Bluetooth LE:

Most of us are familiar with the Bluetooth communications protocol. More and more we are seeing small low power devices being integrated with Bluetooth allowing users to control and interface with these peripheral via their phone. Some of the most popular of these devices are Bluetooth headphones, health monitors, insulin pumps and even tracking devices.

One of the largest factors in the prevalence of small Bluetooth enabled devices is the advent of the Bluetooth LE protocol. Bluetooth LE has been designed to consume considerably less power than the classic Bluetooth protocol. Since about 2012 most mobile phone manufactures have provided devices capable of both Bluetooth classic and Bluetooth LE communication. This is made simpler as both the classic and LE protocols operate at the standard 2.4GHz frequency, meaning they can use the same antenna internally.

Under the Bluetooth Specifications, devices broadcast their MAC address as a unique identifier. Once two devices are connected, they are free to communicate over a wide variety of communication profiles. These profiles are identified on the device by standard UUID’s. Typically, these protocols will be configured on the device at the firmware level.

For example, a mobile phone may implement the A2DP protocol for streaming high quality audio. For Bluetooth LE, all communication happens over the Generic Attribute Profile (GATT). Using the GATT protocol, communication is achieved using a nested set of services and characteristics. A characteristic contains a single value and 0-n descriptors that describe the characteristic’s value. A characteristic can be thought of as a type, analogous to a class. Any device can have several services configured under the GATT profile with each service being capable of having many characteristics defined. Services are typically used to logically break up characteristics by area. Both characteristics and services are identified via UUID’s. In terms of communication, when reading and writing data on a BLE device, we directly address a specific characteristic. On the firmware side, device manufactures can specify where these characteristics point to.

For consistency, certain standards already exist for how Services and Characteristics should be set up for certain devices. For instance the Heart Rate service is standardised to have a UUID of value 0x180D. Further to this, this service is configured with 3 characteristics for reading and writing various data points. In this way, a manufacture of a device must set up its device to have this service with these characteristics. Software developers can access these specific addresses in their code to provide universal communication with devices. For more details on BLE and how to deal with it in native Android, see

Xamarin Integration:

When programming using Xamarin.Android & Xamarin.iOS, the developer has access to the native Bluetooth access methods, both of which (depending on the specific phones) gives the developer access to Bluetooth LE via the GATT protocol. However, when using Xamarin.Forms, there is currently no fully supported API provided by Xamarin for cross-platform Bluetooth LE communication.

Step in Xamarin.BluetoothLE . Written by tbrushwyler and provided on the MIT licence, Xamarin.BluetoothLE provides a very simple service layer to communicate over BLE. The source code for this library is available on GitHub and can be added to your Xamarin cross-platform project as a Nuget package.

Instructions on how to set up the BluetoothLE library can be found on the readme section of the GitHub repo here. Access to the functions of the library is achieved through the interface IAdapter. With IAdapter defined as a static variable (or interfaced out in a service layer) all of the function of the repo can be accessed through the interface. For instance, if we wish to scan for devices nearby, one would simply invoke the below:

IAdapter BluetoothAdapter;
// some setup code here

The above call will start scanning for nearby BLE devices. This is a void method, so to maintain a list of devices, a handle must be implemented in an event handler for DeviceDiscovered

private void DeviceDiscovered(object sender, DeviceDiscoveredEventArgs e)
    if (DeviceList.All(x => x.Id != e.Device.Id))

In the above case, e.Device is an object of type IDevice as defined in the Xamarin.BluetoothLE library. Once a device has been identified, we can achieve a connection to it with the code below:


As above, to see any output of this, the DeviceConnected event will need to be handled. Once a device is connected you can view all of its’ details through the IDevice interface. Within this definition it can be seen that there is a list of Services defined. These are all of the GATT profile services that are defined on the device. By default when a device is connected, this list will be blank. A scan for services must be done to populate this. In our implementation we did this by adding the scan to the DeviceConnected event as below.

private void BluetoothAdapterOnDeviceConnected(object sender, DeviceConnectionEventArgs deviceConnectionEventArgs)
    deviceConnectionEventArgs.Device.ServiceDiscovered += DeviceOnServiceDiscovered;

The above will populate the list of services on the device. In the same pattern as above, the list of characteristics in IService will initially be empty. Implementing the ServiceDiscovered below will then flesh out the list of service characteristics.

private void DeviceOnServiceDiscovered(object sender, ServiceDiscoveredEventArgs serviceDiscoveredEventArgs)

At this point we now have scanned for a device, connected to this device and via event handling, we have populated a list of GATT services and characteristics. The final part of our treatment here will be sending some data to a certain characteristic.

IDevice device = BluetoothAdapter.ConnectedDevices.First();

    device ,
    device .Services[4].Id.ToString(),
    device .Services[4].Characteristics[1].Uuid,
    new byte[] {10});

In the above code we have sent a single byte of data to the second characteristic of the fifth service of the device we are connected to. It is now up to the device to properly interpret this byte of data.

It is also possible to configure a read operation on a specific characteristic. It should also be noted that while some characteristics can be read from and written to, certain characteristics can only be read from or written to.