Bom pessoal, hoje escrevo o artigo em resposta a algumas dúvidas que vem surgindo.

 

Seria o início de uma fragmentação enorme do Windows Phone?

O que preciso fazer?

Devo pensar nesses celulares mais simples?

Em caso de dúvidas mais teóricas e muitas vezes mais filosóficas, sugiro conversarmos no www.rodolphomarques.com . Dê uma olhada nas colunas mensais que escrevo sobre Windows Phone lá, minha opinião, as informações que posso passar, e aí batemos um papo sobre isso. Aqui, nossa ideia será saber como fazer e o que muda.

Apenas uma rápida afirmação: SIM, você DEVE considerar esses telefones. Seja por termos um Nokia barato na jogada, o que deve massificar muito o uso, ou pelo fato de que esses telefones entrarão com tudo em mercados como China e Brasil, fato é, não desconsidere o fato de que aparelhos com 256MB existem. Você vai agradecer por pensar nisso!



O desenvolvimento para esses aparelhos foi adicionado no SDK 7.1.1 , o qual foi lançado em fevereiro. O Thiago escreveu um post sobre o que esse update contém. Clique aqui e leia o post.

 

 

Para nós, o que importa é: você quer que sua aplicação continue executando em qualquer Windows Phone que exista. Quanto mais gente tiver acesso ao seu app, melhor não?
Então as dúvidas são:


-Tendo um app já publicado, como ter certeza que ele funcionará nos novos aparelhos?

 

Vamos responder cada uma delas. Sempre lembrando, aqui estamos tratando de aplicativos XAML. Não entraremos em jogos. O link para saber mais sobre XNA é esse aqui

Se você já tem uma aplicação no Marketplace, você precisa

- Testar se sua aplicação não passa do limite de 90MB.
Sua app não pode usar mais do que esse valor, do contrário, ela não estará disponível para uso nesses aparelhos.
Para isso, você pode verificar usando o "Performance Analysis" no Visual Studio e testar seu aplicativo. Veja as duas imagens abaixo que mostram como acessar essa opção e executar seu aplicativo testando a memória utilizada pela mesma.

 

 

 


Dessa forma você pode entender o uso de memória, CPU, durante todo o ciclo da sua aplicação. Isso é bacana e bastante recomendado, para entender onde estão os pontos críticos, fazer um ajuste fino ou qualquer coisa que possa ajudar a experiência do usuário.

 

 

Uma forma fácil e direta para fazer esse teste dos 90MB é usar o MarketPlace Test Kit (botão direito em cima do projeto, Open Marketplace Test Kit). Essa tool fará os testes automatizados e irá informar se sua aplicação está ok quanto ao pico de memória.

 

 

 

-Validar cada chamada dos Background Agents e os bloquear em dispositivos com 256 MB

Em aparelhos como o Lumia 610 não é permitido o uso de Background Agents. Aliás, é a ÚNICA feature de desenvolvimento que não está habilitada para aparelhos 256. Então é o único ponto que realmente exige atenção. Caso você não os use, parabéns, só checar consumo de memória e seguir adiante. 
Sobre agentes, estamos falando tanto das tasks "periodic" quanto "resource intensive". Então, caso sua aplicação as use, seja para fazer update de tile, sincronização de dados, ou qualquer outro uso, você precisa remover o registro desses agentes nos aparelhos com 256MB. "Mas Rodo, eu quero poder continuar utilizando o recurso em todos os outros aparelhos MAS TAMBÉM disponibilizar meu app aos de 256MB"
É aqui que entra o ApplicationWorkingSetLimit, uma nova propriedade que, passada como parâmetro ao método DeviceExtendedProperties.GetValue entregará a quantidade de memória disponível e dará ao desenvolvedor opções de tratamento diferenciadas em cada caso.
No exemplo do Background Agents, iremos os registrar apenas caso estejamos trabalhando com aparelhos de 512MB.

 
 long result =
(long)DeviceExtendedProperties.GetValue("ApplicationWorkingSetLimit");

Caso o resultado acima seja menos do que 90MB (94371840), estamos falando de um aparelho 256MB. É necessário então não registrar agentes e , claro, importante tentar minimizar o uso de memória. Como já sabemos que nosso aplicativo executou o test kit e passou, apenas vamos adicionar código para registrar o agente somente em caso de aparelhos com 512MB:

  1:             Int64 ram = (Int64)DeviceExtendedProperties.GetValue("ApplicationWorkingSetLimit");
  2: 
  3:             if (ram < 94371840L)
  4:             {
  5:                 string textoAoUsuario = "Não é possivel registrar o Agente. Telefone não é compatível";
  6:             }
  7:             else
  8:                 RegistrarAgente();

