(X) Hide this
    • Login
    • Join
      • Generate New Image
        By clicking 'Register' you accept the terms of use .

Manage network connectivity in Windows Store apps

(2 votes)
Andrea Boschin
>
Andrea Boschin
Joined Nov 17, 2009
Articles:   91
Comments:   9
More Articles
1 comments   /   posted on Feb 11, 2013
Categories:   Windows 8
Tweet

The Windows Store apps are some way different from desktop and web applications. Together with the handling of different form factors, required when you work in the mixed environment that can vary from a normal PC to a slim and small tablet, you have also the responsibility of taking in serious account the network connectivity issues. If it's not a real problem when your application runs into a desktop wired to the ethernet, it's a bit more complex situation when it runs in a laptop or netbook, but the trouble is much more awful if your hardware is a tablet, where network could fastly change in quality and cost.

Both these aspect should be taken in consideration because they are a potential bad issue for your customers. On a side, intermittent connections can be source of errors and slowdown that gives a negative feedback to the user. But if your application starts eating lot of money due to connectivity costs you are pretty sure that the user will uninstall it as soon as he understand the point.

Detect network status and its changes.

The very first need you will meet during the development of a network enabled application, is the detection of the network status. It is a strong requirement for certification submission, when an application use the network, it check for its status just before it try to access a remote resource. The worst thing you can do is to run the network call and handle the possible exception stating that an errore has happened. Catch errors is obviously important but you should check for network availability just before to run the remote call and in the case the network is not available you have to notify the user. This may be achieved using the NetworkInformation class. It is a static class that exposes a bunch of methods to retrieve informations about its status.

   1: public static bool IsNetworkAvailable(NetworkConnectivityLevel minimumLevelRequired = NetworkConnectivityLevel.InternetAccess)
   2: {
   3:     ConnectionProfile profile = 
   4:         NetworkInformation.GetInternetConnectionProfile();
   5:  
   6:     NetworkConnectivityLevel level = 
   7:         profile.GetNetworkConnectivityLevel();
   8:  
   9:     return level >= minimumLevelRequired;
  10: }

The method above is an example of how to use the information returned by GetNetworkConnectivityLevel. When you ask for a ConnectionProfile using the GetInternetConnectionProfile method in NetworkInformation class, you receive an instance of the class that is able to investigate about the network availability. The returned value is an enumerator that has the following meaning:

None: the device is disconnected and the network cannot be reached.
LocalAccess: the connection is only able to connect to local area network.
ConstrainedInternetAccess: You have connection to the internet but credentials are required.
InternetAccess: Full internet access available.

Since these values are sorted from the less accessible to the most accessible, the method I usually use require a minimum access level to ask and compare it with the value returned. So you will write something like this:  

   1: if (Utilities.IsNetworkAvailable()) // defaults to NetworkConnectivityLevel.InternetAccess
   2: { /* access remote resource */ }
   3: else
   4: { /* notify error to the user */ }

Most of times this suffice, but in some cases, you need to take decisions on the base of network status changes. Let say you have to consume a socket that use a persistent connection (e.g. a remote control application), you may need to detect when the connection is gone and when it's came back again, to gracefully disconnect and reconnect without the user interaction. For this purpose the NetworkInformation class provides a NetworkStatusChanged event that is raised when the connection and disconnection happen.

   1: NetworkInformation.NetworkStatusChanged += NetworkInformation_NetworkStatusChanged;
   2:  
   3: static void NetworkInformation_NetworkStatusChanged(object sender)
   4: {
   5:     if (Utilities.IsNetworkAvailable())
   6:     {
   7:         // restore connection...
   8:     }
   9: }

Combining these two information you can also create a simple page that gracefully handles missing connectivity instead of using a MessageDialog that is usually discouraged by the user interface guidelines. Let say you use something like this to navigate to a page when network connectivity is not available:

   1:  
   2: if (!Utilities.IsNetworkAvailable())
   3:     this.Frame.Navigate(typeof(MissingNetworkPage));

Then, inside the MissingNetworkPage you have to monitor network status changes and when it is detected your code should call the GoBack method to navigate back to the calling page. The page have to attach the NetworkStatusChanged event in the OnNavigatedTo method but have also to detach the delegate in the OnNavigatingFrom to avoid duplicate notifications when other disconnections happen. Here is the code:  

   1: protected override void OnNavigatedTo(NavigationEventArgs e)
   2: {
   3:     NetworkInformation.NetworkStatusChanged += NetworkInformation_NetworkStatusChanged;
   4:     base.OnNavigatedTo(e);
   5: }
   6:  
   7: protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
   8: {
   9:     NetworkInformation.NetworkStatusChanged -= NetworkInformation_NetworkStatusChanged;
  10:     base.OnNavigatingFrom(e);
  11: }
  12:  
  13: public async void NetworkInformation_NetworkStatusChanged(object sender)
  14: {
  15:     ConnectionProfile profile = NetworkInformation.GetInternetConnectionProfile();
  16:  
  17:     if (profile != null)
  18:     {
  19:         NetworkConnectivityLevel level = profile.GetNetworkConnectivityLevel();
  20:  
  21:         if (level == NetworkConnectivityLevel.InternetAccess)
  22:             await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => this.Frame.GoBack());
  23:     }
  24: }

The MissingNetworkPage.xaml should be an informative page that contains almost a back button and a message that invites the user to press the button to retry or wait for the connection to be restored. In this case the page automatically return to the point where the work was interrupted.

Connection costs

