Xamarin Bluetooth LE: Scan for devices iOS Edition

Posted on Leave a commentPosted in Uncategorized

For Android see Xamarin Bluetooth LE: Scan for devices Android Edition

Proceeding with iOS and create the same “scan for devices” app. This time I am skipping the boilerplate code of buttons and events and such. Just cut to the chase with the BluetoothEnumerationService

    public class BluetoothEnumerationService
    {
        private readonly CBCentralManager _centralManager;
        private readonly Dictionary<string, CBPeripheral> _devices = new Dictionary<string, CBPeripheral>();

        public BluetoothEnumerationService()
        {
            _centralManager = new CBCentralManager(new MyCentralManagerDelegate(_devices), DispatchQueue.CurrentQueue);    
        }

        public async Task<IEnumerable<CBPeripheral>> GetDevicesAsync()
        {
            if (_centralManager.State != CBCentralManagerState.PoweredOn)
                return Enumerable.Empty<CBPeripheral>();

            _centralManager.ScanForPeripherals((CBUUID[])null); // #NoFilter
            await Task.Delay(200);
            _centralManager.StopScan();
            return _devices.Values;
        }
    }

Simple stuff here. You need a new instance of CBCentralManager. The MyCentralManagerDelegate is what’s actually going to give you your devices (and it’s coming up). Like before, I just want to check if the Bluetooth features are turned on and if not, return an empty enumeration of CBPeripheral.

Then just start/wait/stop the scan and through the magic of MyCentralManagerDelegate, _devices.Values is going to have CBPeripherals in it if they were found during scan.

If you were going to do any filtering of devices, that’s on line 16 above.

    public class MyCentralManagerDelegate : CBCentralManagerDelegate
    {
        private readonly Dictionary<string, CBPeripheral> _devices;

        public MyCentralManagerDelegate(Dictionary<string, CBPeripheral> devices)
        {
            _devices = devices;
        }

        public override void DiscoveredPeripheral(CBCentralManager central, CBPeripheral peripheral, NSDictionary advertisementData, NSNumber receivedSignalStrengthIndication)
        {
            _devices[peripheral.Identifier.AsString()] = peripheral;
        }

        public override void UpdatedState(CBCentralManager cbCentralManager)
        {
            // Here you can perform actions when the bluetooth state changes on/off/resetting...
        }
    }

You could probably imagine what the MyCentralManagerDelegate class was for before it was written, but there it’s spelled out. You get a call to DiscoveredPeripheral when a new peripheral is discovered. I’m using the same dictionary scheme to make sure I get unique devices only in my lists.

For context the ViewController is here:

    public partial class ViewController : UIViewController
    {
        private readonly BluetoothEnumerationService _bluetoothEnumerationService;

        public ViewController(IntPtr handle) : base(handle)
        {
            _bluetoothEnumerationService = new BluetoothEnumerationService();
        }

        async partial void startScanning(UIButton sender)
        {
            var devices = await _bluetoothEnumerationService.GetDevicesAsync();
            bleDeviceList.Source = new TableSource(devices.Select(x => x.Name).ToList());
            bleDeviceList.ReloadData();
        }
    }

Xamarin Bluetooth LE: Scan for devices Android Edition

Posted on Leave a commentPosted in Uncategorized

For iOS see Xamarin Bluetooth LE: Scan for devices iOS Edition

I was working through a Xamarin Forms PCL app recently and had to implement GATT communications on UWP, Android and iOS applications.