Lembrando ainda que o telefone pode não ter sido atualizado. nesse caso a chamada acima gerará uma exceção, por conta do uso do ApplicationWorkingSetLimit. Um Try catch cai bem!


Caso você já tenha sua app, só precisa pensar nisso!

E caso esteja escrevendo um novo aplicativo, comece pensando nas duas questões acima.

Nos dois casos, mas principalmente quando for escever um novo aplicativo (onde ainda não tem a chance de fazer a execução do testkit), lembre..

-OTIMIZAR MEMÓRIA!
Para otimizar memória, lembre:
-Cuidados com uso de imagens, áudio, transições (alguns controles são realmente pesados).
-quando usar lista de dados, pense em virtualização e/ou melhores forma de utilização. não tente carregar uma longa lista toda de uma vez, trazendo muitos objetos do server ao telefone.
-teste, teste, teste. Temos acesso ao novo emulador de 256MB, caso não tenha um telefone para testes. Use o performance analysis, test kit.
 E, caso queira ler mais sobre o assunto performance, um link bom é esse aqui


Por fim, você ainda tema  chance de explicitamente optar por não distribuir seu aplicativo a esses novos aparelhos.
Para restringir esse seu aplicativo aos telefones como o Lumia 610 (o usuário será informado da restrição) é simples:

Vá ao seu arquivo WMAppManifest.xml(estará localizado no seu projeto Windows Phone, pasta Properties). Adicione, logo após a tag "Capabilities" o seguinte código:

  1: <Capability Name="ID_CAP_ISV_CAMERA" />
  2:       <Capability Name="ID_CAP_CONTACTS" />
  3:       <Capability Name="ID_CAP_APPOINTMENTS" />
  4:     </Capabilities>
  5:       <Requirements>
  6:           <Requirement Name="ID_REQ_MEMORY_90" />
  7:       </Requirements>
  8:     <Tasks>
  9:       <DefaultTask Name="_default" NavigationPage="MainPage.xaml" />


A TAG requirements, localizada entre as linhas 5 a 7 é o que é necessário para informar que seu aplicativo não estará disponível para aparelhos mais simples.


Bom, é isso. Lembre que, excluindo os Background Agents, o resto é apenas práticas de performance, que farão bem ao seu aplicativo em QUALQUER cenário. seus usuários agradecerão, com certeza.


E, se querem uma dica, não optem por bloquear seu aplicativo em dispositivos 256MB. O trabalho para adaptar, caso necessário, é pouco.. e valerá a pena!

 

 

 

 

 

Bom pessoal, hoje um artigo para mostrar algo que é bem simples, mas que tem gerado muitas dúvidas no pessoal.

Tenho recebido muitas dúvidas e questões relacionadas a nuvem e ao SkyDrive. Talvez por envolver diferentes APIs e o nome assuste, não sei, mas fato é que parece ser muito mais complexo do que é.

Vamos mostrar hoje como salvar alguma informação da sua aplicação em um arquivo no SkyDrive. Da mesma forma podemos obter a lista de folders na aplicação ou mesmo trabalhar com outros aplicativos Live. Mas hoje o foco é backup na nuvem.

 

Para trabalhar com SkyDrive (e outrs soluções Live) em seu aplicativo Windows Phone, você precisa do SDK da Live para começar. Vá para http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=28195 e faça o download.


 

 

Após isso, adicione as referências ao seu aplicativo:

 

 

 

 

Pronto, agora é só implementar o código!

Para começar, precisamos colocar em algum local do aplicativo um botão para que o usuário possa se logar ao SkyDrive (no caso, o Live ID).

Você pode arrastar/usar o controle SignInButton , que irá encapsular todas as chamadas REST e o processo OAuth necessárias para que o usuário consiga fazer o login.

 

 

 

O código xaml do controle ficará assim:

  1: <my:SignInButton x:Name="skyDriveLogin" ClientId="xxxxxxxxx" 
  2: Scopes="wl.signin wl.basic wl.skydrive wl.skydrive_update" 
  3: Branding="Windows"  TextType="Login" SessionChanged="skyDriveLogin_SessionChanged" 
  4: RedirectUri="" />

 

