Windows Phone 7

O Windows Phone e a nuvem – uma introdução

Ramon Arjona

Estou aprendendo a ler e escrever em espanhol. No lugar onde vivo, posso praticar meu espanhol tentando ler os avisos bilíngues que aparecem em muitos locais públicos. O problema é que, às vezes, paro em uma determinada palavra e não consigo descobrir seu significado ou fico confuso ao ler uma sentença inteira. Também é difícil ter certeza de que entendi o que li, sem poder contar com uma tradução em inglês paralela como referência. Eu poderia levar comigo um dicionário inglês-espanhol, mas ficar folheando todas aquelas páginas é tão analógico.

O que realmente quero, uma vez que meu telefone está sempre à mão, é uma maneira fácil de obter ajuda na tradução através do telefone. Visitar o Bing pelo telefone e usar o Microsoft Translator baseado em nuvem é útil, porém demanda muitos pressionamentos de teclas para chegar à tela de tradução. Se pelo menos existisse uma maneira — uma maneira fácil — de obter o tradutor no telefone. Bem, com o advento do Windows Phone 7, existe.

Este artigo é uma introdução ao desenvolvimento de aplicativos do Windows Phone e mostra como vincular um aplicativo desses a um serviço Web na nuvem. É necessário estar um pouco familiarizado com C# e com o Visual Studio, e seria útil ter pelo menos alguma experiência no desenvolvimento de aplicativos com a linguagem XAML, embora isso não seja requerido. Eu utilizei a atualização de abril do CTP (Community Technology Preview), das ferramentas do Windows Phone. Quando você estiver lendo isto, é possível que tenham ocorrido alterações, então vá para developer.windowsphone.com para ler a documentação mais atual e baixar as ferramentas mais recentes.

Comecemos pelo princípio: Obtendo uma AppID

Se você for interagir com o Translator — ou com qualquer um dos serviços Web do Bing — a primeira etapa é obter uma AppID. Ela é usada pela API do serviço para validar que uma solicitação está vindo de um desenvolvedor de aplicativo registrado do Bing.

Vá para bing.com/developers/createapp.aspx e entre com seu Windows Live ID. Em seguida, preencha o formulário, que solicita o nome e a descrição do seu aplicativo, bem como detalhes como nome e endereço de email da sua empresa. Seu endereço de email é usado para notificar você quando essas APIs forem alteradas; por exemplo, quando novas versões forem disponibilizadas ou quando as versões antigas forem colocadas offline. Para a API do Translator em particular, no momento da sua redação, este documento diz que as versões antigas permanecerão online por 90 dias após o lançamento de uma nova versão.

Em seguida, leia os termos de uso, marque a caixa para indicar que você aceita esses termos e clique no botão “Aceitar” para ir até uma página que contém a sua recém-criada AppID. Sempre é possível voltar a essa página para referência, mas eu geralmente copio e colo minha AppID no arquivo de origem do meu aplicativo quando o crio pela primeira vez.

Leia sempre os termos de uso de um serviço Web que você pretende consumir em um aplicativo. É sério, resista à tentação de apenas fazer uma varredura, especialmente se você pretende distribuir o aplicativo para usuários através do Marketplace. Você deve isso aos seus clientes, precisa entender os objetivos e outras condições no nível de serviço definidos pelos parceiros que fornecem os serviços que o seu aplicativo consome. Então, não deixe de ler e entender os termos de uso, se o seu aplicativo estiver consumindo um serviço da Microsoft ou de terceiros.

Agora que você tem uma AppID, estamos prontos para começar a trabalhar no aplicativo tradutor móvel.

Definindo o cenário

Antes de começar a trabalhar no meu primeiro aplicativo, dei uma olhada em alguns aplicativos móveis bem-sucedidos existentes no mercado. Verifiquei aplicativos para telefones do Windows e outros smartphones para tentar identificar o que torna um aplicativo móvel realmente bem-sucedido. Li análises de produtos. Entrevistei pessoas. Incomodei meus amigos para que me deixassem brincar com seus telefones.

Depois de toda essa pesquisa, concluí que a chave de um aplicativo móvel bem-sucedido é a simplicidade. Todo aplicativo popular supre um ou dois cenários principais do usuário, e faz isso muito bem. Por exemplo, descobri toda uma classe de aplicativos cujo único objetivo é gerar ruídos grosseiros. Na prática, eles são essencialmente uma nova implementação da almofada do pum em um telefone. As pessoas parecem achá-los engraçados, pelo menos o suficiente para pagar para carregá-los em seus telefones.

