Wednesday, January 30, 2013

Determining Internet Connection status in a WinRT app

Last week I received word from someone using the Scripture Box Windows 8 app that he continually received notifications that he wasn't connected to the internet. That is, the app thought he was disconnected and therefore wouldn't try to sync with the Azure mobile service used for cloud storage.

I was quite confused. In all my testing - both with connected and disconnect scenarios (on multiple machines) - the app always correctly identified my internet connection status. I was using code similar to the following:

         var ConnectionProfiles = NetworkInformation.GetConnectionProfiles();  
         foreach (var connectionProfile in ConnectionProfiles)  
         {  
           if (connectionProfile.GetNetworkConnectivityLevel() == NetworkConnectivityLevel.InternetAccess)  
           {  
             App.IsConnectedToInternet = true;  
             doSync = true;  
             break;  
           }  
         }  

While searching for potential problems, I ran across another slightly different method to discover one's connection status:

       ConnectionProfile conProfile = NetworkInformation.GetInternetConnectionProfile();  
       if (conProfile != null && conProfile.GetNetworkConnectivityLevel() == NetworkConnectivityLevel.InternetAccess)  
       {  
         App.IsConnectedToInternet = true;  
         doSync = true;  
       }  

From the documentation I couldn't quite tell what the difference was, and which was the correct to use.

I also happened to stumble upon this helpful post that basically included a simple but effective manual approach to checking for internet connectivity:

     public static async Task<bool> IsConnectedToInternetManualCheck()  
     {  
       HttpWebRequest req;  
       HttpWebResponse resp = null;  
       Uri url = null;  
       url = new Uri("http://microsoft.com");  
       req = (HttpWebRequest)WebRequest.Create(url);  
       try  
       {  
         resp = (HttpWebResponse)await req.GetResponseAsync();  
         req.Abort();  
         req = null;  
         resp = null;  
         return true;  
       }  
       catch  
       {  
         req.Abort();  
         req = null;  
         return false;  
       }  
     }  

I figured this was a last resort effort to check for internet connectivity. So which method to use? I couldn't reproduce the issue, and I certainly didn't want to break what was working for others. I also didn't want to go through the release/certification process multiple times for the same issue. (For a few seconds I was tempted to see if this person would be interested in side-loading for testing purposes.)

I decided to take the safe approach and chain the three methods together: first checking with NetworkInformation.GetInternetConnectionProfile(). If that didn't work, then I'd loop through all network connections with NetworkInformation.GetConnectionProfiles(), and finally, if necessary, using the manual method above. Not necessarily pretty, but in the end one of the two additional methods worked. I just wish I knew which one.

And on an encouraging side note - the app update passed through the Microsoft Store certification process in approximately 12 hours(!) and was available in the store shortly thereafter. Good job, Microsoft.


1 comment: