Distributing Apps For Testing

When testing apps, I generally use a combination of 3 tools for distribution. It’s important to understand the strengths and weaknesses of the various available tools to easily onboard testers and gather feedback.

App Center

I’ll only be touching on App Center Distribute, none of the other features. I would say that it’s worthwhile to use Microsoft App Center for the distribution features alone. There are other valuable features in the App Center product which I will likely cover in future articles.

App Center Releases

App Center Distribute is overall a fantastic, robust tool for distribution. It’s great for small test groups and power users.

  • Audience:
    • Internal QA teams
    • Internal stakeholders
    • Small groups of external testers
    • iOS (and iPadOS – sigh) and Android
  • Pros:
    • Free, don’t need Apple’s blessing to push out changes
    • Android apps are extremely easy to manage
    • Multiple versions available to test at the same time (this is big)
  • Cons:
    • Uses iOS ad-hoc distribution. This means all devices you want to use to test need to be registered through Apple, and the app is packaged with a list of the registered devices and on install iOS checks to make sure the device you’re installing to is on the list. Even though you can register devices and re-package apps through App Center (really fastlane under the hood), it’s still a cumbersome process that involves manual steps from testers and admins/developers.
    • Android users need to toggle the “Allow installation of apps from unknown sources” option in settings.

TestFlight (iOS only)

TestFlight was once an independent startup working to tackle the problem of distributing apps for both Android and iOS. Apple purchased TestFlight in early 2014 and quickly removed Android support.

  • Audience:
    • iPhone/iPad users
    • Large test groups
    • Public beta testers
  • Pros:
    • Good end-user experience, simple to install test apps
  • Cons
    • Requires a separate TestFlight app
    • App approval required for beta testing
    • Can only test one version at a time
    • Builds expire after 90 days

Google Play Store (Android only)

The Google Play Store added testing distribution quite some time ago and has continued to mature the workflow.

  • Audience:
    • Android users
    • Large test groups
    • Public beta testers
  • Pros:
    • Test apps are installed through the Google Play Store (like production)
  • Cons:
    • Can only test one version at a time
    • This might be a personal thing, but I find the Google Play Publishing portal very cumbersome to use.

Conclusion

You mileage will vary with each of these tools. I recommend starting with App Center and shifting to TestFlight and the Google Play testing tracks as you move closer to a production release.

Version Checking for Xamarin Apps

The Problem

One of the biggest differences between web apps and mobile apps is the decentralized nature of mobile apps. Instead of pushing updates into servers or the cloud, we instead push the updates through the App Store and Google Play Store where the updates are pulled down by our users.

The fact that updates are not guaranteed can create some work for us as developers, particularly when we need to make a breaking change to our backend. Ideally, we want to support backwards compatibility where we can, but it’s not always possible or realistic.

The Solution

In order to avoid frustration, a flurry of support calls and having to react to the situation, you can use a simple force update flow to inform your users that their app needs to be updated.

Before we get to the code, let’s break this down into the steps of the force update flow:

  1. The app sends a request which includes the app version to the API.
  2. The API processes the request, comparing the app’s version from the request to a minimum version defined in the API configuration.
  3. If the app’s version is less than the minimum required version, the server responds with 400 Bad Request and some information about the API version and minimum client version.
  4. The app handles the response and navigates to a modal page with more information.

You’re likely tired of my rambling, let’s get to the code!

Send The App Version to the API

We’re going to extend DelegatingHandler which we will pass to our HttpClient constructor, this allows us to intercept requests/responses and do some processing. Incidentally, this is also what HttpTracer does.

Pretty straightforward, we override SendAsync and intercept the request in our ProcessRequest method. This naming convention is borrowed from MessageProcessingHandler, another BCL class, I wasn’t able to user MessageProcessingHandler because we need our processing methods to be async. Now, I know what you’re thinking, “Dylan’s an idiot, he’s not even doing any asynchronous processing”, this is true, I’m not, but I do need it to get the response content and I want the method signatures to be consistent.

Our request is augmented to include a “client-version” header, this is defined in a common library where we keep a few pieces of code which are used in the API and the client. The version value is pulled from Xamarin.Essentials.VersionTracking. The version value is the same as you would see on the stores.

Process the Request on the API

There’s a few moving parts with this. Let’s look at this from the bottom of our dependency chain up and we’ll address registration last.