Da mesma forma, existem aplicativos que simulam um jogo de dados, recomendam um restaurante para o jantar e até mesmo calculam a gorjeta dessa refeição específica. Todos eles focalizam um cenário do usuário e são executados nesse cenário de forma simples e intuitiva. Essa abordagem não é exclusiva de qualquer marca de smartphone em particular. A ideia de que devemos ter uma experiência de usuário refinada e intuitiva é reforçada pelo guia de design e interação de interface do usuário do Windows Phone, publicado em developer.windowsphone.com/windows-phone-7.

Quando comecei a trabalhar no meu aplicativo tradutor, era importante focalizar exatamente o que eu queria que o aplicativo fizesse, e nada mais. Para isso, primeiro precisei ter uma visão clara do que eu queria realizar. Com essa visão em mente, pude resistir à tentação de adicionar novos recursos legais que, embora interessantes, não tinham serventia no principal cenário do usuário. Decidi que meu aplicativo deveria traduzir inglês e espanhol. Ele deveria alternar facilmente os modos de tradução do espanhol para o inglês ou do inglês para o espanhol, e deveria lidar apenas com palavras individuais ou sentenças simples. Além do mais, só me preocupei com o espanhol e o inglês, de forma que meu aplicativo ignorasse outros idiomas.

Compilando o aplicativo

Para começar a compilar o aplicativo tradutor, abra o Visual Studio Express 2010 para Windows Phone. Escolha “New project...” e selecione “Windows Phone Application”. Isso abrirá o projeto padrão do Windows Phone com uma tela dividida em duas seções: Title e Content. Essas seções são delineadas com um objeto Grid da XAML, que permite definir uma série de linhas e colunas nas quais podemos posicionar elementos filho da interface do usuário, como Buttons e TextBlocks (veja a Figura 1).

Figura 1 Projeto padrão do Windows Phone com exibições da tela e do código

Em primeiro lugar, edite o nome e o título da página do aplicativo selecionando esses elementos de interface do usuário no designer. Esse procedimento realça a XAML na janela do modo de exibição de código do designer, mostrando qual elemento você precisa editar. Em seguida, abra a caixa de ferramentas e arraste alguns elementos de interface do usuário para a grade inferior da página, chamada ContentGrid. Escolha uma TextBox, onde colocaremos as palavras a serem traduzidas, em seguida um TextBlock, onde a tradução será renderizada. Finalmente, adicione dois botões (veja a Figura 2).

Figura 2 Adicionando os elementos de interface do usuário TextBox, TextBlock e Button

Um botão executará a tradução e o segundo alternará a direção da tradução, do espanhol para o inglês ou vice-versa.

XAML: a interface do usuário moderna

O coração da experiência do usuário do Windows Phone 7 é o sistema de design chamado “Metro”. E o coração da implementação de uma interface do usuário de acordo com o sistema Metro é a XAML. Se você trabalhou com o Silverlight ou o Windows Presentation Foundation (WPF) anteriormente, provavelmente estará familiarizado com a XAML. Caso contrário, esta seção fornece uma breve introdução.

XAML é uma maneira de estruturar declarativamente a interface do usuário, fornecendo uma rigorosa separação entre a lógica do aplicativo e a sua aparência. Você observará que o código da página principal do aplicativo, por exemplo, está contido em Mainpage.xaml.cs, mas o layout básico do aplicativo está contido em Mainpage.xaml. Ao contrário do desenvolvimento tradicional do Windows Forms, não há mistura do código do aplicativo com o layout da interface do usuário do aplicativo. Cada elemento da interface do usuário no aplicativo é modelado como um elemento XML em um arquivo XAML.

Essa é uma vantagem, pois permite que uma pessoa trabalhe independentemente na aparência do aplicativo, enquanto outra trabalha na lógica do aplicativo. Por exemplo, agora que delineamos a interface do usuário básica do aplicativo tradutor, podemos entregar a XAML a um especialista em interface do usuário enquanto continuamos trabalhando no código. O designer não precisaria saber nada sobre a implementação do meu aplicativo e eu não precisaria saber nada sobre a paleta de cores que ele escolheu.

É claro que eu não tenho nenhum orçamento para um designer de interface do usuário, mas tenho o MSPaint e ele é suficiente para demonstrar como é fácil atualizar os ativos gráficos que acompanham meu aplicativo.

Fornecendo um novo ícone ao Translator