As I've previously said, the worst issue your application can run into, is the consumption of much more money that the user expects. This can easily happens in lot of cases when the device has a mobile connection. There are a number of events that can boost connection costs unexpectly like switching to roaming when you cross a country border, or often the reach of a data limit of your provider. Luckily your Windows 8 device is able to correctly detect the network status, not only by the availability point of view, but also for the costs.

Inside the ConnectionProfile instance you get by the GetInternetConnectionProfile method I've talked before, there are a GetConnectionCost method that provides all the information you need. These includes:

NetworkCostType: an enumerator that is the main indicator about the type of connection you are using.
ApproachingDataLimit: a flag that inform when the connection limit is about to be reached (it is the best moment to notify your user...)
OverDataLimit: another flag the say you have passed the limit.
Roaming: again a flag that is set when the device uses a roaming connection

The NetworkCostType enumerator is key in this case. On the basis of its value you have to use a different strategy to manage your connectivity.

Unrestricted: go without any limitation.
Fixed: pay attention to the reach of the OverDataLimit. When the flag is not set you should limit data transfer but you have to ask your user after the limit has been reached because the costs are overboosted.
Variable: in this case the connection if always subject to the size of transferred data. You have to always pay attention and minimize the size and number of downloads.

The enumeration also contains a "Unknown" value. This is usually paired with an Unrestricted connection so you can use the same strategy in network access.

Apply strategies with a pattern

Since the situation here is on how to apply different connection strategies on the basis of a number of variable parameters that are the presence of a valid connection but also the costs generated by it, is may be a good idea to apply some patterns to decouple the implementation by the values that generate a given behavior. This helps to isolate the problems and go with a right route for the specific case that is handled. The pattern here is the Strategy (http://www.oodesign.com/strategy-pattern.html) that apply perfectly to the current case. First of all we should define the actions we would like to manage by each strategy. In my case this definition is made by an interface that have only one method:

   1: public interface IConnectionStrategy
   2: {
   3:     Task<bool> IsAuthorizedAsync();
   4: }

The IsAuthorizedAsync have the responsibility of determine if in the specific scenario the connection may be used. The method is defined with an asynchronous signature just because I expect that in some cases it'll have to prompt the user for an authorization using a dialog. 

Now you have to determine the exact kind of behaviors you expect. I see three scenario: The UnrestrictedConnectionStrategy where the connection is unlimited or the limits have not been reached. The LimitedConnectionStrategy instead is used when you need to be careful in using resources but is is not required an authorization by the user. Finally the OptInConnectionStrategy should verify if the user allows the connection at least the first time it tries the access. After the authorization have been granted the connection operates as for the LimitedConnectionStrategy. Here is the implementation of the most complex rule:

   1: public class OptInConnectionStrategy : LimitedConnectionStrategy
   2: {
   3:     bool isAuthorized = false;
   4:  
   5:     public async Task<bool> IsAuthorizedAsync()
   6:     {
   7:         if (isAuthorized)
   8:             return await base.IsAuthorizedAsync();
   9:         else
  10:         {
  11:             MessageDialog dialog = new MessageDialog("Are you sure you want to connect to the internet?");
  12:             IUICommand denyCommand = new UICommand("No");
  13:             dialog.Commands.Add(denyCommand);
  14:             IUICommand grantCommand = new UICommand("Yes");
  15:             dialog.Commands.Add(grantCommand);
  16:             IUICommand result = await dialog.ShowAsync();
  17:             isAuthorized = result == grantCommand;
  18:             return isAuthorized;
  19:         }
  20:     }
  21: }

The final part is to create a Context, I call it ConnectionManager, that is able to detect connection changes and create an instance of the right strategy based on the current status. This will be a static class that attach the NetworStatusChanged event and change the implementation of the IConnectionStrategy it uses internally.

   1: public static class ConnectionManager
   2: {
   3:     private static IConnectionStrategy strategy = new UnrestrictedConnectionStrategy();
   4:  
   5:     static ConnectionManager()
   6:     {
   7:         NetworkInformation.NetworkStatusChanged += NetworkInformation_NetworkStatusChanged;
   8:     }
   9:  
  10:     static void NetworkInformation_NetworkStatusChanged(object sender)
  11:     {
  12:         ConnectionProfile profile = NetworkInformation.GetInternetConnectionProfile();
  13:         strategy = CreateStrategy(profile);
  14:     }
  15:  
  16:     static async Task<bool> IsAuthorizedAsync()
  17:     {
  18:         return await strategy.IsAuthorizedAsync();
  19:     }
  20:  
  21:     private static IConnectionStrategy CreateStrategy(ConnectionProfile profile)
  22:     {
  23:         ConnectionCost cost = profile.GetConnectionCost();
  24:  
  25:         // add here logic to determine strategy to use...
  26:     }
  27: }

After you defined once the logic to use to create the right strategy you are ready to go. Every time your code need to access the network you first call the ConnectionManager.IsAuthorizedAsync(). If this method returns true you can run without any problem, but if the value is false you have to avoid connections because the current status and user do not allow them.

The strategy pattern is perfect in this situation because completely abstracts the behavior from the decisions that are needed to determine the current behavior. Thanks to a common context, rules by the NetworkStatusChanged event. This makes the strategy auto-adaptive and your developre life is for sure quiet and easy.


Subscribe

Comments

  • DavideB

    Re: Manage network connectivity in Windows Store apps


    posted by DavideB on Feb 11, 2013 18:03

    Very interesting article! 

    PS: There is a broken link to "http://www.oodesign.com/strategy-pattern.html)"

Add Comment

Login to comment:
  *      *       

From this series