We all love our interfaces, we start by defining IVersionCheckService with two simple members.

  • PerformVersionCheck – this looks at the request headers, if we have a “client-version” header specified and it’s less than the MinimumClientVersion defined in our config, we throw a ClientVersionNotSupportedException.
  • MinimumClientVersion – this exposes the configuration value for usage elsewhere if required.

Now we call our VersionCheckService from an implementation of IActionFilter, this makes it simple to decorate our controllers to specify where we’re going to enforce the version check. Note that we’re using ASP.NET Core’s build in DI which means our attribute definition looks slightly different.

Process the Response on the API

Here’s our ClientVersionNotSupportedException and our Startup registration.

There’s a bit of magic to the serializing in ClientVersionNotSupportedException to make sure we can get the information out that we need.

We’re doing a few things in Startup.cs:

  • Lines 34-36: we’re registering our configuration, service and filter.
  • Lines 42-46: we setup a custom exception handler
  • Lines: 62-71: we handle our ClientVersionNotSupportedException

Process the Response on the Client

Back to our VersionCheckHandler to handle the exception in the response.

This is our final handler, see how I have added the ProcessResponse method which takes care of deserializing our ClientVersionNotSupportedException and throwing it.

Finally, we catch the ClientVersionNotSupportedException on lines 42 & 65 and navigate to a modal page informing the user that they need to update.

Conclusion

Blogging is hard. This took a lot of time and effort, the write up started with a longer version which accounts for offline scenarios. I’ll get to that later, this is enough to digest for now.

I really hope someone finds this useful! Please let me know if you have any feedback!

The code is here if you would like to run it up: Xamarin App Version Checking

Xamarin Quick Tip: EF.Core

If you are using EF.Core in Xamarin, the Xamarin.iOS linker needs to exclude various BCL classes in order to properly function.

Include this Linker.xml in your Xamarin.iOS head project to ensure the linker doesn’t remove any of the required dependencies!

https://gist.github.com/dylanberry/081ba2ffb55e37d5d05f7588be3178cc

HttpTracer v2.0

TLDR: Add HttpTracer to your project and pass a new instance to HttpClient for Fiddler-like http audit/debug capabilities.

What is HttpTracer?

About a year ago, Daniel John Causer, Chase Florell and I decided that some code that I was using to inspect HTTP traffic in my Xamarin apps should be an open source library.

The code was simple enough, a simple DelegatingHandler that you can pass into your HttpClient instance and it would print your app’s http traffic to your debug output. The output would contain the method, url, headers and content for both requests and responses.

After working through issues with the initial implementation and the learning curve with releasing a library to the general public via nuget (this was a first for Daniel and me), we at last had a solid library that worked as advertised out of the box.

Evolution

We were aware that the library wasn’t perfect and shipping it in a production app bordered on irresponsible. Logging all http traffic from your app is a heavy operation and a potential security risk. I decided to build out a feature that would fine grain control over what was captured and logged.

I started by building a spec: https://github.com/BSiLabs/HttpTracer/issues/34#issue-421978732

After some excellent suggestions from Allan Ritchie and Chase Florell, I built out the verbosity features and published a package to Myget. From there, I was able to test with several real apps to ensure that the library was functioning properly. I fixed my issues, republished, retested and pushed HttpTracer 2.0 on Nuget!

Future

Working on this project has been an excellent learning experience. Owning and maintaining my first open source application has taught me many things about testing, designing libraries for public consumption, nuget packaging, multi-targeting and more.

We are now discussing some wishlist items, like being able to tie into some of the existing logger interfaces that are a part of .NET (currently you would need an adapter class).

I also took some time to try the framework with Blazor. It was a great learning experience as well, being able to work with .NET Core 3.0 for the first time and WASM too! After some stumbles, I was finally able to get HttpTracer working in a small Blazor app, it’s less useful in the context of WASM since you can just use the network tab in developer tools to inspect requests, but it’s still really cool to see the library working with a cutting edge platform!

Check out the gist for Blazor here: https://gist.github.com/dylanberry/8cf04c591ebf81f46a197855316012fe

Thanks for reading and if you have any feedback on HttpTracer, please let me know!

Xamarin Dev Tools – Hello, I’m a Mac. And I’m a PC.

