James Montemagno
James Montemagno

Live, Love, Bike, and Code.

Live, Love, Bike, and Code

Share


Tags


James Montemagno

Building, testing, & shipping My Cadence for iOS in less than a week

My holiday hacking came early this year when I decided to build my own DIY spin bike. Soon, after a few rides, my mind started to swirl with app ideas of how to improve my ride. Then when Apple released Apple Fitness+ without support for displaying cadence information from sensors I knew I had to build an app. That app is My Cadence, which connects to a small cadence sensor and displays the current cadence. It is actually packed full of awesome features including custom themes, in-app purchases, store reviews, and more! Best of all it only took me around 12 hours to develop, test, and ship during the last week since I started it. So, today I want to walk through all of the features I put in and how I developed them.

Xamarin.Forms 5

With Xamarin.Forms 5 nearing stable release it was the first thing I updated to when I created the project. I leveraged a lot of new features such as embedded fonts, App Themes for Light/Dark mode, gradient brushes, geometry clipping, and a bunch more! I love how easy it is to react to the mode change on the user's device with a simple line of code.

 <Label Text="The following sensors have been tested with My Cadence."
        TextColor="{AppThemeBinding Dark=White, Light=Black}"/>

Here is a bit of the app themes in action:

Bluetooth

The cadence sensor broadcast over Bluetooth Low Energy. This was actually the first time that I had worked with Bluetooth and I leveraged the Plugin.BLE library to easily detect, connect, and read data from the device. I may upgrade to Shiny in the future, but this was the first one I grabbed and it has been working well.

I fell in love so much with Bluetooth that Frank and I recorded a full Merge Conflict podcast on it!

In-app Purchases

I decided to add a "Pro" mode into the application at the last minute. My thought was that the entire app would be free without restrictions, but to help support the app a user could upgrade to "Pro" to unlock custom theming in the app. I leveraged my InAppBilling plugin and had the upgraded implemented in about 30 minutes. Here is the code from the app if you are interested in how easy it is to implement.

const string productId = "pro";

async Task PurchasePro()
{
    if (IsBusy)
        return;

    IsBusy = true;

    try
    {
        if(Connectivity.NetworkAccess != NetworkAccess.Internet)
        {
            await DisplayAlert("No internet", "Please check internet connection and try purchase again.", "OK");
            return;
        }

        var connected = await CrossInAppBilling.Current.ConnectAsync();

        if (!connected)
        {
            await DisplayAlert("Unable to Connect", "Unable to connect to the app store, check your internet connectivity and try again.", "OK");
            return;
        }

        //check purchases
        var purchase = await CrossInAppBilling.Current.PurchaseAsync(productId, ItemType.InAppPurchase);

        if (purchase == null)
        {
            return;
        }
        else if (purchase.State == PurchaseState.Purchased)
        {
            Settings.IsPro = true;
            SetPro();
            return;
        }

        throw new InAppBillingPurchaseException(PurchaseError.GeneralError);

    }
    catch (InAppBillingPurchaseException purchaseEx)
    {
        var message = string.Empty;
        switch (purchaseEx.PurchaseError)
        {
            // figureout error message
        }

        if (string.IsNullOrWhiteSpace(message))
            return;

        Console.WriteLine("Issue connecting: " + purchaseEx);
        await DisplayAlert("Uh Oh!", message, "OK");
    }
    catch (Exception ex)
    {
        // Handle Exception
    }
    finally
    {
        await CrossInAppBilling.Current.DisconnectAsync();
        IsBusy = false;
    }
}

Store Reviews

On thing that I always forget to put in my app is a way to prompt the user to review the application. Another one of my random plugins comes in to save the day, the Store Review Plugin! In the settings screen I added a button to review the app:

void TextCellReview_Tapped(System.Object sender, System.EventArgs e)
{
    CrossStoreReview.Current.OpenStoreReviewPage("1545730360");
}

Then I also decided to do a prompt for the user to review after they use the app 5 times successfully.

var count = Settings.Usage;
count++;
if(count == 5)
{
    CrossStoreReview.Current.RequestReview(false);
}
Settings.Usage = count;

Custom Controls

I surprisingly I only used 1 custom control in the entire app and it was available directly on NuGet! This control was an advanced color picker and I landed on one built by Dalton Spillman. It is fantastic as it allows full fidelity of color selection and has a built in ViewModel that works great for getting and setting colors.

You can find the code to the control on GitHub.

Xamarin.Essentials

Wow, Xamarin.Essentials continues to make me super productive over and over and over again. I leveraged:

Every time I thought I was going to need to write some custom code Xamarin.Essetials was there.

CI & CD

In one of my late night code sessions I decided to setup App Center Build/Distribute on the app and I am so glad I did. It took seconds to setup and I had things automatically building, versioning, and distributing to TestFlight in under 10 minutes!

App Center Build & Distribute

More!

There is a lot more that went into this application outside of just the code. I generated a full website and app screenshots from http://apptoolkit.io/, created an app icon from EasyAppIcon.com, & had some amazing tester on Twitter using TestFlight.  

Thanks Dan for Testing!

Available Now & OSS Code Soon

It is now available in the App Store completely for free! Soon the app is coming to Android as well as I just need to tweak a few Android specific settings and get it through the review process.

If you are looking to get into spinning checkout my full blog on building a DIY spin bike.

Finally, I do plan on putting the full source code online, so be sure to check back when I write up a blog on it.

Copyright © James Montemagno 2020 All rights reserved. Privacy Policy

View Comments