Eu clico duas vezes no ApplicationIcon.png padrão que foi adicionado automaticamente ao projeto quando o criei. Isso abre meu software de edição de imagem, que é o MSPaint, no computador de desenvolvimento. Eu substituo o cansativo ícone de engrenagem por um T maiúsculo. Em seguida, apago o plano de fundo preto e o preencho com um rosa monocromático. Provavelmente, não ganharei nenhum prêmio de design gráfico, mas gosto disso (veja a Figura 3).

Figura 3 Um novo ícone de projeto criado com o MSPaint

Para examinar a alteração, pressiono o botão iniciar para implantar o aplicativo no emulador do Windows Phone 7. Se você trabalhou com versões anteriores de emuladores do Windows Phone, verá imediatamente o quanto a experiência do desenvolvedor foi aprimorada. Trabalhar com o emulador do Windows Phone 6.5 pode ser desagradável e envolve etapas de configuração manual para iniciar e anexar o depurador ao emulador. Aqui no ambiente de desenvolvimento do Windows Phone 7, tudo funciona quando pressiono o botão verde para iniciar. Estou até mesmo satisfeito com a rapidez com que o emulador carrega e exibe a interface do usuário principal do aplicativo (veja a Figura 4).

Figura 4 O aplicativo exibido pelo emulador do Windows Phone 7

Para ver o ícone do aplicativo, eu saio da interface do usuário principal e navego para a tela principal do emulador. O elemento gráfico do tradutor está lá e parece OK (veja a Figura 5).

Figura 5 Verificando o ícone do novo aplicativo no emulador

O manifesto do aplicativo

O ícone do aplicativo é definido em um arquivo chamado WMAppManifest.xml, localizado na pasta Properties do projeto. Para renomear o ícone do aplicativo, altere o nome do ApplicationIcon.png no seu projeto e faça com que a alteração seja refletida aqui, no elemento IconPath:

<IconPath IsRelative="true"
   IsResource="false">myicon.png
   </IconPath>

Se o aplicativo não puder encontrar seu ícone, será atribuído a ele o padrão de tempo de execução, que se parece com um círculo branco em um plano de fundo preto.

Outro elemento desse arquivo que pode ser examinado é o elemento Capabilities, que contém as funcionalidades específicas que o seu aplicativo deseja usar. Convém solicitar exatamente o que o aplicativo precisa, nada mais. Se você examinar o arquivo, verá que ele tem algumas funcionalidades que provavelmente não usaremos no aplicativo tradutor.

Por exemplo, ID_CAP_GAMERSERVICES declara que o aplicativo precisa interagir com APIs do jogo XBox. A funcionalidade ID_CAP_LOCATION diz que o aplicativo deseja utilizar a funcionalidade de local do dispositivo. E ID_CAP_PUSH_­NOTIFICATION diz que o aplicativo deseja interagir com o recurso de notificação por push do Windows Phone 7. Todos esses são ótimos recursos, mas não precisamos deles em nosso aplicativo, então os excluímos. De fato, provavelmente precisamos apenas da funcionalidade ID_CAP_NETWORKING, que diz que o aplicativo deseja usar a rede para enviar e receber dados.

A API do Microsoft Translator

O Microsoft Translator expõe três tipos de APIs. A API SOAP fornece ao consumidor digitação forte e facilidade de uso. A API AJAX é útil principalmente para desenvolvedores de páginas da Web que desejam inserir a tradução em sua interface do usuário. A API HTTP é útil quando nem a API SOAP nem a API AJAX é adequada.

Vamos escolher a interface SOAP, pois é a mais fácil de trabalhar considerando nossos objetivos. Vá para Solution Explorer e clique com o botão direito do mouse em References. Em seguida, escolha “Add a Service Reference” e insira o ponto de extremidade da interface SOAP para a API do Translator: http://api.microsofttranslator.com/V2/Soap.svc. Dê ao ponto de extremidade do serviço o nome TranslatorService na caixa de texto do namespace e clique em OK (veja a Figura 6).

Figura 6 Adicionando uma referência de serviço SOAP

O Visual Studio cuida do resto, gerando o código de cliente da interface SOAP para você.

Agora adicione código ao aplicativo. Adicione a AppID e uma referência ao cliente TranslatorService na declaração da classe MainPage do aplicativo:

string appID = <<your appID>>;
  TranslationService.LanguageServiceClient client = 
    new TranslationService.LanguageServiceClient();

