Sunday, March 22, 2015

Starting with Microsoft Band and Xamarin

Recently Xamarin released their API for Microsoft Band that works with Android, iOS and Windows Phone. It was a tough choice on what to play with before vacation;  a new Xamarin Forms preview that works with Windows Store and Windows Phone 8.1 was released as well as Xamarin Everywhere that hits Android Wear and Apple Phone. A complete overload of super cool stuff.

But ... last week I got a new Microsoft Band and you know, time to play.  First off, the Band isn't really a Smart Watch.  It's more a like a fitness device on steroids.  You can pull all kinds of sensor information out of it, you can also send notifications to it and play with it's appearance. What you can't really do is input information into the Band and have to do something on the phone. That is to say the band is about collecting sensor information and consuming information but not for inputting information like a "true" smart watch allows.

Xamarin has wrapped the Microsoft platform APIs, pretty much verbatim. One thing they have done which is nice is if the calls are asynchronous on Android, they have Task returning versions. However, like the Microsoft platform specific versions the APIs do not match from platform to platform so making cross platform code will still be challenging unless you wrap them in your own unified interface.  Xamarin has a nice page on the component store that explains the basics of the APIs which are pretty easy to use.  They can be found here:

https://components.xamarin.com/view/microsoft-band-sdk

With that in mind I set out to give this a try.  Since my Band is currently synchronized with an Android device I am working with the Android version of the API.  First I figured I'd try to add and then remove an icon from my Band that could receive notifications and messages.  I created a class to open and close the connection.

public class BandConnection : IDisposable
{
    private IBandClient bandClient;
    private Activity context;

    public BandConnection(Activity context)
    {
        this.context = context;
        var pairedBands = BandClientManager.Instance.GetPairedBands();

        if (pairedBands != null && pairedBands.Length >= 1)
        {
            bandClient = BandClientManager.Instance.Create(context, pairedBands[0]);
        }
    }

    public async Task ConnectAsync()
    {
        if (bandClient == null)
        {
            throw new InvalidOperationException("BandClient is not set");
        }
        await bandClient.ConnectTaskAsync();
    }

    public async void Dispose()
    {
        if (bandClient != null && bandClient.IsConnected)
        {
            await bandClient.DisconnectTaskAsync().ConfigureAwait(false);
        }
    }
}

The class just takes in the current activity and then gets the first band registered with the device. If you were making a "real" application it may be a good idea to make some sort of screen to choose what Band the user wanted to connect to if there were more than one.  The ConnectAsync method opens the connection to the Band.  As you can see I use the ConnectTaskAsync method of the BandClient instead of ConnectAsync.  All the asynchronous Android APIs seem to be wrapped up with Task returning operations with that naming convention.  When the class is disposed, if the bandClient is connected, the connection is closed.

I added a simple method to create a new tile on my band if there is room for one.

public async Task AddTileAsync(string tileId, string tileName, BandIcon largeIcon, BandIcon smallIcon)
{
    if (bandClient == null)
    {
        throw new InvalidOperationException("BandClient is not set");
    } 
    var tiles = await bandClient.TileManager.GetTilesTaskAsync().ConfigureAwait(false);
    var id = UUID.FromString(tileId);

    var spacesRemaining = await bandClient.TileManager.GetRemainingTileCapacityTaskAsync().ConfigureAwait(false);
    if (spacesRemaining > 0 && !tiles.Any(t => t.TileId.ToString() == tileId))
    {
        var tileBuilder = new BandTile.Builder(id, tileName, largeIcon);
        if (smallIcon != null)
        {
            tileBuilder.SetTileSmallIcon(smallIcon);
        }
        var tile = tileBuilder.Build();
        await bandClient.TileManager.AddTileTaskAsync(context, tile);
    }
}

I have added two images to my Android project, as per the API specs. One image is 24x24 and the other 48x48.  I create them and convert them into the BandIcon format. The following code is what I used to call the AddTileAsync method.