O ClientID na linha 1 é uma identidade que pecisa ser obtida para seu aplicativo: Vá para dev.live.com e você terá a lista de aplicativos. É só criar um novo aplicativo e irá receber o seu ID.

 

Além disso estamos definindo os escopos com os que queremos trabalhar (note o “update” no sky drive), o Branding é apenas o visual que o botão de login assume (você pode ter o logo do windows, do sky drive, etc..), e o session changed é o evento que iremos utilizar para Logar nosso usuário. O redirectURI também precisa ser uma URI válida!



Vamos ver como a nossa tela fica com o Botão:

 

 

Agora é hora de conectar o nosso usuário. O processo de login ocorrerá chamando a página de login do Live ID e o evento SessionChanged será disparado.

 

Veja a tela de login, de resultado, e o código do evento que mostra a autorização na tela:

 

 

  1: LiveConnectClient client;
  2: 
  3:         private void skyDriveLogin_SessionChanged(object sender, Microsoft.Live.Controls.LiveConnectSessionChangedEventArgs e)
  4:         {
  5:             if (e.Status == LiveConnectSessionStatus.Connected)    
  6:             {    
  7:                 client = new LiveConnectClient(e.Session);    
  8:                 ((App)App.Current).LiveSession = e.Session;    
  9:                 this.txtMensagem.Text = "Autorizado";      
 10:                 
 11:                 client.GetCompleted += new EventHandler<LiveOperationCompletedEventArgs>(OnGetCompleted);  
 12:                 client.GetAsync("me", null);   
 13:             }   
 14:             else   
 15:             {   
 16:                 this.txtMensagem.Text = "Falha no login"; 
 17:                 client = null;  
 18:             }              
 19:         }
 20: 
 21:         void OnGetCompleted(object sender, LiveOperationCompletedEventArgs e)
 22:         {
 23:             if (e.Error == null)
 24:             {
 25:                 if (e.Result.ContainsKey("first_name") &&
 26:                     e.Result.ContainsKey("last_name"))
 27:                 {
 28:                     if (e.Result["first_name"] != null &&
 29:                         e.Result["last_name"] != null)
 30:                     {
 31:                         this.txtUsuario.Text =
 32:                             "Bem vindo " + e.Result["first_name"].ToString() + "" + e.Result["last_name"].ToString() + "!";
 33:                     }
 34:                 }
 35:             }
 36:             else
 37:             {
 38:                 this.txtUsuario.Text = "Erro: " + e.Error.ToString();
 39:             }
 40:         }



Vamos lá, temos 40 linhas, mas a maioria está aí apenas para validações e para mostrar quem está logado.

 

Antes de qualquer coisa, estamos instanciando uma propriedade do tipo LiveConnectClient, que é justamente quem buscará a sessão e fará a chamada ao método que nos possibilitará acesso ao SkyDrive.

Na linha 5 fazemos uso do LiveConnectSessionStatus, que validará se já estamos conectados.

Quando o resultadofor “true”, então começamos o processo de realmente ir buscar informações.

Dois pontos importantes das linhas 7 a 12.

Primeiro, na linha 8, notem que ao invés de recebermos a sessão emuma variável local ao método ou à página, estamos o fazendo com uma propriedade da classe App (arquivoApp.xaml, presente em todo aplicativo WP7
E responsável pelo “container” que são os application pages).

E qual o motivo disso? O fazemos para que seja possível reutilizar essa informação através do aplicativo inteiro.
Quando formos subir nosso arquivo para o SkyDrive, não queremos o fazer através da página de configuração, certo? então estamos mantendo essa informação disponível.

Logo mais a utilizaremos novamente.

 

Já na linha 11 / 12 nos inscrevemos no evento Get e passamos o folder root do SkyDrive (no nosso exemplo
estaremos sempre salvando nessa pasta).

Você pode trabalhar da forma como preferir, inclusive dando a opçãode escolha ao usuário.

 

O evento OnGetCompleted nada mais é do que apenas mostrarmos informações sobre o usuário logado,
como podem ver nas imagens acima.

 

Com isso, o usuário está conectado ao SkyDrive!!

 

Simples, não?

 

Vamos agora entender como subir um arquivo.

 

Para isso, usei um exemplo e uma ideia de um formulário onde o usuário irá colocar alguma informação e a
salvará tanto no IsolatedStorage local, quanto poderá clicar em um CheckBox para também salvar a mesma
infona nuvem, no seu SkyDrive. Isso foi a base criada para o aplicativo que criei para o Devbrasil Summit 2012.

 