Here’s some steps and code you need for the first part of that task: Scan for devices on Android

    1. Make sure you have permissions set up. You need BluetoothAdmin and Bluetooth
      required-permissions
    2. Drop a listview in your axml file and derive the activity from ListActivity. You will have to change the id attribute of the ListView to android:id=”@android:id/list”
    3. I just created a new Android SingleView project for demonstration
          [Activity(Label = "AndroidGATT", MainLauncher = true, Icon = "@drawable/icon")]
          public class MainActivity : ListActivity
          {
              private BluetoothEnumerationService _bluetoothEnumerationService;
              protected override void OnCreate(Bundle bundle)
              {
                  base.OnCreate(bundle);
      
                  // Set our view from the "main" layout resource
                  SetContentView(Resource.Layout.Main);
      
                  // Get our button from the layout resource,
                  // and attach an event to it
                  var button = FindViewById<Button>(Resource.Id.MyButton);
      
                  _bluetoothEnumerationService = new BluetoothEnumerationService();
                  
                  button.Click += async delegate
                  {
                      ListAdapter = new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, new[] {"Searching..."});
                      var devices = await _bluetoothEnumerationService.GetDevicesAsync();
                      ListAdapter = new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, devices.Select(x => x.Name).ToList());
                  };
              }
          }
      

      Note that MainActivity is derived from ListActivity instead of Activity

    4. Now you can implement the scanner service
      public class BluetoothEnumerationService
          {
              private readonly BluetoothAdapter _bluetoothAdapter;
              private readonly ScanCallback _androidScanCallback;
              private readonly Dictionary<string, BluetoothDevice> _devices = new Dictionary<string, BluetoothDevice>();
      
              public BluetoothEnumerationService()
              {
                  var bluetoothManager = (BluetoothManager) Application.Context.GetSystemService(Context.BluetoothService);
                  _androidScanCallback = new MyAndroidScanCallback(_devices);
                  _bluetoothAdapter = bluetoothManager.Adapter;
              }
      
              public async Task<IEnumerable<BluetoothDevice>> GetDevicesAsync()
              {
                  if (!_bluetoothAdapter.IsEnabled)
                      return _devices.Values;
      
                  _bluetoothAdapter.BluetoothLeScanner.StartScan(_androidScanCallback);
                  await Task.Delay(200);
                  _bluetoothAdapter.BluetoothLeScanner.StopScan(_androidScanCallback);
                  return _devices.Values;
              }
          }
      
          public class MyAndroidScanCallback : ScanCallback
          {
              private readonly Dictionary<string, BluetoothDevice> _bluetoothDevices;
      
              public MyAndroidScanCallback(Dictionary<string, BluetoothDevice> devices)
              {
                  _bluetoothDevices = devices;
              }
      
              public override void OnScanResult(ScanCallbackType callbackType, ScanResult result)
              {
                  base.OnScanResult(callbackType, result);
                  _bluetoothDevices[result.Device.Address] = result.Device;
              }
          }
      

      First get hold of the Android adapter in lines 9-11 and create your custom AndroidScanCallback. In the callback I want to add an item to the devices dictionary when they are discovered. Since I’ll get tons of hits on each one, I used the dictionary to make sure that I only have one device per Bluetooth Address.

Line 19 in the BluetoothEnumerationService class is where you can add some filtering and scanner settings. For simplicity, this scanner is going to find all the Bluetooth LE devices that are advertising.
Line 20 is a short delay while the scanner works. I don’t know what the optimal value is. In this scenario, I’m assuming that the device is already on and broadcasting because the scan only lasts 200ms.

Android BLE enumeration

Certify vs. No

Posted on Leave a commentPosted in Uncategorized

I was on the fence about whether or not to join Xamarin University and go for mobile certification there.

As is my wont, I did meticulous research on certification vs. no. Not just about Xamarin Mobile development, but in a more general sense.

What I found was that the voices on the side of not certifying were the most plentiful. Most of the article and blog content was of the type: “it’s about what you can do at work, not what a piece of paper says”.

The problem with that is, you have no idea what the position of the writer is. If they are in a job that they already do that kind of work, then of course certification is probably not going to get them much. Most certification is not a replacement for experience.

As a contractor, I feel my position is a little different. I can use the certification as a marketing tool. Splash that on my web page, on my business cards, certifications fit nicely into an elevator pitch.