using (var bandConnection = new BandConnection(this))
{
    if (bandConnection.BandClient != null)
    {
        await bandConnection.ConnectAsync().ConfigureAwait(false);
        var smallIconBitmap = ((BitmapDrawable)Resources.GetDrawable(Resource.Drawable.PhoneFinderSmall)).Bitmap;
        var smallIcon = BandIcon.ToBandIcon(Bitmap.CreateScaledBitmap(smallIconBitmap, 24, 24, false));
        var largeIconBitmap = ((BitmapDrawable)Resources.GetDrawable(Resource.Drawable.PhoneFinderLarge)).Bitmap;
        var largeIcon = BandIcon.ToBandIcon(Bitmap.CreateScaledBitmap(largeIconBitmap, 48, 48, false));

        await bandConnection.AddTileAsync(BandConstants.TileId, "Band Test", largeIcon, smallIcon).ConfigureAwait(true);
    }
}

When using this code it automatically sinks up to the device.  The tile is identified by a unique identifier that I added as a constant to my code. When running it will first ask the user if they want to add the new tile to the Band. You can see my "awesome" abilities as an icon designer:


After choosing allow the band synchronizes the new tile onto the Band.


By scrolling the tiles on the band the newly added tile appears.


I then added a method to remove the tile I just added.

public async Task RemoveTileAsync(string tileId)
{
    if (bandClient == null)
    {
        throw new InvalidOperationException("BandClient is not set");
    } 
    var tiles = await bandClient.TileManager.GetTilesTaskAsync().ConfigureAwait(false);
    var id = UUID.FromString(tileId);
    if (tiles.Any(t => t.TileId.ToString() == tileId))
    {
        await bandClient.TileManager.RemoveTileTaskAsync(id).ConfigureAwait(false);
    }
}

This worked without incident and the tile from my band went away.

Sending a message to the band was also simple. The API reference contains the following description on the difference between a message and a dialog:

App notifications come in two flavors:
- Dialogs – dialog notifications are popups meant to quickly display information to the user. Once the user dismisses the dialog, the information contained therein does not persist on the Band.
- Messages – message notifications are sent and stored in a specific tile, and a tile can keep up to 8 messages at a time. Messages may display a dialog as well.

I added this method to my class to create a message:

public async Task ShowMessageAsync(string tileId, string title, string body, DateTime date, bool showMessage)
{
    if (bandClient == null)
    {
        throw new InvalidOperationException("BandClient is not set");
    }
    var id = UUID.FromString(tileId);
    await bandClient.NotificationManager.SendMessageTaskAsync(id, title, body, date, showMessage);
}

This method calls into my ShowMessageAsync method and gets the device location, converts it to an address and displays it to the user.

using (var bandConnection = new BandConnection(this))
{
    if (bandConnection.BandClient != null)
    {
        await bandConnection.ConnectAsync().ConfigureAwait(false);

        var geocoder = new Geocoder(this);
        var addressList = await geocoder.GetFromLocationAsync(_currentLocation.Latitude, _currentLocation.Longitude, 10).ConfigureAwait(false);

        var address = addressList.FirstOrDefault();
        if (address != null)
        {
            var deviceAddress = new StringBuilder();
            for (int i = 0; i < address.MaxAddressLineIndex; i++)
            {
                deviceAddress.Append(address.GetAddressLine(i))
                .AppendLine(",");
            }

            await bandConnection.ShowMessageAsync(BandConstants.TileId, 
                "Test Message", 
                string.Format("Current address: {0}", deviceAddress), 
                DateTime.Now, 
                true).ConfigureAwait(true);
        }
    }       
}

The message comes across to the band as expected.


Additionally, as expected, a message indicator appears with our tile stating that one new message was received.


When selecting the tile the message appears fully (I blocked out my address).


Sending a dialog is similarly easy.  But as this test indicates the amount of text that can be displayed in the dialog is limited and there is no down button (see more) as with the message.  Dialogs should only be used for very short notifications.