Não mostro aqui o código completo da tela, apenas o evento de click no botão “salvar”, com a parte do
Isolated Storage também suprimida.

 

Assim que o usuário clicar no botão “Salvar” na tela abaixo, o código a seguir é disparado:

 

 



  1:         private void btnNotas_Click(object sender, RoutedEventArgs e)
  2:         {
  3:             //SEÇÃO DE CÓDIGO DO ISOLATED STORAGE REMOVIDO
  4: 
  5:             if (chkSkyDrive.IsChecked == true)
  6:             {
  7:                 if ((App.Current as App).LiveSession != null)
  8:                 {
  9:                     string nomeArquivo = codigo + ".txt";
 10:                     byte[] arrayBytes = Encoding.UTF8.GetBytes(this.textNotas.Text);
 11:                     MemoryStream stream = new MemoryStream(arrayBytes);
 12: 
 13:                     LiveConnectClient cliente = new LiveConnectClient((App.Current as App).LiveSession);
 14: 
 15:                     cliente.UploadCompleted += new EventHandler<LiveOperationCompletedEventArgs>(cliente_UploadCompleted);
 16:                     cliente.UploadAsync("me/skydrive", nomeArquivo, stream);
 17:                 }
 18:                 else
 19:                 {
 20:                     MessageBox.Show("É necessário logar no Sky Drive");
 21:                 }
 22:             }
 23:         }

 

 

O código é bastante simples:


Após salvar para o Isolated Storage (o código é 100% separado, ou seja, você pode salvar para o isolated e tratar com um try/catch de forma independente o acesso ao SkyDrive) validamos se o checkbox “Fazer Upload para o SkyDrive” está checado, seguido por validação da sessão (lembram que a usaríamos em nossa segunda tela? é aqui que a utilização da classe “App” faz sentido).

 

Se tudo estiver ok, vamos, na linha 9, criar um nome para o arquivo. aqui utilizei um código qualquer e adicionei o “.txt”. Fiquem livres para criar métodos verdadeiros, códigos ou padrões que façam sentido, assim como folders (e claro, uso de stringbuilders também são bacanas : ) )

 


Na linha 10 vamos buscar o valor do nosso conteúdo (no meu caso, o valor que inseri na imagem acima - “texto para artigo…”) para criação do nosso array de bytes e geramos um stream do tipo MemoryStream a partir desse array.

 

Novamente amos instanciar um LiveConnectClient, na linha 13, assim como fizemos anteriormente para obter os dados do usuário, e é com esse cliente que iremos chamar nosso serviço para fazer o upload.

Note que na linha 16 passamos o parâmetro de root folder para subir o arquivo (obviamente pode ser alterado e o hardcoded retirado), além do próprio nome do arquivo e o nosso stream.

 

Caso o usuário ainda não esteja logado, salvamos no isolated e mostramos a informação a ele. É só ir até a página de configuração, logar, e voltar para salvar na nuvem.

 

 

 

Só isso , Rodo?

 

 

 

Sim, isso e somente isso. abra seu SkyDrive e valide… seu arquivo estará lá!!

E pronto. agora seu aplicativo Windows Phone consegue fazer uploads e backup para a nuvem!

 

 

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.


AP_Tiles_TileComponentsFront


AP_Tiles_TileComponentsBack

 


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

 

 

 

 

Categorias: artigos
Tags:

 

Olá a todos, continuando a série de artigos, hoje vou falar sobre um dos novos templates disponíveis no Visual Studio para a versão Mango, o “Rich Graphics Application” (conhecido na versão beta anterior como “3d graphics application”), que permite ao desenvolvedor renderizar XNA e Silverlight na mesma aplicação. Até agora (versão 7.0) era possível escolher entre XNA ou Silverlight, e sim, até era possível algumas misturas, como utilizar a API de microfone ou touch input do XNA em uma aplicação Silverlight, mas na hora dos gráficos, você precisava escolher. Ou desenvolvia algo em XNA e teria complicações para renderização de texto, integração com IE, vídeos, etc.. Ou então partia para uma app Silverlight, mas tinha algumas dificuldades (e impossibilidades) de usar gráficos 3d ou mesmo criar “cenas” e loops bacanas em sua app. Agora o novo template permita que tudo seja feito em uma app só. É possível ter um xaml renderizando Silverlight, navegar para um segundo xaml renderizando apenas XNA e em um terceiro ter uma mistura dos dois. Vamos ver alguns pontos teóricos onde isso se torna possível

 

 