O IntelliSense nos mostra que o serviço tradutor tem alguns métodos interessantes disponíveis. A primeira coisa a observar é que todos os métodos são assíncronos. Isso faz sentido, pois não existe nenhuma boa razão para bloquear o aplicativo cliente enquanto aguardamos a conclusão de uma operação de rede. Isso significa que precisaremos registrar um delegado para cada operação específica que executarmos. No nosso caso, só estamos interessados no método TranslateAsync e no evento TranslateAsyncComplete exposto pelo Language­ServiceClient. Mas os outros métodos certamente parecem interessantes. Vamos dar uma olhada para ver se eles se ajustam ao cenário do nosso usuário.

Dois métodos que se sobressaem são GetLanguagesForTranslateAsync e GetLanguageNamesAsync. O primeiro método fornece uma lista de códigos de idioma que têm o suporte do serviço Translator. Chamando esse método, você pode ver que o código de idioma do espanhol é “es”. O método GetLanguageNamesAsync retorna uma lista de nomes de idiomas para um determinado conjunto de códigos de idiomas, localizado para uma determinada localidade. Por exemplo, se você passar “es” para esse método como a localidade e o código de idioma, obterá de volta a cadeia de caracteres “Español”. Se fôssemos fazer um tradutor multilíngue, ambos seriam úteis.

Outro método interessante chama-se SpeakAsync. Ele aceita uma cadeia de caracteres e uma localidade e retorna uma URL para um arquivo WAV que é a pronúncia de uma palavra com o som nativo. Esse é um recurso incrível. Por exemplo, posso digitar uma cadeia de caracteres, obter a tradução e passar essa cadeia de caracteres para o método SpeakAsync para obter um arquivo WAV que posso usar para me comunicar com outras pessoas em espanhol.  Ou então, se eu não estiver seguro quanto à pronúncia de uma determinada palavra, posso usar o método SpeakAsync para ouvir o seu som.

São recursos bem legais e é difícil resistir à tentação de colocá-los no aplicativo só por isso. Por enquanto. vamos resistir e nos concentrar apenas em suprir o cenário do usuário que delineamos no início. Com essa visão clara em mente, é mais fácil quando nos confrontamos com a tentação de adicionar “apenas mais um recurso”. Tenho certeza de que vou acabar usando os recursos oferecidos na API do Translator em algum ponto, mas não agora.

É fácil conectar o código para criar nosso aplicativo tradutor. Em primeiro lugar, registramos os delegados para TranslateCompleted:

client.TranslateCompleted += new
  EventHandler<TranslationService.TranslateCompletedEventArgs>
  
(client_TranslateCompleted);

Em seguida, implementamos o manipulador de eventos para TranslateCompleted, que define o texto do TextBlock como o texto traduzido:

void client_TranslateCompleted(object sender,
   TranslationService.TranslateCompletedEventArgs e)
 {
   TranslatedTextBlock.Text = e.Result;
 }
We wire up the button to submit the text we’ve entered for translation:
 private void TranslateButton_Click(object sender, 
   RoutedEventArgs e)
 {
   client.TranslateAsync(appID, TranslateTextBox.Text, fromLanguage,
     toLanguage);             
 }

Depois adicionamos um código simples ao segundo botão, para alternar os modos de tradução, “espanhol para inglês” ou “inglês para espanhol”. Esse botão gerencia uma variável de estado global e altera o texto do botão de tradução para indicar esse estado.

Finalmente, implantamos o aplicativo no emulador para testá-lo. Agora temos um aplicativo tradutor totalmente funcional, com apenas algumas linhas de código e cerca de uma hora de tempo de desenvolvimento.

Expandindo o aplicativo tradutor

O aplicativo tradutor simples é bom, mas podemos incrementá-lo expandindo o cenário do usuário. Seria ótimo se pudéssemos vincular mais idiomas oferecidos pela API do Translator ao nosso aplicativo, de forma adequada às diretrizes de design do Metro. E seria ainda melhor se pudéssemos eliminar o botão que gerencia a direção da tradução e utilizar em seu lugar uma maneira mais simples e intuitiva de gerenciar a direção da tradução. Seja qual for a opção que utilizarmos, ela precisa ser amigável para uma pessoa que usa os dedos para interagir com o dispositivo, e precisa ser rápida e fácil.

Então, o que fazemos? Compilamos um aplicativo usando o projeto de lista padrão. Inicie um novo projeto e selecione “Windows Phone List Application”. Isso abre uma tela padrão com um controle ListBox na ContentGrid. A ListBox conterá seis idiomas para os quais desejamos traduzir nosso texto, substituindo o texto fictício (veja a Figura 7).