public async Task ShowDialogAsync(string tileId, string title, string body)
{
    if (bandClient == null)
    {
        throw new InvalidOperationException("BandClient is not set");
    }
    var id = UUID.FromString(tileId);
    await bandClient.NotificationManager.ShowDialogTaskAsync(id, title, body);
}

When sending this over it shows up as a popup but does not add to the message counter or add to the message history. As the API documentation stated, the dialog is not retained.


That's it for my first go.  Vibrating the band was similarly easy. Next I'll poke around at getting data from the Band and perhaps customizing its appearance.  Generally I was pleased at how easy it was to work with but cross platform applications may want to create a unified interface.

Tuesday, March 3, 2015

Direct casting vs. As and Linq Single, SingleOrDefault, First, FirstOrDefault

There are tons of articles on these two topics but I still see it so many times I'm putting out a quick reminder.

This:

var someVariable = someOtherVariable as SomeType;

Or this:

var someVariable = (SomeType)someOtherVariable;

I come across people doing the first when they should be direct casting (the second) all the time in code reviews.  When I come across the first the first thing I look for, somewhere very soon after in the code, is a null check.  Why? because using the syntax of the first means that you expect that someOtherVariable may be not castable to SomeType and when that happens someVariable will be set to null.  That is to say that since it may be something other than SomeType, you need to handle that case in code.

If however, someOtherVariable should always have at value that is castable to SomeType and anything else is a logic error somewhere in the code, then you should be using direst casting.  Direct casting will throw an exception right then and there if it is not SomeType and that's what you want. Why?  Because somewhere in your code you have a logic error and you want to find out about it as soon as possible.  Pretty simple to remember.

OK, what are the differences between these Linq statements:

var someVariable = someOtherVariable.First(r => r.SomeValue == "value");

var someVariable = someOtherVariable.FirstOrDefault(r => r.SomeValue == "value");

var someVariable = someOtherVariable.Single(r => r.SomeValue == "value");

var someVariable = someOtherVariable.SingleOrDefault(r => r.SomeValue == "value");

Here is my easy way to remember:

First: ( 1 .. n) It is valid to have one or more results and you want/get the first.  If there are no results that is a logic error and should throw an exception.

FirstOrDefault: ( 0 .. n) It is valid to have zero, one or more valid results and you want/get the first.  Generally if you have no valid result someVariable will be set to null, similar to the "as" syntax above.

Single: ( 1 .. 1 ) It is valid to have one and only one result.  Anything else (zero or more than one) is considered a logic error and will throw an exception.  Great for unique Ids when you know the record should be in the collection

SingleOrDefault: ( 0 .. 1): There should be zero or one result, more than one matching result will throw an exception.  Generally if you have no valid result someVariable will be set to null, similar to the "as" syntax above.  Great for unique Ids when you don't know if the record has been added to the collection and if it isn't in there, you need to add it.

I see these misused all the time too, particularly people favoring FirstOrDefault.  When I've asked them about it misuse usually comes from not understanding the statements or aversion to throwing an exception (i.e they think to themselves, but what if there are no, or many results).

The aversion to throwing an exception in these cases is wrong headed thinking.  Yes, exceptions that get to the user are bad, but logic errors can be similarly bad.  Even worse is logic errors that you don't catch immediately that lead to exceptions later on and now you have the unenviable task of trying to trace back and figure out many lines of code before your variable was set to null in a situation that never should have happened and you didn't handle.

Using the "as" syntax or FirstOrDefault out of a desire to avoid exceptions is a bad practice similar to swallowing exceptions.  Don't do it.  Fail right away and you as the developer will likely find the problem, and if you don't QA has a better chance to than if you simply don't throw and exception and keep going.  By swallow the problem by using "as" or FirstOrDefault you increases the chance that the person finding an issue will be the end user and you will likely have a harder time tracking down the problem and some egg on your face.