O TEMPLATE

Nos templates, verá que pode escolher o “Rich Graphics Application”. É o template que vou detalhar para vocês.

 

image

 

Figura 1 – o template

 

 

Ao criar o projeto, você verá algumas coisas interessantes. O projeto é composto por um MainPage.xaml que apenas tem um botão. Esse xaml, assim como essa aplicação, é Silverlight e exatamente o que já conhecemos como desenvolvedores Silverlight.

 

image

Figura 2 – a página inicial é XAML Silverlight que todos conhecemos

 

É importante que o desenvolvedor entenda que usar esse template significa criar uma aplicação Silverlight e adicionar uma renderização XNA onde desejar. Então todos os conceitos e estrutura continuam funcionando da mesma maneira. Teremos nosso app.xaml, MainPage.xaml, vamos seguir as lógicas e tudo que já existe no Silverlight.

A Mudança inicial vem quando você clica no botão. A aplicação navega para uma segunda página, GamePage.xaml, que será um xaml renderizando APENAS XNA. Ou seja, nesse momento o Silverlight ira sair de cena, o WP7 O.S. irá liberar o máximo possível de memória e trará o XNA para a tela. Legal, mas onde está meu conteúdo XNA? Olhando o solution explorer você entenderá

image

Figura 3 – Solution explorer com projeto XNA referenciado

 

Conforme você pode notar no Solution explorer, o XNA é adicionado como um projeto a parte e depois referenciado no projeto Silverlight. Então fica claro que estamos criando nossas texturas e o que precisarmos no XNA, depois o consumindo no Silverlight. Entenda como diversas camadas sendo “desenhadas” na tela. A figura abaixo mostra como isso acontece em uma tela renderizando Silverlight e XNA.

 

image

Figura 4 – as camadas em uma renderização XNA + SL

 

 

 

Legal, mas e como a página “GamePage” consegue renderizar XNA? E como é o código xmal dessa página?

Em uma página 100% renderizada em XNA não há código! O código completo do GamePage.xaml (no início e mesmo após você adicionar qualquer conteúdo XNA) é esse:

  1: <phone:PhoneApplicationPage 
  2:     x:Class="GraphicsApp1.GamePage"
  3:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  4:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  5:     xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
  6:     xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
  7:     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  8:     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  9:     FontFamily="{StaticResource PhoneFontFamilyNormal}"
 10:     FontSize="{StaticResource PhoneFontSizeNormal}"
 11:     Foreground="{StaticResource PhoneForegroundBrush}"
 12:     SupportedOrientations="Portrait" Orientation="Portrait"
 13:     mc:Ignorable="d" d:DesignHeight="800" d:DesignWidth="480"
 14:     shell:SystemTray.IsVisible="False">
 15:     
 16:     <!--No XAML content is required as the page is rendered entirely with the XNA Framework-->
 17: 
 18: </phone:PhoneApplicationPage>
 19: 

 

Ao verificar o code behind GamePage.xaml.cs você tem algumas coisas interessantes e diferentes do que está acostumado, como ContentManager, GameTimer , SpriteBatch ou SharedGraphicsDeviceManager. Mas antes de qualquer coisa, vamos explicar como o XNA renderiza.

Abrindo o arquivo app.xaml há um novo tag:

  1: <xna:SharedGraphicsDeviceManager />



É esse o responsável por fazer a mágica e trazer o XNA do nível mais baixo para a sua aplicação. Como o SharedGraphicsDeviceManager implementa a interface IApplicationLifetimeAware , você o verá como parte dos seus Application.ApplicationLifetimeObjects . Isso é o que possibilita renderizarmos XNA na nossa GamePage. É o SharedGraphicsDeviceManager que vai fazer o motor do XNA acontecer.

Bacana Rodo, mas e aí? Sei que “é possível” renderizar na página, mas aquele XAML não tem nada! Como é que estamos realmente “ligando” o XNA e colocando nosso conteúdo (seja ele qual for) para rodar na página?