Figura 7 O aplicativo de lista padrão do Windows Phone

Editaremos o arquivo MainViewModelSampleData.xaml, contido na pasta SampleData do projeto. Você verá algum XML com aparência parecida com esta:

<local:ItemViewModel LineOne="design one" LineTwo="Maecenas praesent
 accumsan bibendum" LineThree="Maecenas praesent accumsan bibendum
 dictumst eleifend facilisi faucibus habitant inceptos interdum
 lobortis nascetur"/>

Editando o XML, você pode alterar o modo de exibição de tempo de design da ListBox para incluir todos os idiomas com os quais desejamos trabalhar: espanhol, alemão, inglês, português, italiano e francês. Observe que, após você salvar esse arquivo, o modo de exibição de tempo de design refletirá suas alterações. Isso ocorre porque o controle da ListBox possui ligação de dados com o elemento Items definido em MainViewModelSampleData.xaml. Isso é controlado pelo atributo ItemsSource do controle da ListBox.

Também é possível atualizar o conteúdo da ListBox em tempo de execução. Se você verificar o arquivo gerado pelo Visual Studio, verá uma Observable­Collection<ItemViewCollection> sendo preenchida com dados de espaço reservado semelhantes aos contidos no arquivo MainViewModelSample­Data.xaml. Por exemplo, se eu quisesse gerar dinamicamente a lista de idiomas na interface do usuário com base nos idiomas retornados pelo método GetLanguageNamesAsync, eu editaria o arquivo MainViewModel.cs para popular a coleção Items. Prefiro especificar uma lista de idiomas estática por enquanto e apenas editar a coleção de objetos ItemViewModel diretamente. Quando executarmos o aplicativo de lista, veremos uma interface do usuário parecida com a Figura 8.

Figura 8 A interface do usuário do aplicativo de lista

Quando o usuário toca um desses botões, ele é levado para uma página de detalhes cuja aparência é essencialmente a mesma da interface do usuário do nosso Simple­Translator. Existe uma TextBox para digitar as palavras a serem traduzidas, um TextBlock para conter o texto traduzido e um botão para enviar a tradução. No entanto, em vez de adicionar outro botão para gerenciar a direção da tradução, vamos utilizar a API do Translator. A tradução bidirecional do nosso aplicativo SimpleTranslator não faz sentido nesse cenário multilíngue, e com a adição de mais camadas de interface do usuário o aplicativo começaria a ficar desajeitado em vez de harmonioso. Felizmente, a API do Translator fornece uma maneira de detectar automaticamente o idioma que está sendo passado.

Adicionamos código para, em primeiro lugar, chamar o método DetectAsync do cliente do tradutor, passando o texto que desejamos traduzir e, em seguida, chamar TranslateAsync a partir do manipulador de eventos DetectAsyncComplete. O manipulador de eventos agora tem esta aparência:

void client_DetectCompleted(object sender, 
  TranslationService.DetectCompletedEventArgs e)
{
  string languageCode = e.Result;
  client.TranslateAsync(appID, TranslateTextBox.Text, fromLanguage, tolanguage);
}

Sabemos para qual idioma desejamos traduzir devido ao botão que o usuário selecionou. Sabemos de qual idioma desejamos traduzir porque a API do Translator o detectou automaticamente. Podemos criar um tradutor simples e multilíngue que permite ao usuário obter uma tradução com apenas dois toques — sem contar a digitação — e menos de uma hora de codificação.

Simplicidade

A simplicidade é o centro do desenvolvimento para o Windows Phone 7. Um aplicativo deve concentrar-se em suprir o cenário de um usuário, e fazer isso muito bem. As ferramentas fornecidas com o Windows Phone 7 SDK CTP, além de tornar isso possível, facilitam a entrega de aplicativos simples e potentes. Vimos também que a interação com a nuvem é direta e que o serviço Web Microsoft Translator pode ser conectado a um aplicativo do Windows Phone com apenas um pequeno investimento do tempo do desenvolvedor. Com ferramentas familiares como o Visual Studio e diretrizes claras como o Metro, o Windows Phone e a nuvem se juntam para abrir um mundo de novas oportunidades para desenvolvedores e usuários.

Ramon Arjona é gerente de teste sênior e trabalha na equipe do Windows na Microsoft.

Agradecemos aos seguintes especialistas técnicos pela revisão deste artigo: VikramDendi e Sandor Maurice