Bom pessoal, tudo bem?
Estou hoje com meu primeiro post 100% técnico para o site pós-recebimento do título de MVP.
Usarei esse canal muito mais em 2012, junto com o Thiago, e esperamos poder trazer muito conhecimento Windows Phone para o pessoal.
Lembrando dos canais que uso para divulgação do Windows Phone:
Windows Phone Brasil – divulgação de posts técnicos
RodolphoMarques.com – opiniões, colunas, etc
Conexão Windows – podcasts (em breve um podcast dev de wp7)
Canal do YouTube – vídeos técnicos e para consumidores
Twitter e Facebook – atualizações técnicas e notícias do Windows Phone, além de assuntos diversos (ninguém é de ferro!! haha)
Espero que possamos em 2012 nos encontrar em algum desses canais e nas novidades que vem por aí!!
Mas voltando, resolvi hoje falar de Push Notifications por perceber que esse é provavelmente um dos assuntos mais chamativos do Windows Phone. Sem pensar que isso se deva a ser um dos assuntos mais complexos ou não, mas o que as chamadas Notificações Push podem fazer, e COMO elas o fazem, realmente causam um certo interesse, seguido de muitas dúvidas, por parte do usuário. Apresentei uma sessão no último Tech-Ed Brasil, com o Thiago Mônaco, onde falamos sobre isso, e senti que o assunto é mais complexo do que eu mesmo achava, pelos feedbacks que recebi. Nem tudo fica muito claro e, apesar das melhorias e novidades do Mango (Windows Phone SDK 7.1), ainda é algo que causa confusão.
Porém, é um assunto que é bastante importante que seja entendido, pois é um dos grandes diferenciais do Windows Phone, quando aliado aos Live Tiles (Tile Notifications) e uma solução que pode ajudar o desenvolvedor até para resolver problemas comuns de serviços que entregarão dados em páginas internas da sua aplicação.
No artigo de hoje tento mostrar um pouco mais sobre o assunto, esclarecer dúvidas e fazer um passo a passo de como colocar qualquer um dos três tipos de notificação em seu código.
Mãos a obra!
O QUE É
Os Push Notifications são formas de trabalhar com serviços de maneira inteligente e eficiente, em se tratando de consumo de bateria e na forma de obtenção dos dados. Além disso, dá ao usuário final vantagens como poder verificar novidades sobre seu aplicativo sem que precise necessariamente estar o utilizando, gerando enorme diferencial e utilizando todo o potencial presente na plataforma Windows Phone
ENTENDENDO OS MOTIVOS POR TRÁS DAS PUSH NOTIFICATIONS
Para que eu deveria usar isso? Para enviar uma novidade ao celular, não é só ter um serviço e consumir no telefone? Trazendo mais para a realidade de um aplicativo, se eu quiser obter as novidades de um site de notícias, ou resultados esportivos, não é só consultar um serviço, um método “Obtém Resultados” ou algo do tipo?
Sim, podemos fazer dessa forma, sem problemas. Mas pergunto: como saber se os dados estão atualizados? Como saber se esse resultado é mesmo o mais recente? Ou se essa notícia realmente é a mais atual? Em uma aplicação que informa sobre trânsito, como sei que o tráfego ainda é o mesmo que informei ao meu usuário?
Para obter essas respostas, teremos que consultar o serviço novamente. E novamente. E assim sucessivamente. Não há maneira de saber se o resultado é o mais atual sem ficar consultando repetidamente o serviço. E isso causa, fatalmente, maior consumo de dados para o usuário, além de um consumo maior de bateria para o telefone. E é isso que o Push Notifications vem resolver, ainda entregando de “bônus” ao desenvolvedor a possibilidade de apresentar essas novidades fora do âmbito da sua aplicação, através do conceito de Toast e Tile.
Com as Notificações Push temos o caminho inverso acontecendo. O cliente (aplicação) irá se inscrever como “assinante” da notificação, dizendo que deseja receber as novidades. Com isso, enviaremos um “ID” desse usuário, juntamente com a atualização, de um servidor na nuvem(de nossa propriedade) a um serviço da Microsoft, e esse serviço distribuirá de forma ativa ao celular, no sentido Nuvem para telefone. Ou seja, com isso perde-se a necessidade de consulta incessante ao serviço por novidades: quando elas houverem, isso chegará ao telefone diretamente da nuvem.
Confuso? Vamos entender melhor sobre os passos necessários para que isso tudo aconteça e esclarecer as coisas.
Como isso tudo funciona?
Há uma imagem que sempre gosto de usar, pois exemplifica perfeitamente o que precisamos entender. É a da biblioteca oficial do Windows Phone, biblioteca essa que você pode acessar clicando aqui. A Imagem 1 mostra todos os passos de como o Push acontece. Vamos explicar mais sobre ele abaixo e depois, conforme o código for escrito, voltaremos à imagem para linkar cada pedaço de código a cada passo mostrado aqui. (Nota: Escrevi um artigo detalhando um pouco como o Push funciona e com hubs para diversos locais de estudo, em meu blog pessoal – acesse http://www.rodolphomarques.com )

Imagem 1 – Todo o processo de Push Notification
WINDOWS PHONE - LADO ESQUERDO DA IMAGEM 1 (CÓDIGO E SERVIÇOS QUE SÃO EXECUTADOS NO TELEFONE)
No lado esquerdo da imagem, dentro do retângulo amarelo, temos uma descrição do que é executado no telefone. A sua aplicação está no retângulo menor da cor verde. No retângulo azul, temos um serviço cliente de Push, que é quem se comunica com sua aplicaçãoe também com o MPNS (mais a seguir).
CLOUD SERVICE - RETÂNGULO VERDE (LADO DIREITO SUPERIOR DA IMAGEM)
Ao lado direito, na parte superior, temos um retângulo representando o ambiente em que estará o seu serviço, o seu servidor na nuvem. Esse ambiente conversa tanto com seu telefone como com os serviços Microsoft (MPNS).
MPNS -RETÂNGULO AZUL (LADO DIREITO INFERIOR DA IMAGEM)
Ao lado direito, na parte inferior, temos um retângulo azul, que representa o MPNS (Microsoft Push Notification Services), os serviços disponibilizados pela Microsoft que vão fazer o trabalho pesado. Mais sobre isso abaixo.
Os passos para que o Push Notification funcione são (Seguindo os números da Imagem 1):
1 – O primeiro passo é, tendo uma aplicação que irá usar Push Notification, requisitar uma URI ao serviço cliente. Isso é necessário pois precisamos definir essa requisição como única e linkar aquele usuário com o serviço desejado.
2 - O serviço push cliente, ao receber a requisição da aplicação, a repassa ao MPNS requisitando uma URI única.
3 – Após receber a URI do MPNS, o serviço PUSH cliente o retorna para a aplicação.
4 - Com a Uri na mão, funcionando como um ID, a sua aplicação vai chamar o seu serviço na nuvem requisitando assinatura. Em português claro e limpo, “Quero receber as novidades que esse serviço possuir” é o que está acontecendo. Aqui , sua aplicação está falando com o seu serviço e dizendo que, conforme nosso exemplo anterior, deseja receber qualquer notícia que o serviço tiver disponível. Somente isso. Não estamos aqui definindo nada mais do que isso. Obviamente temos detalhes a entender, mas no geral, somente isso já o fará entender o processo.
5 – O passo 5 acontece quando o serviço tem alguma novidade. Imaginem novamente no nosso exemplo de notícias. Temos um feed de notícias que, quando atualizado, irá pró-ativamente disparar a novidade no sentido servidor -> clientes. O importante, além de tudo, é perceber que o servidor de terceiros não conecta diretamente nos celulares, isso obviamente seria uma baita abertura de segurança, mas sim conversa com o MPNS e esse, por sua vez, irá enviar aos celulares a atualização. O servidor de terceiro, usando a lista de URIs recebidas anteriormente e a novidade que deseja mandar (por exemplo, uma novidade de ações, do tipo “Ações da Microsoft sobem 1%”) empacota isso, envia ao MPNS que distribui aos assinantes, através das URIs. Com isso, temos segurança no envio.
6- Depois do MPNS receber a novidade e qual o cliente para envio, isso é repassado diretamente ao celular, que o recebe em forma de Tile, Toast ou Raw Notification, de acordo com o formato da mensagem.
E o que são esses tipos de notificações que podemos receber? Vamos entender um pouco mais quando falarmos de código cliente e como receber essas Push no nosso código.
Código – PASSOS 1, 2 e 3
Ok, vamos ao nosso código e tentar entender todos esses passos.
É necessário termos dois projetos no Visual Studio. Um deles, necessariamente criado no Visual Studio 2010, é um projeto Windows Phone Application, simples, apenas para que possamos mostrar o recebimento das notificações. O outro, que será o nosso código servidor, será uma biblioteca de serviços e podem ser criadas usando WCF, Azure, etc.

Solução 1 – Código cliente. Template Windows Phone Application
O primeiro passo diz que precisamos contatar nosso serviço Push cliente e requisitar uma URI. Esse, por sua vez, irá contatar o MPNS e obter esse “ID” e retornar à aplicação.
Criando um projeto Windows Phone Application você terá um projeto com uma MainPage.xaml. Para testes, usei apenas essa página e você pode fazer o mesmo. Conforme a Listagem 1, no evento OnNavigatedTo, chame o método ConfiguracaoPush.
Listagem 1: Passos 1, 2 e 3
1: private void ConfiguracaoPush()
2: {
3: HttpNotificationChannel canalPush;
4:
5: string nomeCanal = "canal";
6:
7: canalPush = HttpNotificationChannel.Find(nomeCanal);
8:
9: if (canalPush == null)
10: {
11: canalPush = new HttpNotificationChannel(nomeCanal);
12:
13: canalPush.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(canalPush_ChannelUriUpdated);
14: canalPush.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(canalPush_ErrorOccurred);
15: canalPush.HttpNotificationReceived += new EventHandler<HttpNotificationEventArgs>(canalPush_HttpNotificationReceived);
16:
17: canalPush.Open();
18:
19: canalPush.BindToShellTile();
20: canalPush.BindToShellToast();
21:
22: System.Diagnostics.Debug.WriteLine(canalPush.ChannelUri.ToString());
23: }
24: else
25: {
26: canalPush.ChannelUriUpdated +=
new EventHandler<NotificationChannelUriEventArgs>(canalPush_ChannelUriUpdated);
27: canalPush.ErrorOccurred +=
new EventHandler<NotificationChannelErrorEventArgs>(canalPush_ErrorOccurred);
28:
29: System.Diagnostics.Debug.WriteLine(canalPush.ChannelUri.ToString());
30: }
31: }
Começando na linha 3, declaramos um HttpNotificationChannel, que é justamente o canal aberto entre nossa aplicação e o Push Services. Entre a linha 3 e 9 estamos tentando validar se o canal já está aberto e, caso ainda não exista, iremos fazer o que os passos 1 a 3 nos pedem.
Estamos requisitando a abertura de canal e uma URI, que é retornada após o canal estar aberto.
No nosso exemplo, estamos mostrando essa URI no output de Debug. Em uma aplicação final, iríamos enviar essa URI para o serviço de terceiro (passo 4) como uma requisição de assinatura. A URI que recebemos do MPNS se parece com o que mostro na imagem abaixo. Note também que não estou utilizando try catch ou mesmo validando a abertura do canal.

URI recebida pela aplicação
Pontos importantes do código, além da abertura do canal:
-É aqui que estamos gerando nossas assinaturas aos handlers dos eventos. Seja se a URI for atualizada, algum erro ocorrer ou recebermos uma notificação HTTP (Raw notification), já temos nossos eventos respondendo.
-Entre as linhas 19 e 20 temos dois pontos importantes: BindToShellTile e BindToShellToast. Esses dois métodos estão informando que queremos , assim que recebermos mensagens Push, atualizar nosso tile principal ou então mostrar a atualização via Toast. No código estamos colocando isso de forma simplória. Em uma aplicação final é necessário que seja criada uma tela para que o usuário possa explicitamente informar que deseja receber essas atualizações. Em outras palavras, não é permitido pelo Marketplace que a aplicação assine Notifications sem o consentimento do usuário.
Feito isso, estamos prontos, temos a URI única disponível e podemos escrever nosso código servidor que irá enviar código ao MPNS (passo 5). Note que são duas coisas bastante distintas. Uma é o que fizemos acima, obtendo uma URI única (como mencionado, só estamos suprimindo o envio dessa URI para a nuvem, para ser armazenada pelo nosso servidor, pois isso foge ao tópico principal). A outra, é o servidor enviar atualizações ao telefone.
Código – PASSO 5 – Solução 2
Na segunda solução temos o código cliente. No caso atual, foi criada uma solução WPF (Business App) + um conjunto de serviços WCF (O projeto BGAgent não será utilizado nesse exemplo). Você poderia criar uma solução WEB, um console application, etc. A ideia aqui é que usuários de uma determinada aplicação, como por exemplo, a aplicação de ações ou de resultados que mencionei, irão fazer o input de dados nesse aplicativo. Ao fazer isso, a informação será disparada ao MPNS e aos clientes em questão.

Solução 2 – Código Servidor. Solução WPF + Serviços
Assim como na parte cliente, não entraremos em todos os detalhes de código, como UI ou eventos, mas sim tentar entender espeficiamente os passos que fazem o Push funcionar.
Para enviar uma notificação ao cliente precisamos tão e somente escrever um método como o da Listagem 2. Esse método pode ser chamado do disparo de um evento como, por exemplo, clique de um botão, execução de alguma ação de background. Imagem um funcionário digitando a novidade em sua aplicação WEB e, ao clicar em salvar, já disparando para o site e também chamando esse método, que envia aos telefones? É exatamente isso que irá ocorrer.
LISTAGEM 2 – Envia Tile ao cliente
1: protected void btnEnviaTile_Click(object sender, EventArgs e)
2: {
3: try
4: {
5: string httpNotification = this.TextBoxUri.Text;
6:
7: HttpWebRequest request = (HttpWebRequest)WebRequest.Create(httpNotification);
8:
9: request.Method = "POST";
10:
11:
12: string mensagemTile = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
13: "<wp:Notification xmlns:wp=\"WPNotification\">" +
14: "<wp:Tile>" +
15: "<wp:BackgroundImage>" + TextBoxBackgroundImage.Text + "</wp:BackgroundImage>" +
16: "<wp:Count>" + TextBoxCount.Text + "</wp:Count>" +
17: "<wp:Title>" + TextBoxTitle.Text + "</wp:Title>" +
18: "<wp:BackBackgroundImage>" + TextBoxBackBackgroundImage.Text + "</wp:BackBackgroundImage>" +
19: "<wp:BackTitle>" + TextBoxBackTitle.Text + "</wp:BackTitle>" +
20: "<wp:BackContent>" + TextBoxBackContent.Text + "</wp:BackContent>" +
21: "</wp:Tile> " +
22: "</wp:Notification>";
23:
24: byte[] mensagemNotificacao = Encoding.Default.GetBytes(mensagemTile);
25:
26: request.ContentLength = mensagemNotificacao.Length;
27: request.ContentType = "text/xml";
28: request.Headers.Add("X-WindowsPhone-Target", "token");
29: request.Headers.Add("X-NotificationClass", "1");
30:
31: using (Stream streamRequisicao = request.GetRequestStream())
32: {
33: streamRequisicao.Write(mensagemNotificacao, 0, mensagemNotificacao.Length);
34: }
35:
36: HttpWebResponse response = (HttpWebResponse)request.GetResponse();
37: string statusNotificacao = response.Headers["X-NotificationStatus"];
38: string statusCanal = response.Headers["X-SubscriptionStatus"];
39: string statusAparelho = response.Headers["X-DeviceConnectionStatus"];
40:
41:
42: }
43: catch (Exception ex)
44: {
45: this.LabelResponse.Text = "Exceção na notificação: " + ex.Message;
46: }
47:
48: }
Na Listagem 2 estou enviando uma Tile Notification aos clientes.
Na linha 5 buscamos a URI de um TextBox (se estivéssemos enviando as URIs para o servidor, teríamos como buscar aqui de um banco de dados ou coisa do gênero - note, é o conceito de assinantes. Teremos uma listagem de telefones para quem queremos enviar tal mensagem, os listamos e, com um laço, enviamos a todos).
Criamos o request (um simples POST, nada de código proprietário aqui) e precisamos formatar a mensagem. Há formas e wrappers para nos ajudar aqui, e usei isso em artigos e soluções passadas (há um webcast que podem acessar no canal http://www.youtube.com/conexaowindows que mostro isso), porém aqui estou mostrando de forma crua. Há um padrão específico para mandarmos essa mensagem, criar esse xml. Um Tile, no Windows Phone, permite a uma aplicação cliente de terceiro a atualização do seu título, contador e imagem na parte da frente. A parte de trás do tile pode ser atualizada com um título, um pequeno texto de conteúdo e uma outra imagem. São essas propriedades que você vê nas linhas 15-20 e são as possíveis. Veja um tile nas duas imagens abaixo (uma mostrando a parte frontal, a segunda mostra a parte de trás) para entender melhor o que pode ser atualizado.


A partir da linha 24 tudo que temos é a montagem final do XML, seguida do stream e a execução do mesmo, utilizando nossa mensagem. Notem que nosso request é um HttpWebRequest usando a nossa URI única. Ou seja, é aí que sabemos que estaremos executando um POST para o MPNS (passo 5) e não ao telefone. A URI, sendo única, “informa” ao MPNS qual é o cliente (e o Push Client Service, com quem o MPNS conversa, também conhece essa URI). No final, apenas um catch para exceção (somente a genérica, não façam isso em casa!). Há ainda a possiblidade de informar à p´ropria aplicação (ou talvez a um arquivo de log, quem sabe?) sobre o resultado dessa chamada ao MPNS, usando as strings mostradas nas linhas 36-39.
O código para enviar um Toast ou Raw seria o mesmo, diferenciando apenas o formato do xml que estamos enviando. A Listagem 3 mostra o formato do XML de Toast. Já o Raw notification envia um xml que pode ser montado pelo usuário da melhor forma, já que não será consumido em nenhum local específico (Tile notifications são consumidos na tela inicial, toast no topo da tela, ambas acontecem sem a aplicação estar sendo executada . já o Raw é um xml simples que é consumido DENTRO da sua aplicação, apenas para facilitar o envio de novidades e trabalhar de forma a economizar bateria, como nos outros modelos. Ou seja, o Raw não é consumido em um objeto específico, um controle específico, portanto, fica aberto a utilização e consumo do xml da forma que melhor atender o usuário).
Listagem 3 – XML para Toast
1: string toastMessage = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
2: "<wp:Notification xmlns:wp=\"WPNotification\">" +
3: "<wp:Toast>" +
4: "<wp:Text1>" + TextBoxTitle.Text.ToString() + "</wp:Text1>" +
5: "<wp:Text2>" + TextBoxSubTitle.Text.ToString() + "</wp:Text2>" +
6: "<wp:Param>/SecondPage.xaml?NavigatedFrom=Toast Notification</wp:Param>" +
7: "</wp:Toast> " +
8: "</wp:Notification>";
O Toast é formado pela possibilidade de envio de um título, um conteúdo e, depois do update Mango, a possibilidade de Deep Toast, onde você passa um parâmetro e, ao clicar no toast message, o usuário é levado diretamente a uma página interna da aplicação, que pode ser a própria página da novidade que está informando. Faz mais sentido do que apenas entrar na primeira página da app, não? Se eu cliquei na novidade “ações da Microsoft sobem” eu provavelmente queira ver essa novidade, não a página inicial.
Veja na imagem abaixo o que é um toast e entenda, visualmente, um pouco mais o que pode ser alterado.
Toast mostrando um titulo e conteúdo. Ao clicar, podemos levar o usuário a uma página interna
Com esse código escrito, você está pronto para trabalhar com Push Notifications!
Ao executar seu código servidor, estará chamando o MPNS (passo 5) que, por sua vez, enviará a mensagem ao telefone(Passo 6) e o ciclo está completo! Veja nas imagens abaixo o resultado desse código!


Recebendo Tile Notification (frente e trás). Aplicação não está sendo executada

Recebendo Toast Notification – Parte superior da tela. App não está sendo executada. Usuário clica e vai direto ao artigo.
Por hoje é isso, qualquer dúvida podem me contatar no email ou então diretamente no Twitter, http://www.twiter.com/rodocarmo