Voltando ao code behind do “GamePage”, é importante sempre lembrar do nosso OnNavigatedTo , que é o evento que irá ser disparado quando a navegação chegar na página. Ou seja, toda vez que formos acessar a nossa GamePage, esse evento ocorre. Então, lá nesse evento, o seguinte código é adicionado:

 

  1:         protected override void OnNavigatedTo(NavigationEventArgs e)
  2:         {
  3: SharedGraphicsDeviceManager.Current.GraphicsDevice.SetSharingMode(true);
  4:             spriteBatch = new SpriteBatch(SharedGraphicsDeviceManager.Current.GraphicsDevice);
  5:             // aqui colocamos o código para carregar o conteúdo XNA que quisermos.
  6:             timer.Start();
  7:             base.OnNavigatedTo(e);
  8:         }

 

O código contém a grande mágica, que é a linha onde usamos o SharedGraphicsDeviceManager . É ali que estamos dizendo à aplicação que queremos usar o XNA. O método SetSharingMode nos permite isso. Após isso iremos usar o XNA para desenhar e carregar o que quisermos na tela, como por exemplo:

 

  1: ContentManager appContent = new ContentManager(app, "Content");
  2: fundo = appContent.Load<Texture2D>("background");

 

A segunda parte da mágica ocorre no evento OnDraw, que irá realmente montar os layers na tela. Lá é onde se tornará possível, por exemplo, ter código XAML sendo renderizado junto com o XNA.

 

  1: SharedGraphicsDeviceManager.Current.GraphicsDevice.Clear(Color.CornflowerBlue);
  2: spriteBatch.Begin();
  3: spriteBatch.Draw(background, Vector2.Zero, Color.White);
  4: spriteBatch.End();

 

Aqui limpamos o buffer e depois iremos colocar os layers na tela. Se fôssemos utilizar uma tela com XNA + Silverlight, precisamos explicitamente dizer que queremos renderizar o nosso Silverlight (imaginem que tenhamos adicionado código XAML para termos botões, grids, etc..). Como vocês viram, quando renderizamos XNA, não precisamos (nem iremos) ter nenhum código XAML. Quando adicionarmos código XAML para renderizar Silverlight em uma página, ele simplesmente não aparecerá se o seu SetSharingMode estiver como true. Para renderizar Silverlight + XNA é necessário usar o UIElementRenderer , que vai renderizar um UIElement qualquer do Silverlight junto com o XNA.

É O UIElementeRenderer que possibilita , então, a integração entre ambas as tecnologias. Os conceitos ficam mais ou menos divididos como SharedGraphicsDeviceManager permite que possamos acessar e ligar os motores do XNA em uma aplicação Silverlight, SetSharingMode é o cara que irá nos informar que desejamos renderizar XNA naquela página (e que queremos tirar o Silverlight de cena, por isso mesmo que tenhamos botões e controles Silverlight eles não irão aparecer) e o UIElementeRenderer é o que possibilitará a renderização de ambas as tecnologias. É com esse cara que iremos unir nossos layers, criar as camadas e as desenhar na tela como algo único para o usuário final.

No código acima, por exemplo, iríamos simplesmente adicionar mais uma linha de “Draw” para o Silverlight, montando nossos layers da forma como preferirmos. Se você “desenhar” o XNA primeiro, ele aparece por baixo do Silverlight, e vice versa.

Espero que essa explicação de conceitos do novo template tenha os ajudado um pouco a entender esse que é um dos novos conceitos do mango e que causam um pouco de confusão. Acredito que nesse assunto o mais complicado, muito mais do que entender códigos e demos, é entender como XNA + SL funcionam juntos e, mais do que isso, qual a necessidade do template.


Devo admitir que o código envolvido para fazer as tecnologias se conversarem é simples e a parte complexa fica para o XNA, o qual demanda uma veia artística que esse que vos fala inclusive não possui. O grande porém é que, apesar de simples, são conceitos um pouco diferentes e que demandam entender algumas coisas diferentes do que estamos acostumados a ver no Silverlight. Mas nada que uma demo simples caseira com quadrados e circunferências não resolva! Faça o teste e me conte!


Abraços!

 

Bem pessoal, continuando a série de artigos, hoje vamos falar sobre execução de áudio no background. Um assunto importante para os desenvolvedores que trabalham com o Windows Phone, pois, apesar de já ser possível hoje integrarmos aplicações de terceiros com o hub Music + Videos e fazer uso de algumas ferramentas interessantes, não é possível rodar áudio no background, ou seja, se sua aplicação utiliza áudio internamente, não através do hub de música, assim que o usuário deixa a aplicação, o áudio não está mais disponível.

Para o Mango update, temos alguns novos templates, que você conheceu na parte 1. Um deles é o Windows Phone Audio Playback Agent, que irá nos possibilitar executar músicas que estão no Isolated Storage ou remotas, e que iremos conhecer hoje.

