It’s important to plan for mobile applications to be used when there is either poor mobile data / WiFi or none at all. Mobile apps will be used in a wide variety of locations where mobile data can be an issue .e.g rural areas or trains where one second you can have full 4G, and 30 seconds later have no signal at all. Handling these scenarios will greatly improve the usability of our app and hopefully lead to happier users.

Xamarin Essentials

Achieving our aims is easy thanks to the work that Microsoft have done with Xamarin.Essentials. Xamarin.Essentials provides the functionality we need (as well as a lot of other great APIs), Connectivity. It provides a simple interface for checking what kind of network we’re on.

if (Connectivity.NetworkAccess == NetworkAccess.Internet)
{
    // Connection to internet is available
}

This gives us the ability to either feedback to the app user that there is no internet connection, or handle this scenario in code. For example:

public async Task GetAsync()
{
  if (Connectivity.NetworkAccess == NetworkAccess.Internet)
  {
    // Make API call
  }
}

Retrying with Polly

Sometimes network requests don’t work first time, that doesn’t mean that they won’t work on the second or third time of trying. We can handle this scenario using a great tool called Polly. Polly is a “resilience and transient-fault-handling library” which means it’s designed to handle failures, whether that is via retrying or by blocking that action from taking place. Polly is a great library that’s worthy of countless dedicated posts.

public async Task GetAsync()
{
  if (Connectivity.NetworkAccess == NetworkAccess.Internet)
  {
    var httpClient = new HttpClient();
    var response = await Policy.Handle<HttpRequestException>()
        .WaitAndRetryAsync(3, retryCount => TimeSpan.FromSeconds(2))
        .ExecuteAsync(async () => await httpClient.GetAsync("URL_GOES_HERE"));
    return response;
  }
  else
  {
    // return empty list of data
  }
}

Caching

Unreliable network connectivity is one of the countless reasons that you should be caching data within your application. There are a lot of libraries available for caching, one of the simplest that I’ve found is MonkeyCache, you set a key and expiry and job done. This allows you to fallback to the cached content if a user loses their network connectivity. Our example now starts to look like this

public async Task GetAsync()
{
  if (Connectivity.NetworkAccess == NetworkAccess.Internet)
  {
    var httpClient = new HttpClient();
    var response = await Policy.Handle<HttpRequestException>()
        .WaitAndRetryAsync(3, retryCount => TimeSpan.FromSeconds(2))
        .ExecuteAsync(async () => await httpClient.GetAsync("URL_GOES_HERE"));
    Barrel.Current.Add(key: "URL_GOES_HERE", data: response, expireIn: TimeSpan.FromHours(1));
    return response;
  }
  else
  {
    return Barrel.Current.Get<IEnumerable<Data>>(key: "URL_GOES_HERE");
  }
}

Summary

We’ve built up a solution in this post that will handle the majority of issues thrown up by network connectivity. The code examples will give you a great starting point to handle the types of network connection, retrying and caching data. This will cover the scenarios, and hopefully lead to happier users of your apps.