25 09 2013
Detectando conexão à Internet em aplicativos para a Windows Store
Olá caro leitor!
Se você está desenvolvendo aplicativos para a Windows Store (aplicativos Metro), provavelmente você utiliza em algum momento a conexão com a Internet para realizar alguma operação. Obviamente, antes de fazer esse processo, normalmente você gostaria de saber se o usuário está atualmente com uma conexão disponível. No artigo de hoje veremos como você pode fazer essa verificação.
Vamos começar o exemplo criando uma aplicação para a Windows Store. Na MainPage que é criada automaticamente, vamos criar uma interface bem simples, contendo somente um StackPanel com dois TextBlocks, um com o texto “Conectado” e outro com o texto “Desconectado”. A ideia é que quando a conexão com a Internet estiver disponível, o TextBlock “Conectado” seja exibido e, obviamente, quando a conexão não estiver disponível, o TextBlock “Desconectado” seja exibido:
<Page
x:Class="ExemploWinRT_DetectandoConexaoInternet.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:ExemploWinRT_DetectandoConexaoInternet"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<StackPanel Orientation="Vertical"
Margin="50">
<TextBlock Text="Conectado!"
Style="{StaticResource HeaderTextStyle}"
Foreground="#DE7AE81F"/>
<TextBlock Text="Desconectado!"
Style="{StaticResource HeaderTextStyle}"
Foreground="#DEFD1616"/>
</StackPanel>
</Grid>
</Page>
O próximo (e mais importante) passo é criar uma classe que terá o papel de detectar se a conexão com a Internet está disponível no momento. Para deixar essa classe mais interessante, podemos também adicionar um evento que será disparado quando o estado da conexão com a Internet for alterado. Veja abaixo como ficaria essa classe, que no exemplo chamei de InternetConectionHelper:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Networking.Connectivity;
namespace ExemploWinRT_DetectandoConexaoInternet
{
/// <summary>
/// Classe que auxilia na detecção do estado da conexão com a Internet.
/// </summary>
public static class InternetConnectionHelper
{
#region Atributos e Propriedades
/// <summary>
/// Indica se uma conexão à Internet está disponível no momento.
/// </summary>
public static bool ConexaoDisponivel
{
get
{
var internetConnectionProfile = NetworkInformation.GetInternetConnectionProfile();
return internetConnectionProfile != null;
}
}
#endregion
#region Eventos
/// <summary>
/// Simples forwarding do evento NetworkStatusChanged da classe NetworkInformation.
/// </summary>
public static event NetworkStatusChangedEventHandler ConexaoDisponivelChanged
{
add { NetworkInformation.NetworkStatusChanged += value; }
remove { NetworkInformation.NetworkStatusChanged -= value; }
}
#endregion
}
}
Como você pode reparar no código acima, para detectarmos se a conexão com a Internet está disponível no WinRT, utilizamos a classe NetworkInformation, presente no namespace
Windows.Networking.Connectivity. O método estático GetInternetConnectionProfile da classe NetworkInformation retorna as informações do perfil de conexão com a Internet e, como já era de se esperar, caso esse método retorne nulo, isso significa que uma conexão com a Internet não está disponível no momento.
Parece lógico, certo? Porém, isso não é tudo! É aqui que 90% dos artigos relacionados a esse assunto acabam falhando! Caso você esteja utilizando algum tipo de hypervisor (Hyper-V, VirtualBox, etc), provavelmente você tem um adaptador virtual para conexões com a Internet que são utilizados por suas máquinas virtuais. Nesse cenário, o método GetInternetConnectionProfile não retorna nulo, mesmo que você esteja sem conexão com a Internet (até mesmo em Flight Mode do Windows 8)! E aí então, como resolver essa zica? Fácil! É só fazer uma pequena alteração na nossa propriedade ConexaoDisponivel, de forma que, caso o método GetInternetConnectionProfile não retorne nulo, nós verificamos se o ConectivityLevel do objeto retornado é InternetAccess. Veja só:
/// <summary>
/// Indica se uma conexão à Internet está disponível no momento.
/// </summary>
public static bool ConexaoDisponivel
{
get
{
var internetConnectionProfile = NetworkInformation.GetInternetConnectionProfile();
// Não basta checar se InternetConnectionProfile é nulo (como muitos exemplos encontrados na Internet), porque ele nunca será nulo caso você
// tenha algum adaptador virtual (por exemplo HyperV ou VirtualBox adapters). Portanto, precisamos checar também se o connectivity level do
// InternetConnectionProfile é "InternetAccess".
return internetConnectionProfile != null && internetConnectionProfile.GetNetworkConnectivityLevel().Equals(Windows.Networking.Connectivity.NetworkConnectivityLevel.InternetAccess);
}
}
Pronto. Agora sim a classe está preparada para detectar corretamente se a conexão com a Internet está disponível ou não, mesmo se você estiver utilizando Hyper-V ou algo do tipo. Vamos então agora conectar os TextBlocks da nossa MainPage com a propriedade ConexaoDisponivel da nossa classe, porém, quero fazer isso utilizando MVVM, que eu sempre procuro utilizar nos meus exemplos. O toolkit que costumo utilizar é o MVVM Light Toolkit. Para adicioná-lo ao projeto, basta utilizarmos o NuGet Package Manager:


Uma vez adicionado o MVVM Light Toolkit, vamos adicionar também outro pacote que iremos precisar, que se chama WinRTConverters:

Com esses pacotes em mãos, vamos ao nosso App.xaml, onde temos que corrigir uma pequena falha que ocorre com o MVVM Light Toolkit quando utilizado em aplicações para a Windows Store. Basicamente faça uma busca no arquivo App.xaml por “clr-namespace:” (sem aspas) e substitua por “using:“. Agora compile o projeto para garantir que tudo está funcionando até esse ponto.
Aproveitando que estamos no arquivo App.xaml, vamos adicionar uma instância da classe BooleanToVisibilityConverter, que é um dos converters disponíveis na biblioteca WinRTConverters e que precisaremos no nosso exemplo. O código final do arquivo App.xaml deve ficar parecido com este:
<?xml version="1.0" encoding="utf-8"?>
<Application x:Class="ExemploWinRT_DetectandoConexaoInternet.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:ExemploWinRT_DetectandoConexaoInternet"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:ExemploWinRT_DetectandoConexaoInternet.ViewModel"
xmlns:visibilityconverters="using:WinRTConverters.Visibility"
mc:Ignorable="d">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!--
Styles that define common aspects of the platform look and feel
Required by Visual Studio project and item templates
-->
<ResourceDictionary Source="Common/StandardStyles.xaml" />
</ResourceDictionary.MergedDictionaries>
<vm:ViewModelLocator x:Key="Locator"
d:IsDataSource="True" />
<visibilityconverters:BooleanToVisibilityConverter x:Name="BooleanToVisibilityConverter" />
</ResourceDictionary>
</Application.Resources>
</Application>
Agora é hora de ajustarmos a ViewModel que utilizaremos na nossa MainPage. Ao adicionarmos a referência ao MVVM Light Toolkit, a classe MainViewModel é criada automaticamente dentro da pasta ViewModel no nosso projeto. É essa ViewModel que utilizaremos na nossa MainPage. Na MainViewModel, vamos criar uma propriedade chamada ConexaoDisponivel, que simplesmente é um atalho para a propriedade de mesmo nome que se encontra na nossa classe InternetConectionHelper criada anteriormente. Além disso, precisamos fazer um hook no evento ConexaoDisponivelChanged que chamará o método RaisePropertyChanged da nossa MainViewModel. Como essa propriedade está bindada na interface, precisamos utilizar o Dispatcher para chamar o método RaisePropertyChanged. Com isso em mente, o código da MainViewModel ficaria assim:
/// <summary>
/// ViewModel contendo as propriedades e comandos a serem bindados na Main View.
/// </summary>
public class MainViewModel : ViewModelBase
{
#region Atributos e Propriedades
/// <summary>
/// Atalho para a propriedade de mesmo nome da classe InternetConnectionHelper. Adicionada na ViewModel para implementar suporte a change notification.
/// </summary>
public bool ConexaoDisponivel
{
get
{
return InternetConnectionHelper.ConexaoDisponivel;
}
}
#endregion
#region Construtores
/// <summary>
/// Constroi uma instância de MainViewModel, realizando outras tarefas necessárias.
/// </summary>
public MainViewModel()
{
// Quando o evento ConexaoDisponivelChanged é disparado na classe InternetConnectionHelper, precisamos notificar a alteração da propriedade ConexaoDisponivel
// para que a UI seja atualizada caso necessário.
InternetConnectionHelper.ConexaoDisponivelChanged += (s) => GalaSoft.MvvmLight.Threading.DispatcherHelper.CheckBeginInvokeOnUI(() => RaisePropertyChanged("ConexaoDisponivel"));
}
#endregion
}
O próximo passo é adicionar os bindings nos nossos TextBlocks da MainPage de forma que eles utilizem a propriedade ConexaoDisponivel da nossa ViewModel. No primeiro TextBlock (que tem o texto “Conectado!”) faremos um binding normal com essa propriedade, utilizando o converter BooleanToVisibilityConverter criado anteriormente. Já no segundo TextBlock (que tem o texto “Desconectado!”), faremos também um binding com a mesma propriedade e também utilizaremos o mesmo converter, porém, passando como parâmetro para o converter o valor booleano “True”. Dessa forma, o converter agirá de forma invertida, ou seja, quando a propriedade ConexaoDisponivel estiver true, o TextBlock estará invisível, e quando ela estiver false, o TextBlock estará visível. Além disso, precisamos configurar o DataContext da nossa página apontando para a nossa MainViewModel. Faremos isso utilizando o ViewModelLocator do MVVM Light Toolkit. Veja como fica o XAML final da nossa MainPage:
<Page
x:Class="ExemploWinRT_DetectandoConexaoInternet.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:ExemploWinRT_DetectandoConexaoInternet"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
DataContext="{Binding Main, Source={StaticResource Locator}}">
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<StackPanel Orientation="Vertical"
Margin="50">
<TextBlock Text="Conectado!"
Style="{StaticResource HeaderTextStyle}"
Foreground="#DE7AE81F"
Visibility="{Binding ConexaoDisponivel, Converter={StaticResource BooleanToVisibilityConverter}}" />
<TextBlock Text="Desconectado!"
Style="{StaticResource HeaderTextStyle}"
Foreground="#DEFD1616">
<TextBlock.Visibility>
<Binding Path="ConexaoDisponivel"
Converter="{StaticResource BooleanToVisibilityConverter}">
<Binding.ConverterParameter>
<x:Boolean>True</x:Boolean>
</Binding.ConverterParameter>
</Binding>
</TextBlock.Visibility>
</TextBlock>
</StackPanel>
</Grid>
</Page>
Por fim, como nós utilizamos o DispatcherHelper do MVVM Light Toolkit na nossa MainViewModel, precisamos inicializá-lo a partir do construtor da nossa MainPage. Para isso, vá até o code behind da MainPage e adicione a seguinte linha no construtor, logo após a chamada de InitializeComponent:
GalaSoft.MvvmLight.Threading.DispatcherHelper.Initialize();
Pronto! Com isso temos um exemplo completo que mostra como gerenciar e responder à alteração da conexão à Internet a partir de aplicativos para a Windows Store. Para testar o exemplo, execute o projeto e tente ativar o modo de voo no seu computador para habilitar e desabilitar a conexão à Internet:

E com isso concluímos mais um artigo da série sobre desenvolvimento de aplicativos para a Windows Store. Você encontra o código completo desse exemplo no meu GitHub, bem como nos meus exemplos da MSDN Galery.
Espero que tenham gostado! Até a próxima semana!
André Lima
Explorando as in-app purchases em aplicativos para a Windows Store Criando um simples formulário de parâmetros em Windows Forms