Mãos a obra!

O TEMPLATE

Como comentado no artigo anterior, o template Windows Phone Audio Playback Agent é um dos quatro novos templates disponíveis no Update Mango. Eles se juntam aos templates antigos para oferecer novas possibilidades ao desenvolvedor. O template que trabalharemos é responsável por todo o trabalho pesado de execução do áudio no background, usando o novo conceito de “agentes” (Background Agents). Desse template iremos gerar uma dll , que será referenciada e consumida em um projeto de aplicação Windows phone 7.

CRIANDO O PROJETO

Para começar, crie um novo projeto do tipo Windows Phone Audio Playback Agent no seu Visual Studio 2010.

image

 

 

 

O projeto, ao ser criado, já conta com uma classe AudioPlayer, que faz parte do novo namespace Microsoft.Phone.BackgroundAudio e herda da classe AudioPlayerAgent (que por sua vez herda de BackgroundAgent, mas está fora do nosso escopo), e essa é a classe que fará o trabalho sujo. Alguns eventos já estarão prontos e faremos um player muito simples, que apenas tocará a música, ou seja, Play e Stop. A idéia do artigo é apenas didática, mas um exemplo com mudança de faixas não adiciona complexidade nenhuma, pois envolve apenas algumas regras básicas de contadores e um pouco mais de código. Outro ponto importante é que não estamos utilizando uma classe “music” ou algo do gênero, com melhores práticas, mas que ocuparia muito espaço por aqui. Quem desejar saber mais ou ter um exemplo mais completo, entrem em contato ou acessem meu blog pessoal, pois escrevi esse exemplo em alguns webcasts e posso repassar a vocês O vídeo ou mesmo outros exemplos.

Primeiro passo, vamos escrever um método que tocará nossa música.

  1:         private void PlayMusic(BackgroundAudioPlayer player)
  2:         {
  3:             player.Track = new AudioTrack(new Uri("Stellar.wma",UriKind.Relative)
  4: , "Stellar", "Debutantes99", "Tempestade", null);
  5: 
  6:             player.Play();
  7:         }
  8: 

No exemplo, estamos usandoa instância de player que iremos receber por parâmetro e a propriedade Track (do tipo AudioTrack e que contém as informações da música executada) está sendo populada. Instanciamos uma nova AudioTrack, na ordem dos parâmetros, com a localização, nome, artista, álbum e imagem de capa.

Para que possamos saber como e qual música tocar quando o usuário desejar, e como fazer o Play/Stop, precisamos de código no evento “OnUserAction“, que já estará no arquivo AudioPlayer.cs. O bacana é que você verá inclusive um comentário sobre a necessidade de adicionar código para o handle da ação do usuário. É aqui que iremos chamar no método PlayMusic criado no código anterior. Faça o override, adicionado:

  1: switch (action)
  2: {
  3: case UserAction.Play:
  4: PlayMusic(player);
  5: break;
  6: case UserAction.Stop:
  7: player.Stop();
  8: break;
  9: }

Pontos importantes: a ação Play irá nos levar ao nosso método, já com o Stop estamos utilizando o evento padrão. O caminho é o seguinte: Usuário clica em Play na tela, a classe Audio Player será executada, o evento acima chamado e, por último, nosso PlayMusic é executado.

Pronto. Para uma aplicação simples com Play e Stop é tudo que criaremos nesse projeto. Agora precisamos o referenciar e escrever nosso código na tela.

ADICIONANDO O PROJETO WINDOWS PHONE APPLICATION

Crie um novo projeto Windows Phone Application. Tela mais simples possível, apenas para verificar o processo de execução de áudio.

Adicione a referência ao projeto. Botão direito, add reference, projects e selecione nosso projeto de background criado anteriormente.

image

 

 

Seu arquivo de música deve ser adicionado ao projeto. Após adicionar um arquivo existente de música, botão direito, properties, mude o build action para “content”, conforme figura abaixo.

image

 

 

Não esqueça que, caso esteja usando Isolated Storage, o arquivo precisa ser adicionado, caso contrário, o processo não funciona. O passo não está mostrado aqui, mas adicione a música como sendo um arquivo qualquer de Isolated Storage. Mais um ponto importante, estamos utilizando apenas uma página, sem o conceito de MVVM aplicado. É importante que estude o pattern e possa aplicar em soluções reais.

