Skip to main content
July 25, 2016
Mobile

Offline Apps: what to do when your user disconnects



You’ve just boarded your airplane flight, found a free spot in the overhead to store your carry-on and settle in for the journey by pulling out your Windows 10 device to check for status updates on your various social networks. Suddenly, you are aware of a polite flight attendant hovering over you and requesting that you put your device into airplane-mode. While doing so, you start to wonder as a developer, what happens to each of those apps as it loses its network connection.

Are these apps still usable? Will they throw errors if you try to interact with them? Is the data pulled from the last data connection still available or simply gone? Let’s see if we can resolve some of these questions before your flight is over today.

As you know, many Universal Windows Platform (UWP) apps consume the latest data from social media, blogs and other sources. These are referred to as “connected apps.” Since UWP apps can run on desktops as well as mobile devices, it isn’t unusual for connected apps to occasionally get disconnected. Not surprisingly, it can be a challenge to properly handle common network connectivity issues when that connectivity is lost.

In this post, we will explore the following four common scenarios that developers of connected apps must know how to handle, as well as some tips and best practices for properly managing interruptions in connectivity, like:

  • Handling network status changes midstream
  • Offline first time launch
  • Offline first time launch, login required
  • Offline login when the user has already logged in

Handling network status changes midstream

A network check at app startup for internet connectivity is never enough. After all, network connectivity may change at any time. If the user is in the middle of using your app and network connectivity is lost, the application should obviously not crash and it should not display the exception stack.

Instead, it should continue to function in whatever limited fashion is possible while displaying an informative message to the user and disabling functionality that requires connectivity. Then, when the application detects that the network connectivity has been restored, functionality should be re-enabled and it should resume working normally.

The NetworkStatus API is your tool of choice for determining internet connectivity. Always do a quick gate check on the network status before attempting a network operation:

[code lang=”csharp”]

bool isConnected = NetworkInterface.GetIsNetworkAvailable();

[/code]

Besides checking your network status before attempting to use a networked resource, it’s also important to display a meaningful message for your user when your app gets disconnected. This will make it easier for your user to take appropriate action.

As demonstrated in the sample NetworkConnectivityMonitor code on GitHub, the Network APIs provide an easy way to handle connectivity changes. Although your app should also implement proper error handling in addition to using the NetworkStatusChanged event, this event can be used for UI notifications like this:

[code lang=”csharp”]

NetworkInformation.NetworkStatusChanged += async (s, e) =>
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
offline.Visibility =
(e.IsConnected ? Visibility.Collapsed : Visibility.Visible);
});
};

[/code]
However, network APIs will not indicate if your middle-tier service is down, nor if the connection has dropped in the middle of your remote call. This is why it’s always a good idea to wrap your network connection code with proper exception handling. If you are using the HttpClient class for network calls, keep in mind that any exception details will be available in the HRESULT property, while HttpResponseMessage.StatusCode provides the cause of an unsuccessful call.

[code lang=”csharp”]

try
{
// if the url is not well formed, need to handle the error as an exception
// read for more details
// i.e. 0x80131537 for a bad format
Uri uri = new Uri(url);

// expect HTTP errors to be visible through the HResult property of the caught exception
// https://blogs.msdn.microsoft.com/jpsanders/2008/06/25/troubleshooting-code-that-uses-the-http-protocol/
// i.e. 0x80072EE7 could occur when the connection is lost
// don’t rely on the message text (could be different in another language OS)
// The text associated with this error code could not be found.
//
// The server name or address could not be resolved
//
try
{
HttpClient client = new HttpClient();
HttpRequestMessage msg = new HttpRequestMessage(HttpMethod.Get, uri);

HttpResponseMessage response = await client.SendRequestAsync(msg);

if (response.IsSuccessStatusCode)
{
// handle response
}
else
{
// handle response based on response.StatusCode
}
}
catch (Exception x)
{
// Handle other possible exceptions when the connection is lost:
// ————————————————————-
// HResult – 0x80072EFD
// A connection with the server could not be established
//
// HResult – 0x80072EE7
// The server name or address could not be resolved
//
// HResult – 0x0x80072EE2
// The operation timed out
//
}
}
catch (Exception x)
{
// expecting bad format url
// i.e. HResult – 0x80131537
Debug.WriteLine(x.ToString());
}

[/code]

Offline first time launch

A surprising number of apps crash when you try them offline on first time use. It is easy to test: simply install an application, switch on airplane mode, then launch the application. Even if it is offline, the application should provide some limited functionality on first-time launch. To manage this, use default data packaged with your app if the app is initially offline. At the same time, disable any functionality that requires network connectivity.

Tip

To implement an offline UI, some app developers create a single app level variable that indicates network connectivity (based on NetworkInformation.NetworkStatusChanged event) and that implements INotifyPropertyChanged. They then bind various UI elements enabled and visible properties based on the current connectivity. This app level state could also be used before making any network call.

Although a “warning bar” is not a built in control, many developers will create an element in their XAML at the top of the page, and hide and show it depending on network connectivity. Typically the background is light-blue, but the color does not matter so long as it is consistent whenever it is shown in your app.

IMAGE1

Offline first time launch, login required

Some apps require data from their secured web services to provide any useful functionality. When the application is offline and the user attempts to log into the application, you should warn the user of their offline status with an appropriate error message while also disabling login. When the network connection has been resumed, login should work appropriately.

If your app requires a login, consider packaging some mock data for first-time use rather than making the app completely empty, or forcing the user to close the app when offline. Even better, try to create an initial tutorial experience for your user than can run both offline and online.

Offline login when the user has already logged in

A common practice for handling offline scenarios is to take advantage of your app’s time online to retrieve and store content in a background task. By pre-loading content in this way, it can be made available to the user even when the network is unreliable later. When applying the user’s credentials in this way, however, it is important to take extra care to do this is a safe and secure manner.

You should leverage PasswordVault for secure storage of credentials in situations where the contents of the locker are specific to the app (or related background services). This is particularly helpful when using a background task to securely retrieve and store data for offline use since apps and services don’t have access to credentials associated with other apps or services.

While the app model in Windows 10 ensures that the data stored locally with ApplicationData.LocalSettings and ApplicationData.LocalFolder is only accessible to that UWP app, this should not be considered completely secure. If another app on the user’s machine has IO permissions to access the storage location it can view the settings or files.

In order to secure your app user’s offline content, you can leverage the Cryptography APIs directly in conjunction with PasswordVault for encryption and decryption of your locally stored data. The DataProtectionProvider cryptographic provider simplifies these tasks and can be used to encrypt and decrypt data against your stored credentials—without requiring the enterprise authentication capability which often presents challenges for certification and app distribution.

How to test offline behavior

A good way to simulate network issues during coding and testing phases is to use the mobile emulator in Visual Studio 2015. In the Additional Tools tab, you’ll find a tab called Network, which allows you to test a missing Internet connection, a slow connection or even one with poor signal strength. This way, you can easily check that your app behaves properly when the Internet connection is gone or so slow that it triggers timeouts or malformed responses.

IMAGE2

For offline scenarios that involve larger amounts of data, an app may implement an offline (cached) mode with minimal code by leveraging Azure Mobile App service Offline Data Sync. When the app is offline, instead of data being sent to the backend, it is automatically redirected to the local store—to be synced later when connectivity is restored.

Wrapping up

We often fall into the trap of assuming that our apps are either always online or always offline. In fact, our apps are usually in a gray area in between with varying and inconsistent levels of connectivity. Great UWP apps are built with this in mind and provide an impactful and responsive user experience under any network scenario. And by the way, if you really did read this post while on a flight, please let us know in the comments! For additional information about handling offline and intermittent connectivity, please check out these articles:

Download Visual Studio to get started.