Xamarin Development Tools

Part 1 – Windows vs. macOS

I’m going to speak from experience here because it’s been a long road. The first 2 years I worked on Xamarin and mobile projects, I used a Windows machine, it was a decent laptop with an Intel Core i7 chip, 16 GB of ram and an SSD, not bad, right? Well, for any other task, yeah, it was perfect, but for Xamarin, it struggled. Loading solutions was slow and deploying/debugging with Android emulators was glacial. Debugging iOS was a huge pain; yes, Visual Studio has the ability to connect to a Mac build agent, but it’s unreliable, buggy and requires an exact version match. Too many moving parts.

I took the plunge about 2 years ago and began using a MacBook Pro full time and let me tell you, it has been a huge improvement. Visual Studio for Mac is fast and lightweight, you can run/debug iOS and Android on one piece of hardware and it’s really fast to deploy to the iOS Simulator. Switching provided a massive boost to my development productivity.

Furthermore, I didn’t even have to turn my back on Windows, I can dual boot with Bootcamp and run Windows inside a VM using Parallels. The best of both worlds!

With almost 3 years of full time macOS use behind me, here are my observations/recommendations to help ease the transition from Windows/PC to Mac.

macOS for Xamarin Developers

Hardware/Drivers

Hardware – I have a MacBook Pro (Retina, 15-inch, Mid 2015). I ordered this laptop in early 2016 when the newer models were announced. Looking at the benchmarks at the time, any performance benefits from the marginal CPU upgrade in the new models were far outweighed by the cons (lack of connectivity ports, no dedicated power port, bad keyboard). No regrets, this machine is a workhorse, decently fast, good battery life and handles a VM nicely.

Peripherals – In my home office, I use a DisplayLink USB 3.0 dual HD dock to drive twin 24″ 1920×1200 monitors that flank my laptop stand. This dock always worked wonderfully with my Windows machines, but was always a bit finnicky with my Mac and had much higher latency than plugging in the display directly. Since 10.13 “High Sierra” I have abandoned the display capabilities of the dock completely. High Sierra implemented changes which broke the dock’s capabilities. I now plug in both monitors, one to HDMI and one to mini DisplayPort. Frustrating to manage all the cords/connections, but the displays have lower latency with a direct connection.

My home office setup.

Networking – macOS has no concept of a metered connection like Windows or Android. If you spend any amount of time using a portable hotspot/tethering/limited wifi, you will want to grab TripMode. If left unchecked, your Mac (and it’s applications) will treat all your connections like an unlimited, high-speed link which will cost you time and money.

Multitasking

Virtual Desktops – “Spaces” work relatively well. There tends to be a few bugs and hiccups, but they’re certainly handy.

Window Management – You’re going to miss Window’s snapping features more than you will ever know. Get a replacement, I recommend Magnet. Windows users will also need to get used to the fact that the “Maximize” doesn’t exist and the green button in the top left of the application title moves the application to a dedicated space/virtual desktop. You can split the screen in full screen spaces similar to snapping, but it’s restrictive and irritating.

Applications

Google Drive – the new Google Drive File Stream is generally ok. You will want to close it if you’re on a slow/unstable connection as it tends to start eating CPU.

Office – Microsoft’s Office for Mac is adequate for most tasks. Excel lacks a lot of the features necessary for manipulating large datasets and there is no Visio for Mac (try draw.io for basic diagrams). Outlook has been a trainwreck over the last few releases and I’ve taken to angrily tweeting about it:

Parallels – Don’t bother with any other VM software, pony up the cash and buy Parallels Desktop

Bootcamp – This is still relevant here are my recommended steps for setting up Windows on your Mac:

  1. Download Windows: https://www.microsoft.com/en-ca/software-download/windows10ISO
  2. Setup Bootcamp: https://support.apple.com/en-ca/HT204009
  3. Setup Parallels to use your Bootcamp partition: http://kb.parallels.com/en/112941
  4. Install VS 2017 + Optimize: https://stormpath.com/blog/ultimate-guide-to-using-visual-studio-on-a-mac

Using the tools and techniques described above can help your productivity on a Mac. Overall, the switch will be a bit rocky if you’re unfamiliar, in the end you will move much faster and ship your apps sooner by using a Mac!

More to come next time when we talk about IDEs and development tools.