Após isso, precisamos apenas criar os botões na tela e chamar nosso projeto de áudio. No MainPage.xaml adicione dois botões dentro do grid Content Panel. Também adicione um TextBlock, que irá mostrar ao usuário qual é a música sendo executada. O seu código ficará assim:

  1: <!--ContentPanel - place additional content here-->
  2: <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
  3:   <StackPanel>
  4:     <TextBlock x:Name="currentMusic" Foreground="{StaticResource PhoneAccentBrush}" Height="50" FontStyle="Italic"></TextBlock>
  5:     <Button Content="TOCAR" x:Name="btnPlay" Click="btnPlay_Click"></Button>
  6:     <Button Content="STOPAR" x:Name="btnStop" Click="btnStop_Click"></Button>
  7:   </StackPanel>
  8: </Grid>
  9: 

 

Duplo clique nos botões e você irá gerar o evento de ambos. A listagem abaixo mostra o código do arquivo MainPage.xaml.cs:

  1: public partial class MainPage : PhoneApplicationPage
  2:     {
  3:         // Constructor
  4:         public MainPage()
  5:         {
  6:             InitializeComponent();
  7: 
  8:             BackgroundAudioPlayer.Instance.PlayStateChanged += new EventHandler(Instance_PlayStateChanged);
  9:         }
 10: 
 11:         protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
 12:         {
 13:             if (BackgroundAudioPlayer.Instance.PlayerState == PlayState.Playing)
 14:             {
 15:                 this.currentMusic.Text = BackgroundAudioPlayer.Instance.Track.Artist + " - " + BackgroundAudioPlayer.Instance.Track.Title + " from album " + BackgroundAudioPlayer.Instance.Track.Album;
 16:             }
 17: 
 18:         }
 19: 
 20:         void Instance_PlayStateChanged(object sender, EventArgs e)
 21:         {
 22:             AudioTrack track = BackgroundAudioPlayer.Instance.Track;
 23:             
 24:             if (track != null)
 25:             {
 26:                 this.currentMusic.Text = track.Artist + " - " + track.Title + " from album " + track.Album;
 27:             }
 28:         }
 29: 
 30:         private void btnPlay_Click(object sender, RoutedEventArgs e)
 31:         {
 32:             BackgroundAudioPlayer.Instance.Play();
 33:         }
 34: 
 35:         private void btnStop_Click(object sender, RoutedEventArgs e)
 36:         {
 37:             BackgroundAudioPlayer.Instance.Stop();
 38:         }
 39:     }

Pontos importantes a destacar:

- O event handler no construtor, para que possamos obter a faixa quando o usuário a executar e enviar a mesma ao tetblock.

-O override do OnNavigatedTo. Esse evento é executado quando a navegação vem para a página atual, ou seja, sabemos que o evento rodará quando nosso MainPage for acionado. Dessa forma, vamos tentar obter a música tocando, se o player estiver sendo executado, iremos adicionar os dados ao TextBlock. Isso é importante, pois como nosso áudio funcionará no Background e aplicação pode não estar mais sendo executada (mas o áudio sim), ao voltarmos a ela quero que o texto mostre qual a música atual.

-Os eventos de play e stop nada mais são do que chamadas ao BackgroundAudioPlayer. Mas e quanto aos nossos métodos e eventos criados no projeto anterior? Lembre-se que o que fizemos foi um override no evento que define mudanças de ação do usuário, ou seja, na hora que tivermos um Play por parte do usuário, o OnUserAction será disparado, iremos ver que é um Play e nosso método PlayMusic será executado, fechando o ciclo.

Ao executar a aplicação, temos o resultado:

image

 

CONCLUSÃO

Nesse artigo podemos ver como é fácil na versão Mango rodar um áudio no background, utilizando o poder do framework e do novo template. Temos disponível, assim como o Play e Stop mostrado, o método de Pause, Skip, etc, sendo extremamente fácil adicionar essas funções. Sigam o que viram aqui, criem suas classes para conter uma lista de músicas que desejam executar, utilizem o padrão MVVM para ter um modelO e também código separado da interface, e criem os players dentro da aplicação de forma fácil. Em caso de dúvida, entrem em contato!

LINKS ÚTEIS

MSDN Library
http://msdn.microsoft.com/en-us/library/ff402529(v=VS.92).aspx

 
Podcast Windows Phone
http://www.conexaowindows.com

Blog pessoal
http://www.rodolphomarques.com