[Windows 8] Tip: Saber si tenemos acceso real a internet

Hola a todos!

Una situación muy común hoy en día es encontrarnos con una conexión WiFi o Ethernet abierta en la que, una vez conectados, debemos acceder a un portal local para indicar un usuario y password. En este caso, efectivamente tenemos conectividad pero no tenemos salida a internet. Nos encontramos ante lo que se denomina una conexión cautiva.

Normalmente, comprobamos simplemente si tenemos internet o no. Para ello manejamos el evento NetworkStatusChanged de la clase NetworkInformation y consultamos el método GetInternetConnectionProfile. Si esta llamada nos devuelve NULL, entonces no tenemos internet. Si devuelve un ConnectionProfile, tenemos internet:

   1: if (NetworkInformation.GetInternetConnectionProfile() == null)

   2: {

   3:     ShowNotification("Conexión a internet desactivada.");

   4: }

   5: else

   6: {

   7:     ShowNotification("Conexión a internet activada.");

   8: }

Esto puede ser suficiente en muchos casos pero, como comentábamos al principio del artículo, puede que tengamos conexión de internet mediante una WiFi abierta. Cuando intentemos ejecutar una petición web o abrir una página web, lo primero que obtendremos será un portal interno de la red, pidiéndonos usuario y password. Esto es cada vez más normal en eventos y en hoteles. Con nuestro método anterior, tendríamos un falso positivo. Si, tenemos una conexión a internet, pero es inútil hasta que el usuario se autentifique en el portal. ¿Como podemos solucionar esto? Mediante el uso del método GetNetworkConnectivityLevel de la clase ConnectionProfile.

GetNetworkConnectivityLevel nos devolverá un enumerado con el nivel de conexión del perfil:

None, no disponemos de conectividad.

LocalAccess, acceso solo a red local, no a internet.

ConstrainedInternetAccess, nos informa de que…. nos encontramos tras un portal de autenticación!!, justo lo que necesitamos. Pero tiene su truco… luego lo veremos.

InternetAccess, acceso a internet y a la red local.

De esta forma, podríamos modificar nuestro primer código por algo así:

   1: public NetworkConnectivityLevel GetConnectivityLevel()

   2: {

   3:     var iConnection = NetworkInformation.GetInternetConnectionProfile();

   4:     if (iConnection == null)

   5:         return NetworkConnectivityLevel.None;

   6:  

   7:     return iConnection.GetNetworkConnectivityLevel();

   8: }

   1: var stat = this.networkService.GetConnectivityLevel();

   2:  

   3: switch (stat)

   4: { 

   5:     case NetworkConnectivityLevel.None:

   6:         ShowNotification("No existe conexión a internet.");

   7:         break;

   8:     case NetworkConnectivityLevel.InternetAccess:

   9:         ShowNotification("Existe conexión a internet.");

  10:         break;

  11:     case NetworkConnectivityLevel.LocalAccess:

  12:         ShowNotification("Solo acceso local.");

  13:         break;

  14:     case NetworkConnectivityLevel.ConstrainedInternetAccess:

  15:         ShowNotification("Debe autenticarse en el portal de la red.");

  16:         break;

  17: }

Ahora ya tenemos un control más granulado sobre el estado de nuestra conexión. Pudiendo indicar al usuario el estado exacto en el que se encuentra.

Pero no podemos confiar a ciegas en GetConnectivityLevel. Puede darse el caso en el cual nos encontremos en una conexión con un portal de autenticación y el estado devuelto sea LocalAccess, pues Windows no ha podido detectar el portal. Para estos casos la recomendación es que, siempre que nos encontremos en el estado LocalAccess, intentemos hacer una petición a una web pública conocida. Por ejemplo el archivo robots.txt de www.windowsphone.com (solo un ejemplo, aquí cada uno que vea la que prefiere). Al tratarse de un archivo plano, será muy fácil saber si nos encontramos tras un portal. Si la petición falla: no tenemos acceso a internet. Si la petición nos devuelve un archivo HTML, es muy posible que nos encontremos ante un portal y podamos informar al usuario de ellos.

Tendremos que tener en cuenta el caso concreto, esta es la recomendación oficial de MSDN para detectar un portal, depende de la situación, creo que en el estado LocalAccess podríamos informar al usuario de que existe la posibilidad de que:

A) tenga un problema con la conexión

B) Necesite autenticarse en un portal, ofreciéndole la opción de que abra un navegador y lo compruebe.

En ambos casos nos ahorramos la petición extra. Pero a cambio no podemos darle una respuesta concisa al usuario. Por eso comento que, depende de nuestras necesidades, puede hacer falta que realicemos la comprobación o solo con avisar nos llegará.

¿Y Windows Phone?

Pues… este código compila perfectamente en Windows Phone 8, pero no funciona. Si intentamos acceder al método GetNetworkConnectivityLevel desde un proyecto Windows Phone 8, obtendremos una excepción NotImplementedException, de esas que tanto gustan en Redmond… ¿Le pagarán a alguien a razón de cuantas NotImplementedException incluya en el API de Windows Phone? Esperemos que en futuras versiones, se reduzca el número de estas feas excepciones…

Y… FIN!

Esto es todo amigos! Un pequeño truco, para ayudarnos a crear apps que informen lo mejor posible al usuario sobre su conexión. A continuación os dejo un ejemplo de como aislar esta comprobación en un componente WinRT para poder usarlo tanto en C# como Javascript o C++ y reutilizarlo en diferentes proyectos. A disfrutarlo!

Un saludo y Happy Coding!

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *