You are on page 1of 58

Com quantas

mentes se
revoluciona
o mundo?

6 a 12 de fevereiro de 2012
Anhembi (SP)

Inovao
Cultura Digital
Cincia
Entretenimento Digital
Unimos talento Criamos futuro
www.campus-party.com.br
@CampusPartyBRA
www.facebook.com/campuspartybrasil
EDITORIAL

O
uso de mdias nos aplicativos extremamente comum, desde
sinais de alertas em aplicativos convencionais at sua vital im-
portncia em jogos. Podemos encontrar desde simples toques
polifnicos at mesmo sons em trs dimenses, com diversos efeitos sonoros, mu-
dando consideravelmente a percepo do usurio em relao ao aplicativo que ele
est usando.
O uso da mdia tambm est sendo utilizado na entrada de dados. Alm dos tecla-
Ano 4 - 39 Edio - 2011 ISSN 1807736-6 dos convencionais, as telas touchscreen, j encontramos sites e aplicativos que requi-
sitam que o usurio fale a informao que deseja inserir no software.
Para telefones celulares e smartphones a importncia das mdias se torna ainda
Corpo Editorial
Atendimento ao Leitor maior devido ateno que o usurio pode dar ao aparelho. Por exemplo: o moto-
A DevMedia conta com um departamento exclu- rista est dirigindo pela auto-estrada quando recebe uma mensagem de SMS. Caso
sivo para o atendimento ao leitor. Se voc tiver
ele precise olhar para o visor do aparelho, estar deixando de prestar ateno onde
algum problema no recebimento do seu exemplar
ou precisar de algum esclarecimento sobre assina- mais importa, na estrada. Se a mensagem fosse lida de forma automtica e repro-
turas, exemplares anteriores, endereo de bancas duzida no sistema de som do prprio automvel, o risco de um acidente diminuiria
Editor Geral
Rodrigo Oliveira Spnola
de jornal, entre outros, entre em contato com: consideravelmente.
editorwebmobile@devmedia.com.br Outro ponto muito importante na ajuda a deficientes visuais. Apesar da conscin-
www.devmedia.com.br/mancad
(21) 3382-5038 cia em relao usabilidade e acessibilidade ter aumentado nos ltimos anos, ainda
Sub Editor pouco provvel encontrarmos um aplicativo para celular ou smartphone que mostre
Eduardo Spnola Publicidade
Para informaes sobre veiculao de anncio na duas informaes na forma textual e oral.
Jornalista Responsvel revista ou no site e para fechar parcerias ou aes Mas, felizmente para ns programadores, todas as plataformas mobile de hoje
Kaline Dolabella - JP24185 especficas de marketing com a DevMedia, entre apresentam APIs que nos permitem inserir e capturar udio e vdeo em nossos apli-
em contato com:
Na Web cativos como Android e JavaME.
www.devmedia.com.br/webmobile/pagina.asp publicidade@devmedia.com.br Neste contexto, esta edio da Mobile Magazine destaca a tema Multimdia em An-
droid e JavaME. Para, isto teremos dois artigos apresentado o tema. O primeiro artigo,
Utilizando sons e imagens em aplicaes Android, mostra parte da API de mdia do
Android utilizando dois exemplos. O primeiro um aplicativo de streaming de mdia,
Fale com o Editor! que pode ser facilmente transformado em uma aplicao completa para rdios. O
Se voc estiver interessado em publicar um artigo na segundo exemplo mostra um lbum de fotos capturadas e persistidas pela prpria
muito importante para a equipe saber o que
revista ou no site Mobile Magazine, entre em contato aplicao. J o segundo artigo, Trabalhando com dados multimdia em aplicaes
voc est achando da revista: que tipo de artigo
com os editores, informando o ttulo e mini-resumo do
voc gostaria de ler, que artigo voc mais gostou CLDC/MIDP com Java ME, apresenta a utilizao de dados multimdia em aplicaes
tema que voc gostaria de publicar:
e qual artigo voc menos gostou. Fique a vontade JavaME.
Rodrigo Oliveira Spnola - Editor da Revista
para entrar em contato com os editores e dar a Alm destas matrias, esta edio da Mobile Magazine ainda traz outros artigos
editorwebmobile@devmedia.com.br
sua sugesto! passando por assuntos como Jogos, Android e .NET Mobile. Tenha uma tima leitura.

D seu feedback sobre esta edio!


NDICE
NDICE
A Mobile Magazine tem que ser feita ao seu gosto. eu
Feedback
Para isso, precisamos saber o que voc, leitor, acha da revista! 04 - Construindo um jogo de Corrida de Carros em Android
s
D

Luiz Fernando Barbosa


sobre e

D seu voto sobre este artigo, atravs do link:


www.devmedia.com.br/webmobile/feedback
s

ta
edio
20 - Desenvolvendo aplicaes para Android com PhoneGap
Mayron Cachina

28 - Utilizando sons e imagens em aplicaes Android


Assinatura Ricardo Ogliari e Robison Cris Brito

38 - Trabalhando com dados multimdia em aplicaes CLDC/MIDP com Java ME


Ricardo Ogliari e Robison Cris Brito
Mais contedo por menos !

48 - MVVM no Windows Phone


A revista WebMobile parte integrante da assitura WebMobile Plus. Paulo Quicoli
Para mais informaes sobre o pacote WebMobile Plus, acesse:
http://www.devmedia.com.br/webmobile/pagina.asp
Construindo um jogo de Cor

A Resumo DevMan
plataforma Android tem como base o kernel 2.6 do Linux.
Sobre ele temos uma mquina virtual chamada Dalvik,
que responsvel por executar as aplicaes. O Android De que se trata o artigo:
padro (pois cada fabricante pode modific-lo) vem com algumas Neste artigo ser apresentada a construo de um jogo de corrida de carros.
aplicaes padres como media player, calendrio, calculadora e Mostraremos de forma prtica e passo a passo os conceitos relacionados ao
SMS/MMS. Alm disso, os usurios de aparelhos Android contam sistema Android para este tipo de jogo.
com uma loja virtual chamada Android Market.
Para a plataforma Android, a Google disponibiliza o Android Em que situao o tema til:
SDK, que um conjunto de ferramentas que provm a infraes- Recentemente, os jogos para celulares ganharam popularidade por fornecer
trutura necessria para a construo de aplicaes, como: biblio- o entretenimento pessoal mvel. Esta popularidade faz com que os jogos de-
tecas de classes e um simulador para que possamos testar nossos sempenhem um papel fundamental na gerao de renda para as operadoras
aplicativos sem a necessidade do aparelho real. Esse SDK est de celulares, desenvolvedores de jogos e fabricantes de aparelhos telefnicos.
disponvel para Windows, OS X e Linux. Neste contexto, este artigo pode ser til para desenvolvedores iniciantes ou
O mercado mvel est em expanso e hoje podemos encontrar experientes que desejam entrar neste fantstico mundo dos jogos.
vrios dispositivos com Android, facilitando assim a sua dissemi-
nao. Outro ponto bastante importante o fato da plataforma ser Construindo um jogo de Corrida de Carros em Android:
livre e ter o seu cdigo fonte liberado, assim como um SDK que O mercado mvel est em expanso e hoje podemos encontrar vrios dispo-
possui um emulador, facilitando o desenvolvimento. sitivos com Android, facilitando assim a sua disseminao. Outro ponto bastan-
Recentemente, os jogos para celulares ganharam popularidade te importante o fato da plataforma ser livre e ter o seu cdigo fonte liberado,
por fornecer o entretenimento pessoal mvel. Esta popularidade assim como um SDK que possui um emulador, facilitando o desenvolvimento.
faz com que os jogos desempenhem um papel fundamental na De acordo com dados sobre o Market - loja de aplicativos para Android OS da
gerao de renda para as operadoras de celulares, desenvolvedores Google, jogos representam entre 30 e 50 por cento do volume de downloads
de jogos e fabricantes de aparelhos telefnicos. de aplicativos. Sendo assim, torna-se um grande nicho para ser explorado
O desenvolvimento de jogos (ler Nota DevMan 1) passa por vrias pelos desenvolvedores, e este artigo vem contribuir neste aspecto.
etapas, e algumas delas so: Game Design; Rascunho dos objetos e
cenrios; Modelagem; Engenharia de Software; e Programao.
O Game Design a etapa onde o jogo criado com suas idias, Ele possibilita a criao de interfaces de usurio, adicionar com-
personagens e estria, ou seja, a concepo propriamente dita. O ponentes, depurar aplicaes utilizando as ferramentas do SDK
rascunho do jogo a etapa do processo que auxilia os modeladores android e exportar os .apk (assinados ou no).
a criarem o mundo do jogo. J a modelagem a etapa onde sero O ADT estende os recursos do Eclipse para permitir que voc
criados modelos e texturas utilizados no jogo. Na engenharia configure rapidamente projetos Android, crie uma aplicao,
de software feita a modelagem do sistema, e na programao, adicione componentes baseados na API do framework Android,
o jogo desenvolvido. Este artigo abordar apenas a etapa da depure suas aplicaes usando as ferramentas do SDK e at ex-
programao. porte APK assinadas (ou no) para distribuir sua aplicao.
Assim, a motivao deste artigo aprender conceitos relaciona- Em geral, usar o Eclipse com o ADT a forma mais recomen-
dos a jogos. Iremos desenvolver um pequeno esboo de framework dada de desenvolver aplicaes Android e o jeito mais rpido de
para o funcionamento e controle do jogo. Neste contexto, neste comear. Se voc usa Eclipse, o plugin ADT lhe fornecer um bom
tutorial desenvolveremos um jogo de corrida usando vrios re- comeo no desenvolvimento de aplicaes Android.
cursos tais como: threads, sprites, soundpool para reproduo de Para instalar e atualizar o plugin ADT, voc pode tirar vanta-
som atravs da API Mdia Player do Android e muitos outros. gem do recurso de atualizao remota do Eclipse. Configurando
um site de atualizao, voc pode facilmente baixar, instalar e
Preparando o ambiente de desenvolvimento verificar atualizaes do ADT. Alternativamente, voc pode
O Android Development Tools (ADT) trata-se de um plugin para baixar a ltima verso do ADT para seu computador como um
o eclipse que facilita a criao rpida de novos projetos Android. arquivo local.

4 WebMobile Magazine - Edio 39


rida de Carros em Android
Luiz Fernando Barbosa

Sendo assim, nosso primeiro passo instalar o SDK do Android


e o plugin ADT no Eclipse. Iremos precisar deles para construir o
nosso jogo e voc pode fazer isto baixando o SDK atravs do site
http://developer.android.com/sdk/index.html.

Nota do DevMan 1
Conceitos de jogos
Para que o leitor possa acompanhar melhor o artigo, vamos relembrar alguns conceitos aqui:
Curva de aprendizagem: o tempo que um jogador necessita para assimilar os comandos e as regras
do jogo. Existem principalmente duas abordagens utilizadas para permitir que o jogador aprenda as
regras e os comandos: (1) atravs da criao de uma fase do jogo, conhecida como tutorial, onde os Figura 1. Verificando o Virtual Device
comandos e as regras so explicitamente demonstrados e (2) atravs da criao de fases iniciais com
nveis de dificuldade baixos. Essas abordagens facilitam a despertar o interesse do jogador.
Tempo de vida do jogo: quantas horas em mdia um usurio vai continuar jogando este jogo antes
de perder o interesse por ele.
Fator de replay: quantas vezes o jogador vai jogar novamente, mesmo j tendo terminado o jogo.
Sprite: um elemento bsico visual que pode ser renderizado a partir de um ou vrios frames de
uma imagem. Estes vrios frames podem ser utilizados para fazer a animao do sprite. Normalmente
corresponde a um objeto na tela do jogo, como um inimigo, o personagem principal, ou um tiro.
FPS (frames per second): significa quadros por segundo. Define quantos quadros so mostrados
ao usurio em um segundo de jogo. Para jogos em celulares, o mnimo aceitvel so 10 quadros por
segundo. Quanto maior a quantidade de quadros por segundo, maior o processamento requerido.
Plataforma-alvo: celular ou conjunto de celulares que sero capazes de rodar o jogo.
Pblico-alvo: pessoas s quais o jogo se destina.
Turno de jogo: conjunto de atividades que o jogo faz a cada frame de jogo. Entre atividades tpicas,
esto repintar a tela, verificar os pontos do jogador ou colises entre os sprites.

Uma vez que voc tenha o SDK e o ADT plugin instalado, hora
de configurar o nosso projeto. Para isso, abra o Eclipse, v em Win-
dow> Android SDK e AVD Manager, clique em virtual devices e
verifique se existe ao menos um dispositivo virtual configurado.
Se no houver, conforme mostra a Figura 1, d um clique no boto
Figura 2. Criando e configurando o Virtual Device
New, preencha o campo Name com um nome sugestivo, adicione-o
selecionando o target Android 2.1 - API level 7, se necessrio infor-
me o tamanho do SD Card a ser criado, se for necessrio capturar Arquitetura bsica do jogo
telas do aplicativo, deixe a opo Snapshot selecionada. Pode-se De uma forma geral, um jogo uma aplicao com resposta em
tambm escolher ou definir as propriedades de resoluo do Skin, tempo real, diferente de uma aplicao para edio de imagens que
assim como tambm acrescentar caractersticas de hardware, tais fica esttica esperando que um evento (comando) seja disparado
como acelermetro, gravar udio, gps e outros. Feito isto, clique pelo usurio. Um jogo tambm espera por estmulos do usurio
no boto Create AVD para criar o dispositivo virtual que ir rodar ou do ambiente, mas enquanto espera, todo um motor j esta
a aplicao de acordo com a Figura 2. em funcionamento.

Edio 39 - WebMobile Magazine 5


Construindo um jogo de Corrida de Carros em Android

Em um sistema Android, por exemplo, temos como principal A aplicao


entrada de dados a tela, que sensvel ao toque. A presso que A nossa engine (motor do jogo) ser formada por:
o usurio faz no touch screen pode ser utilizada como uma Game loop: a repetio do jogo, at o usurio escolher finalizar
entrada de dados, assim como outros sensores tambm podem ou sair do jogo;
ser utilizados no jogo, tais como GPS, microfone, acelermetro, Game Engine (update e draw): responsvel por fazer atuali-
cmera, bssola, e outros. zao dos estados dos objetos e o desenho da tela.
Neste jogo de corrida, o carro ser controlado pelo acelermetro Sprite desenho e coliso (deteco): a abstrao de um objeto
e a velocidade pela presso exercida na tela. O motor do jogo mo- com propriedades distintas e inclusive com a deteco de coliso
nitora o evento onTouch que em cada toque determina a presso e com outro objeto.
com esta iremos determinar a velocidade do carro. O movimento Game Resources (sounds, images): so os recursos utilizados
determinado pela escuta do sensor acelermetro, atualizando no jogo, tais como imagens, fontes, sons e outros.
a posio do carro, e verificando se houve ou no coliso. Caso
positivo, iremos exibir uma sequncia da exploso com o som da Vamos a partir de agora analisar o desenvolvimento de cada um
mesma. Enfim, esta ser a lgica do jogo que utilizaremos. Perceba destes itens de nossa aplicao.
que limitamos sua complexidade justamente para conseguirmos
passar o contedo de forma mais bem explicada neste artigo. Game Loop
Como exemplo de itens que poderiam ser adicionados temos: O Game loop a repetio das principais atividades do jogo,
controle de vidas, de nveis, etc. conforme podemos observar na Figura 3:
Para implementarmos esta arquitetura, nosso jogo ser composto entrada de dados;
de trs mdulos: atualizao (dados do jogo, por exemplo: movimentao, placar,
Lgica do jogo: este mdulo responsvel pela mudana de esta- vidas, etc);
do dos objetos atores do jogo. Com atores quero dizer cada objeto desenho do que se v na tela (dando percepo de movimento).
que tem um estado. Nosso carro, por exemplo, ser deslocado de
acordo com o acelermetro e isso se traduz em calcular a veloci- De acordo com a Figura 3, manipulamos a entrada, poste-
dade do movimento do carro e verificar possveis colises; riormente fazemos a atualizao dos estados e em seguida
Som: este mdulo ir produzir sons considerando a coliso; desenhamos a nova tela. Como se v na figura, a atualizao e
Grficos: este o mdulo responsvel pela apresentao visual desenho esto logicamente ligados e so disparados um aps
do jogo. Isso pode ser to simples como desenhar diretamente o outro.
na tela, atravs de um buffer, ou mesmo algo mais elaborado
utilizando OpenGL (ler Nota DevMan 2).

Nota do DevMan 2
OpenGL
Android inclui suporte para grficos de alto desempenho em 2D e 3D com o Open Graphics Library
(OpenGL), especificamente, a API OpenGL ES. OpenGL uma multi-plataforma API grfica que
especifica uma interface de software padro para hardware de grficos 3D de processamento.
OpenGL ES uma verso da especificao OpenGL destinado para dispositivos embarcados. O OpenGL
ES 1.0 e 1.1 tm sido apoiados desde o Android 1.0. Comeando com o Android 2.2 (API Nvel 8), a
estrutura suporta o OpenGL ES 2.0.
Figura 3. Game Loop Bsico

A taxa de exibio dos objetos na tela medido em FPS Frames Na Listagem 1 o game loop representado em pseudo-cdigo
por Segundo. Se temos uma taxa de 10 FPS, significa que so Java. A listagem demonstra um loop onde so executadas
apresentados 10 imagens a cada segundo. Um filme exibido vrias tarefas de um jogo de forma contnua e o mais rpido
a 24 FPS e a taxa de exibio de um monitor de computador possvel, porm temos um problema simples nesta concepo,
de 60 FPS. Quanto maior a taxa de exibio, mais suave ser a o tempo.
animao, e com certeza mais bem elaborada poder ser. Ima- No caso de um jogo Android, tudo ir ocorrer dentro de uma
gine o deslocamento de um personagem com vrias posies activity. Conforme a Figura 4, a atividade ir criar uma View. A
dos ps, braos e corpo, quanto mais FPS tivermos, mais real View onde tudo acontece, nela temos a principal entrada de
ser a animao. Por outro lado, se a mesma animao for feita dados (Touch Screen), e tambm a principal sada de dados,
com um taxa pequena, no teremos a verdadeira sensao de que a imagem que esta sendo visualizada, conforme podemos
deslocamento. visualizar na Figura 4.

6 WebMobile Magazine - Edio 39


uma classe que nos possibilita um acesso de mais baixo nvel.
Entretanto, para este tutorial utilizaremos a View por ser mais
simples de ser manipulada e satisfazer s nossas necessidades.
Feito isto, vamos partir agora para a anlise da Listagem 4.

Listagem 3. Main.java

package br.com.animacao;

import android.app.Activity;
Figura 4. Game Loop Android import android.os.Bundle;

public class Main extends Activity {


Listagem 1. gameLoop sem controle de tempo private GameView view;
@Override
while (running){ public void onCreate(Bundle savedInstanceState) {
lerEntradas(); super.onCreate(savedInstanceState);
executarAI(); view = new GameView(this);
moverObjetos(); setContentView(view);
verificarColisoes(); }
desenharSprites(); }
tocarMusica();
}
Para facilitar, a implementao da Thread que ir controlar o
Tendo isto em mente, a Listagem 2 nos traz uma rotina de ga- game loop do jogo, a classe GameView estende de View e imple-
meLoop com o acrscimo do controle do tempo. Desta forma, as menta o mtodo Runnable. Nas linhas 23 at 25 criamos a thread
tarefas sero executadas em um tempo constante. Isto ir facilitar que ir fazer o loop infinito do exemplo. Entre as linhas 28 e 37
muito as coisas. Imagine por exemplo que tenhamos um carro que temos o mtodo run, que cuida do loop, fazendo a thread fazer
deve se mover a 10 metros por segundo; ao consideramos o tempo uma pausa e disparando o mtodo update, que ir disparar uma
no game loop, este controle poder ser realizado.

Listagem 2. gameLoop com controle de tempo

lastUpdate = System.currentTimeMillis();
while (running){
if (System.currentTimeMillis() - lastUpdate > 300) {
lastUpdate = System.currentTimeMillis();
lerEntradas();
executarAI();
moverObjetos();
verificarColisoes();
desenharSprites();
tocarMusica();
}
}

Finalizada a concepo de nosso game loop, iremos trabalhar


agora no segundo item de nosso projeto, a game engine.

Game Engine
Este o item da arquitetura de nosso jogo onde cuidaremos da
atualizao dos movimentos (fsica do jogo) e tambm do desenho
na tela. Nas Listagens 3 e 4 temos um exemplo de uma pequena
engine para fazer uma figura se deslocar na tela pelo eixo y.
Na Listagem 3 criamos uma nova View. A View uma classe
simples que nos proporciona o tratamento de eventos (como
onTouch) e um papel em forma de retngulo para podermos
desenhar. A maneira mais simples de cri-la estender da prpria
classe View. Podemos tambm estender da SurfaceView, que

Edio 39 - WebMobile Magazine 7


Construindo um jogo de Corrida de Carros em Android

atualizao da View. J o mtodo draw implementado nas linhas mesmo tempo, alguns representando entidades de IA (inteligncia
43 e 52 define a cor de fundo do canvas para preto. Em seguida, artificial) ou o personagem principal controlado pelo jogador.
calculamos a posio de y e finalmente utilizamos o mtodo Um sprite possui posio(x,y), pode possuir velocidade, som e
drawBitmap do canvas para desenhar na tela o carro na posio at mesmo animao prpria.
calculada. Na Listagem 5 criamos um escopo bsico para o sprite. Este
escopo foi definido porque utilizaremos a reutilizao de c-
digo, ou seja, iremos utilizar herana para evitar repetio de
Listagem 4. Arquivo GameView.java
cdigo . Sendo assim, neste escopo definimos as propriedades e
01. package br.com.animacao; mtodos comuns aos objetos do jogo, tais como posio, limites
02.
da tela, mtodo de desenho, e uma propriedade do tipo Bitmap
03. import android.content.Context;
04. import android.graphics.Bitmap; para armazenar a imagem do objeto. Nas linhas 28 e 38 fazemos
05. import android.graphics.BitmapFactory; a inicializao do sprite. J as linhas 40 a 42 so responsveis por
06. import android.graphics.Canvas;
07. import android.graphics.Color;
desenhar no Canvas o bitmap, na posio de desenho, drawX e
08. import android.util.Log; drawY.
09. import android.view.View; Agora na Listagem 6 temos a classe Carro que estendida da
10.
11. public class GameView extends View implements Runnable {
classe Sprite e implementa o mtodo move e o atributo speed para
12. definirmos o deslocamento do carro na tela. Nas linhas 19 a 24
13. private static final int INTERVAL = 10; implementamos o mtodo move, que verifica se o carro j chegou ao
14. private Bitmap bmpCarro;
15. private boolean running = true; final da tela, se no define uma nova posio para o carro somando
16. private int y; a posio atual com o valor da propriedade speed, caso contrrio
17. define a posio para zero para dar um efeito de continuidade.
18. public GameView(Context context) {
19. super(context); Com isto finalizamos as definies necessrias para a constru-
20. o do jogo.
21. bmpCarro = BitmapFactory.decodeResource(getResources(),
22. R.drawable.carro);
23. Thread minhaThread = new Thread(this); Game Resources
24. minhaThread.setPriority(Thread.MIN_PRIORITY); Os game resources, em nosso estudo de caso, sero os recursos
25. minhaThread.start();
26. }
de som e imagens utilizados no jogo.
27. O jogo de corrida que desenvolveremos neste artigo consiste de
28. public void run() { uma tela principal e vrias classes encapsulando os elementos do
29. while (running) {
30. try {
jogo. Poderemos acrescentar tela de abertura, preferences, confor-
31. Thread.sleep(INTERVAL); me vimos no Artigo Tutorial Android Jogo da Velha publicado
32. } catch (InterruptedException e) { na edio 38 da Mobile Magazine.
33. Log.e(Carro, GameLoop Finalizado!);
34. } Para iniciar, crie um novo projeto Android no Eclipse File> New>
35. update(); Project Android, e preencha os campos conforme a Figura 5.
36. } Nesta figura definimos:
37. }
38. Project Name: onde definimos o nome do projeto;
39. private void update() { Application Name: nome da aplicao;
40. postInvalidate();// Dispara o mtodo draw
Package Name: nome do pacote onde sero criados os arquivos
41. }
42. JAVA do projeto;
43. public void draw(Canvas canvas) { Create Activity: nome da atividade principal;
44. super.draw(canvas);
Min SDK Version: onde definimos qual a menor verso do
45. canvas.drawColor(Color.BLACK);
46. if (y < getHeight() - bmpCarro.getHeight()) { Android na qual a aplicao ir rodar.
47. y+=5;
48. }else{
49. y =0;
Ao concluir as definies, ser gerado um projeto com uma classe
50. } Main.java responsvel por levantar a aplicao. Esta iniciali-
51. canvas.drawBitmap(bmpCarro, getWidth()/2, y, null); zao mais conhecida como Launch e pode ser configurada
52. }
53. }
atravs do arquivo AndroidManifest.xml, conforme ser visto
mais adiante neste artigo.
Toda aplicao Android deve ter um arquivo AndroidManisfest.
Sprite xml presente no diretrio raiz do projeto. AndroidManifest.xml
Em computao grfica, um sprite um objeto grfico bi ou o arquivo de configuraes que permite descrever as funcio-
tridimensional que se move em uma tela sem deixar traos de nalidades e requerimentos do projeto, contendo as informaes
sua passagem. Normalmente, em uma tela temos vrios sprites ao necessrias para a execuo da aplicao.

8 WebMobile Magazine - Edio 39


Listagem 5. Arquivo Sprite.java

01. package br.com.animacao; 64. drawY = this.y - centerY;


02. 65. }
03. import android.content.res.Resources; 66.
04. import android.graphics.Bitmap; 67. public Bitmap getBitmap() {
05. import android.graphics.BitmapFactory; 68. return bitmap;
06. import android.graphics.Canvas; 69. }
07. import android.graphics.Paint; 70.
08. import android.util.Log; 71. public void setBitmap(Bitmap bitmap) {
09. 72. this.bitmap = bitmap;
10. public class Sprite { 73. }
11. 74.
12. private Bitmap bitmap; 75. public int getWidth() {
13. private float x; 76. return width;
14. private float y; 77. }
15. 78.
16. private float centerX; 79. public void setWidth(int width) {
17. private float centerY; 80. this.width = width;
18. private float drawX; 81. }
19. private float drawY; 82.
20. private Paint paint; 83. public int getHeight() {
21. private int width; 84. return height;
22. private int height; 85. }
23. 86.
24. private int widthScreen; 87. public void setHeight(int height) {
25. private int heightScreen; 88. this.height = height;
26. private Resources resources; 89. }
27. 90.
28. public Sprite(Resources resources,int id) { 91. public float getDrawX() {
29. this.resources = resources; 92. return drawX;
30. bitmap = BitmapFactory.decodeResource(resources, id); 93. }
31. this.width = bitmap.getWidth(); 94.
32. this.height = bitmap.getHeight(); 95. public void setDrawX(float drawX) {
33. centerX = 0; 96. this.drawX = drawX;
34. centerY = 0; 97. }
35. setX(0); 98.
36. setY(0); 99. public float getDrawY() {
37. this.paint = new Paint(); 100. return drawY;
38. } 101. }
39. 102.
40. public void draw(Canvas canvas) { 103. public void setDrawY(float drawY) {
41. canvas.drawBitmap(bitmap, drawX, drawY, paint); 104. this.drawY = drawY;
42. } 105. }
43. 106.
44. public void setCenterAtMiddle() { 107. public void setScreenResolution(int width, int height){
45. centerX = bitmap.getWidth() / 2F; 108. this.heightScreen = height;
46. centerY = bitmap.getHeight() / 2F; 109. this.widthScreen = width;
47. } 110. Log.i(Screen,String.valueOf(width)+ , + String.valueOf(height));
48. 111. }
49. public float getX() { 112.
50. return x; 113. public Resources getResources() {
51. } 114. return resources;
52. 115. }
53. public void setX(float x) { 116.
54. this.x = x; 117. public int getWidthScreen() {
55. drawX = this.x - centerX; 118. return widthScreen;
56. } 119. }
57. 120.
58. public float getY() { 121. public int getHeightScreen() {
59. return y; 122. return heightScreen;
60. } 123. }
61. 124. }
62. public void setY(float y) {
63. this.y = y;

Edio 39 - WebMobile Magazine 9


Construindo um jogo de Corrida de Carros em Android

Listagem 6. Arquivo Carro.java

01. package br.com.animacao; 22. else


02. 23. setY(0);
03. import android.content.res.Resources; 24. }
04. import android.graphics.Canvas; 25.
05. 26. @Override
06. public class Carro extends Sprite { 27. public void setY(float y) {
07. 28. super.setY(y);
08. private int speed; 29. }
09. 30.
10. public Carro(Resources resources, int id) { 31. public int getSpeed() {
11. super(resources, id); 32. return speed;
12. } 33. }
13. 34.
14. @Override 35. public void setSpeed(int speed) {
15. public void draw(Canvas canvas) { 36. this.speed = speed;
16. super.draw(canvas); 37. }
17. } 38.
18. 39. }
19. public void move() {
20. if (getY() < getHeightScreen() - getHeight() )
21. setY(getY()+speed);

Nota do DevMan 3
XML o acrnimo de eXtensible Markup Language, uma linguagem de marcao projetada
especificamente para transportar e armazenar dados, a fim de permitir e simplificar a troca de
informaes entre aplicaes estruturalmente disconexas (que no apresentam interfaces comuns).
O seu uso serve as mais variadas necessidades de representao de dados, como transaes de processos
de negcio, dados vetoriais, equaes matemticas, troca de mensagens ou mesmo um cadastro de
clientes, por exemplo. Como os dados so mantidos em formato textual e hierarquicamente organizados
atravs das tags (marcaes) definidas, qualquer software capaz de parsear o arquivo est apto a
processar os dados.
Assim, temos que a linguagem XML (eXtensible Markup Language), resumidamente, define-se como
uma metalinguagem, ou seja, uma espcie de receita para se criar linguagens prprias. O seu uso traz
inmeros benefcios, mas certamente, o maior deles a capacidade de descrever dados de modo a dar
significado aos mesmos. O resultado disso que tanto seres humanos quanto mquinas tm facilidade
em inferir informaes a partir de um documento escrito em XML, o que permite a componentes de
sistemas distintos, desconhecidos originalmente, compreender os dados com a mesma significncia.

Na Figura 6 podemos visualizar os artefatos que foram gerados


automaticamente pelo eclipse. Basicamente, foram gerados todos
os arquivos necessrios para a criao da aplicao. A pasta src/
dentro do pacote app.tictactoe contm a classe Main.java que
representa uma Activity. Dentro da pasta gen/ fica a classe utili-
tria R.java, contendo todas as referencias para os componentes,
permitindo a obteno do recurso pelo nome.
Na pasta res/ ficam localizados todos os recursos da aplicao,
tais como: cones, figuras, msicas, arquivos xml, layouts, etc.
E na raiz do projeto temos o arquivo AndroidManifest.xml. Resu-
mindo, os artefatos gerados esto distribudos em uma estrutura
de diretrios conforme descrito na Tabela 1.

Ciclo de vida
Aplicaes Android so compostas de Activities. Activities repre-
Figura 5. Configurando nossa aplicao sentam a tela de uma aplicao Android. Nela definido o layout da

10 WebMobile Magazine - Edio 39


Arquivo/Pasta Contedo
Scr Pasta que contm os cdigos-fonte do projeto.
Pasta do projeto que contem a classe r.java. Esta classe gerada automaticamente e no deve ser alterada manualmente. Esta classe tem
Gen
classes estticas e constates que fazem referncias aos arquivos XML dentro da pasta res.
Assets Arquivos de dados que sero includos dentro do seu programa. Por exemplo, arquivo de fonte.
res/drawable Pasta com as imagens e cones da aplicao em diversas resolues.
res/layout Pasta com os arquivos XML de configurao de layouts para construo de telas (Ler Nota DevMan 3).
Pasta com os arquivos XML utilizados para a internacionalizao de aplicativos e outras configuraes (Ler Nota DevMan 4). composto de
res/values
um simples XML chave=valor.
Neste arquivo ficam as configuraes globais, tais como o nome e cone da aplicao a verso do Android para qual foi desenvolvida, suas
AndroidManifest.xml
atividades e tambm as intents que a aplicao aceita, e as permisses necessrias para a sua execuo (Ler Nota DevMan 5).

Tabela 1. Estrutura de diretrios

Nota do DevMan 4
Internacionalizao (i18n) o desenvolvimento de uma
aplicao de modo que com a localizao, ela possa se adaptar a
determinado idioma/cultura, ou seja, ser globalizada. Porm, no
apenas traduzir os labels da aplicao, vai muito alm disto, pois
temos pases em que a escrita se d da direta para esquerda, etc.

Nota do DevMan 5
Intents: A classe android.content.Intent representa uma
inteno para executar uma tarefa. Esta inteno enviada para
o Android OS como uma mensagem. Ela pode ser utilizada para Figura 6. Arquitetura da aplicao
lanar (executar) uma atividade, fazer um broadcast, ou iniciar ou
comunicar com um servio.

aplicao, os componentes visuais, botes,


campos de entrada, labels de mensagens,
enfim, todos os elementos visuais.
Cada Activity possui um ciclo de vida
gerenciado pelo sistema operacional que
controla seu estado e fica em uma pilha
de atividade chamada de activity stack,
onde a Activity que est no topo da pilha
pode estar sendo executada ou pausada.
Uma Activity possui sete mtodos utili-
zados pelo sistema operacional para mani-
pular seu ciclo de vida: onCreate(bundle),
onStart(), onRestart(), onResume(), onPau-
se(), onStop() e onDestroy(), conforme
podemos observar na Figura 7. Figura 7. Ciclo de vida da Activity.
De acordo com a Figura 7, temos que pro-
gramar entendendo o ciclo de vida da ativi- programar o mtodo OnDestroy() correta- De acordo com a documentao do
dade. Imagine que o usurio est jogando e o mente, deixando recursos sendo utilizados Android, podemos destacar trs ciclos de
telefone toca, se no houver uma preocupao sem necessidade. Estude bastante este clico vidas de uma atividade:
com os estados da atividade, provavelmente de vida, para mais detalhes d uma olhada Entire lifetime: o ciclo de vida completo
o usurio ir perder o que estava fazendo. em: http://developer.android.com/reference/ da Activity ocorre entre a chamada do
O mesmo se diz, ao sair da aplicao e no android/app/Activity.html mtodo onCreate(bundle) e onDestroy().

Edio 39 - WebMobile Magazine 11


Construindo um jogo de Corrida de Carros em Android

Uma atividade ir fazer toda a configurao global no OnCreate Listagem 7. Arquivo Main.java
(), e liberar todos os recursos remanescentes em onDestroy ().
Visible lifetime: o tempo de vida visvel de uma atividade 01. package br.com.carrace;
02.
acontece entre uma chamada para onStart () at uma chamada 03. import android.app.Activity;
correspondente para onStop (). Durante este perodo a Activity 04. import android.content.pm.ActivityInfo;
05. import android.hardware.SensorManager;
pode estar visvel para o usurio ou aguardando em segundo
06. import android.media.AudioManager;
plano outra Activity terminar. 07. import android.os.Bundle;
Foreground lifetime: o tempo de vida do primeiro plano de uma 08. import android.util.DisplayMetrics;
09. import android.view.Window;
atividade acontece entre uma chamada para onResume () at uma
10. import android.view.WindowManager;
chamada correspondente para OnPause (). Durante esse tempo, a 11.
atividade est na frente de todas as outras atividades e interagindo 12. public class Main extends Activity {
13. private GameView view;
com o usurio. Uma atividade pode alternar entre os estados onRe- 14.
sume() e onPause() com muita frequncia, por exemplo: quando o 15. public void onCreate(Bundle savedInstanceState) {
dispositivo entra em modo sleep, ou quando um resultado de uma 16. super.onCreate(savedInstanceState);
17. SensorManager mSensorManager;
atividade entregue, ou quando uma nova inteno entregue. 18. setRequestedOrientation
Sendo assim, espera-se que o cdigo destes mtodos sejam leves, (ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
evitando consumir recursos preciosos do processador, prejudican- 19. getWindow().addFlags(WindowManager.LayoutParams.
FLAG_FULLSCREEN);
do a aplicao que esta rodando em primeiro plano. 20. getWindow().addFlags(WindowManager.LayoutParams.
FLAG_KEEP_SCREEN_ON);
21. requestWindowFeature(Window.FEATURE_NO_TITLE);
Esta foi uma viso geral do que representa uma Activity no
22. setVolumeControlStream(AudioManager.STREAM_MUSIC);
desenvolvimento e execuo de uma aplicao Android. 23.
24.
Alterando a Atividade Main 25.
26.
// Aponta para uma instancia do SensorManager
mSensorManager = (SensorManager) getSystemService
No passo anterior, o Eclipse gerou automaticamente uma aplicao e (SENSOR_SERVICE);
criou uma atividade. Abra o arquivo Main.java (a atividade principal 27. DisplayMetrics dm = new DisplayMetrics();
28. getWindowManager().getDefaultDisplay().getMetrics(dm);
do jogo) (voc vai encontr-lo no diretrio src no pacote br.com.carrace 29.
pelo painel Project Explorer). O prximo passo no desenvolvimento de 30. view = new GameView(this,
nosso jogo alterar essa atividade de acordo com a Listagem 7. 31. getResources(),dm.widthPixels,dm.heightPixels,mSensorManager);
32. setContentView(view);
Na linha 18, configuramos a orientao da tela como sendo 33. }
modo Portrait retrato, isto evitar que a mesma altere ao 34.
girarmos o equipamento. Na linha 19, definimos o parmetro 35. protected void onDestroy() {
36. super.onDestroy();
FLAG_FULLSCREEN para esconder a barra de status. Na linha 37. view.release();
20, definimos o parmetro FLAG_KEEP_SCREEN_ON para que 38. }
a tela mantenha-se ligada e na linha 21 definimos que a tela no 39. }

ter barra de ttulo.


Na linha 22, configuramos o volume do som. Na linha 26, apon-
tamos para uma instncia do SensorManger. Nas linhas 27 e 28 O GameLoop, responsvel pelo controle do jogo, feito entres as
definimos uma instncia da classe DisplayMetrics para pegarmos linhas 121 e 131, atravs da thread, fazendo pequenos intervalos
o tamanho da tela que utilizaremos para definir os limites da tela. e em seguida disparando o mtodo update e utilizando postIn-
E, por fim, criamos a view GameView, passando alguns parme- validate() para gerar um redesenho da View.
tros e definimos a GameView como contedo da activity. A atualizao, a fsica do jogo ocorre no mtodo update entre
Podemos ver a implementao da classe GameView na Listagem 8. as linhas 134 e 170. Aqui utilizamos o controle do tempo para
Esta classe estendida da classe View e implementa os mtodos termos uma sensao constante de atualizao. Nesta funo
SensorEventListener e Runnable. Entre as linhas 46 e 99, os ob- temos o controle da exploso quando a mesma ocorrer nas
jetos do jogo so instanciados e criados. Nas linhas 79 a 83 con- linhas 139 e 142. Temos um lao de controle para cada carro na
figuramos a ViewGame para aceitar o focus, aceitar click e click lista, checando a visibilidade do mesmo, fazendo a atualizao
longo, para que possamos controlar a velocidade de atualizao da posio, assim como checando se houve coliso. Caso tenha
do jogo. Nas linhas 96 at 98 a thread criada e iniciada, ela ser ocorrido, iremos definir a posio da exploso, iremos tocar o
responsvel pelo game loop. som da exploso e requisitar um redesenho da tela. Por fim,
Para cuidar da velocidade no jogo iremos tratar a presso feita aps o loop nos carros, iremos atualizar o FPS e a atualizao
em qualquer parte da tela para aumentar ou diminuir o tempo de da faixa.
update. Isto feito manipulando o toque no evento OnTouchEvent O mtodo draw, nas linhas 173 at 198, cuida do desenho na
nas linhas 103 at 119. tela, desenhando a exploso se a mesma ocorreu nas linhas 182

12 WebMobile Magazine - Edio 39


at 189. Na linha 191, temos o desenho da faixa. Na linha 193 at 219, caso o evento seja disparado, a posio x do carro do jo-
temos o desenho do carro e nas linhas 195 at 197 o desenho dos gador atualizada. E finalmente temos o mtodo de coliso, que
carros adversrios. responsvel por checar se o carro do jogador colidiu com outro
O carro que o jogador utiliza desloca-se apenas no eixo x, sendo carro. Voc pode verificar isto nas linhas 222 at 242 utilizando
o seu controle feito pelo sensor do acelermetro. Nas linhas 211 interseo.

Listagem 8. Arquivo GameView.java

01. package br.com.carrace; 56. CarroF carro1 = new CarroF(resources, R.drawable.carro2);


02. 57. carro1.setScreenResolution(widthPixels, heightPixels);
03. import java.util.ArrayList; 58. CarroF carro2 = new CarroF(resources, R.drawable.carro2);
04. import java.util.List; 59. carro2.setScreenResolution(widthPixels, heightPixels);
05. 60. CarroF carro3 = new CarroF(resources, R.drawable.carro3);
06. import android.content.Context; 61. carro3.setScreenResolution(widthPixels, heightPixels);
07. import android.content.res.Resources; 62. CarroF carro4 = new CarroF(resources, R.drawable.carro4);
08. import android.graphics.BitmapFactory; 63. carro4.setScreenResolution(width, height);
09. import android.graphics.Canvas; 64.
10. import android.graphics.Color; 65. // Adiciona os carros a lista de carros
11. import android.graphics.Paint; 66. carros.add(carro1);
12. import android.hardware.Sensor; 67. carros.add(carro2);
13. import android.hardware.SensorEvent; 68. carros.add(carro3);
14. import android.hardware.SensorEventListener; 69. carros.add(carro4);
15. import android.hardware.SensorManager; 70.
16. import android.media.AudioManager; 71. // Criar o carro do jogador
17. import android.media.SoundPool; 72. carro = new Carro(resources,R.drawable.carro1);
18. import android.util.Log; 73. carro.setScreenResolution(width, height);
19. import android.view.MotionEvent; 74. // Cria a faixa da rua.
20. import android.view.View; 75. barra = new Barra(resources,R.drawable.barra1);
21. 76. barra.setX(width/2);
22. public class GameView extends View implements SensorEventListener, 77. cPaint = new Paint();
Runnable { 78. // seta a view para receber o focus
23. 79. setFocusable(true);
24. private static final String TAG = GAME VIEW; 80. // seta a view para ser clicavl
25. private SensorManager mSensorManager; 81. setClickable(true);
26. private Sensor mAccelerometer; 82. // seta a view para aceitar o click longo
27. private static final int INTERVAL = 10; 83. setLongClickable(true);
28. private int updateTime = 300; 84. // Cria o SoundPool
29. private Paint cPaint; 85. sounds = new SoundPool(1, AudioManager.STREAM_MUSIC,0);
30. private double aceleracao; 86. // Le o resource de som
31. 87. sExplosion = sounds.load(context, R.raw.batida, 1);
32. private boolean running = true; 88. // Inicializa o nosso contador de FPS
33. List<CarroF> carros = new ArrayList<CarroF>(); 89. fps = new FPSCounter();
34. Carro carro; 90.
35. FPSCounter fps; 91. // Seta cor de fundo do background
36. private Sprite background; 92. this.setBackgroundColor(Color.BLACK);
37. private int width; 93. // Registra a escuta do SensorManager para registrar eventos do
38. private int height; acelerometro.
39. private long lastUpdate; // ultima atualizao 94. mSensorManager.registerListener(this, mSensorManager.
40. private Barra barra; getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
41. private SpriteAnimado explosao; SensorManager.SENSOR_DELAY_GAME);
42. private SoundPool sounds; 95. // Cria uma thread passando como argumento do runnable o
43. private int sExplosion; prprio da classe GameView
44. private boolean explosion=false; 96. Thread monitorThread = new Thread(this);
45. 97. monitorThread.setPriority( Thread.MIN_PRIORITY );
46. public GameView(Context context, Resources resources, 98. monitorThread.start();
int widthPixels, int heightPixels,SensorManager mSensorManager) { 99. }
47. super(context); 100.
48. // Incializa variveis 101. // Trata o evento de toque na tela, iremos pegar a presso do toque
49. this.mSensorManager = mSensorManager; 102. // e utilizar para alterar o tempo de update, para dar sensao
50. this.width = widthPixels; aumento da velocidade
51. this.height = heightPixels; 103. public boolean onTouchEvent(MotionEvent event) {
52. 104. float press=0;
53. explosao = new SpriteAnimado(); 105. press = event.getPressure();
54. explosao.inicializa(BitmapFactory.decodeStream 106. aceleracao = (float) (press * 300);
(resources.openRawResource(R.drawable.explosion)), 107.
120, 160, 24, 20, false); 108. int action = event.getAction();
55. // Criao dos carros 109. if (action == MotionEvent.ACTION_UP ) {

Edio 39 - WebMobile Magazine 13


Construindo um jogo de Corrida de Carros em Android

Continuao: Listagem 8. Arquivo GameView.java

110. updateTime = 300; 180. // Verifica se houve exploso, se sim desenha a exploso e assim
111. return true; que a animao
112. } 181. // terminar, seta a varivel runnig para false, que finaliza o mtodo
113. Run da Thread
114. if (action == MotionEvent.ACTION_DOWN ) { 182. if (explosion){
115. updateTime = 300 - (int) aceleracao; 183. explosao.draw(canvas);
116. } 184. // se a animacao da exploso terminou, setamos running =
117. false para finalizar
118. return super.onTouchEvent(event); 185. // o game loop
119. } 186. if(explosao.dispose)
120. // GameLoop do jogo, responsvel pela execuo dos mtodos 187. running = false;
update e draw 188. return;
121. public void run() { 189. }
122. while (running) { 190. // Desenha a faixa
123. try { 191. barra.draw(canvas);
124. Thread.sleep(INTERVAL); 192. // Desenha o carro do jogador
125. } catch (InterruptedException e) { 193. carro.draw(canvas);
126. Log.e( TAG, game loop interrompido); 194. // Desenha os carrosm
127. } 195. for (CarroF s : carros) {
128. update(); 196. s.draw(canvas);
129. postInvalidate();// Dispara o mtodo draw 197. }
130. } 198. }
131. } 199.
132. 200. public void release() {
133. // Faz update da fisica do jogo. 201. // libera o sensor manager
134. private void update() { 202. mSensorManager.unregisterListener(this);
135. long now = System.currentTimeMillis(); 203. running = false;
136. if ( now - lastUpdate > updateTime) { 204. }
137. lastUpdate = now; 205.
138. // Se houve exploso, faz a atualizao do sprite da exploso 206. @Override
139. if (explosion){ 207. public void onAccuracyChanged(Sensor arg0, int arg1) {
140. explosao.update(now); 208.
141. return; 209. }
142. } 210.
143. // Para cada carro na lista , se estiver invisvel, 211. @Override
inicializa-o novamente 212. public void onSensorChanged(SensorEvent event) {
144. // para evitar a criao de novos objetos, vamos reaproveit-los 213. Sensor sensor = event.sensor;
145. for (CarroF s : carros) { 214. // Verifica se o sensor detectado
146. if(!s.isVisible()){ (disparado do tipo acelermetro, se for
147. s.inicializa(); 215. // move o carro com o valor do evento
148. } 216. if (sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
149. // Atualiza a posio do carro 217. c arro.move(-event.values[0]);
150. s.move(); 218. }
151. // Verifica a se houve coliso, se houve, vamos posicionar o 219. }
sprite da exploso 220.
152. // onde houve o choque 221. // Faz a checagem de coliso entre 2 sprites.
153. if(checkCollision(carro, s)){ 222. private boolean checkCollision(Sprite first, Sprite second) {
154. explosion = true; 223. boolean retValue = false;
155. explosao.setX((int)s.getX()); 224. int width = first.getWidth();
156. explosao.setY((int)s.getY()); 225. int height = first.getHeight();
157. explosao.update(now); 226. int firstXRangeStart = (int) first.getDrawX();
158. // Toca o som da exploso 227. int firstXRangeEnd = firstXRangeStart + width;
159. sounds.play(sExplosion, 1.0f, 1.0f, 0, 0, 1.5f ); 228. int firstYRangeStart = (int) first.getDrawY();
160. // Dispara o mtodo draw 229. int firstYRangeEnd = firstYRangeStart + height;
161. postInvalidate(); 230. int secondXRangeStart = (int) second.getDrawX();
162. break; 231. int secondXRangeEnd = secondXRangeStart + width;
163. } 232. int secondYRangeStart = (int) second.getDrawY();
164. } 233. int secondYRangeEnd = secondYRangeStart + height;
165. } 234. if ((secondXRangeStart >= firstXRangeStart && secondXRangeStart
166. // Faz update do FPS <= firstXRangeEnd)
167. fps.update(); 235. || (secondXRangeEnd >= firstXRangeStart && secondXRangeEnd
168. // Atualiza a animao da faixa <= firstXRangeEnd)) {
169. barra.atualizaBarra(); 236. if ((secondYRangeStart >= firstYRangeStart && secondYRange
170. } Start <= firstYRangeEnd)
171. 237. || (secondYRangeEnd >= firstYRangeStart && secondYRange
172. // Desenha na tela os objetos End <= firstYRangeEnd)) {
173. public void draw(Canvas canvas) { 238. retValue = true;
174. super.draw(canvas); 239. }
175. // Seta cor do paint 240. }
176. cPaint.setColor(Color.WHITE); 241. return retValue;
177. canvas.drawText(FPS: + fps.getFPS(), 20, 20, cPaint); 242. }
178. canvas.drawText(UpdateTime: + String.valueOf(updateTime), 243. }
80, 20, cPaint);
179. cPaint.setColor(Color.BLACK);

14 WebMobile Magazine - Edio 39


A classe Sprite visualizada na Listagem 9 tem como finalidade A classe Carro (apresentada na Listagem 10) estendida da
encapsular caractersticas e aes comuns aos objetos do jogo. classe sprite, implementa o mtodo move nas linhas 16 at 18,
Ela ir armazenar a imagem do objeto, assim como cuidar do lembrando que esta classe ir cuidar do carro do jogador. Sendo
posicionamento e do desenho do objeto na view atravs do m- assim, este carro ter apenas movimento no eixo x. Nas linhas
todo draw. 22 at 29 fazemos uma sobrescrita no mtodo setX, pois aqui ele

Listagem 9. Arquivo Sprite.java

01. package br.com.carrace; 62. public void setY(float y) {


02. 63. this.y = y;
03. 64. drawY = this.y - centerY;
04. import android.content.res.Resources; 65. }
05. import android.graphics.Bitmap; 66.
06. import android.graphics.BitmapFactory; 67. public Bitmap getBitmap() {
07. import android.graphics.Canvas; 68. return bitmap;
08. import android.graphics.Paint; 69. }
09. 70.
10. public class Sprite { 71. public void setBitmap(Bitmap bitmap) {
11. 72. this.bitmap = bitmap;
12. private Bitmap bitmap; // Armazena a imagem 73. }
13. private float x; 74.
14. private float y; 75. public int getWidth() {
15. 76. return width;
16. private float centerX; // Centro x da figura 77. }
17. private float centerY; // centro y da figura 78.
18. private float drawX; // Posio x de desenho, levando em considerao 79. public void setWidth(int width) {
o centro da figura 80. this.width = width;
19. private float drawY; // Posio y de desenho, levando em considerao 81. }
o centro da figura 82.
20. private Paint paint; 83. public int getHeight() {
21. private int width; // largura da imagem 84. return height;
22. private int height; // altura da imagem 85. }
23. 86.
24. private int widthScreen; // largura da tela 87. public void setHeight(int height) {
25. private int heightScreen; // altura da tela 88. this.height = height;
26. private Resources resources; 89. }
27. 90.
28. public Sprite(Resources resources,int id) { 91. public float getDrawX() {
29. this.resources = resources; 92. return drawX;
30. bitmap = BitmapFactory.decodeResource(resources, id); 93. }
31. this.width = bitmap.getWidth(); 94.
32. this.height = bitmap.getHeight(); 95. public void setDrawX(float drawX) {
33. centerX = 0; 96. this.drawX = drawX;
34. centerY = 0; 97. }
35. setX(0); 98.
36. setY(0); 99. public float getDrawY() {
37. this.paint = new Paint(); 100. return drawY;
38. } 101. }
39. 102.
40. public void draw(Canvas canvas) { 103. public void setDrawY(float drawY ) {
41. canvas.drawBitmap(bitmap, drawX, drawY, paint); 104. this.drawY = drawY;
42. } 105. }
43. 106.
44. public void setCenterAtMiddle() { 107. public void setScreenResolution(int width, int height){
45. centerX = bitmap.getWidth() / 2F; 108. this.heightScreen = height;
46. centerY = bitmap.getHeight() / 2F; 109. this.widthScreen = width;
47. } 110. }
48. 111.
49. public float getX() { 112. public Resources getResources() {
50. return x; 113. return resources;
51. } 114. }
52. 115.
53. public void setX(float x) { 116. public int getWidthScreen() {
54. this.x = x; 117. return widthScreen;
55. drawX = this.x - centerX; 118. }
56. } 119.
57. 120. public int getHeightScreen() {
58. public float getY() { 121. return heightScreen;
59. return y; 122. }
60. } 123. }
61.

Edio 39 - WebMobile Magazine 15


Construindo um jogo de Corrida de Carros em Android

ir controlar se o carro est dentro dos limites da tela no eixo x, Listagem 11. Arquivo CarroF.java
evitando assim que o mesmo saia da tela.
01. package br.com.carrace;
02.
Listagem 10. Arquivo Carro.java 03. import java.util.List;
04. import java.util.Random;
01. package br.com.carrace; 05.
02. 06. import android.content.res.Resources;
03. import android.content.res.Resources; 07. import android.graphics.Canvas;
04. import android.util.Log; 08.
05. 09. public class CarroF extends Sprite {
06. public class Carro extends Sprite { 10.
07. 11. private int speed;
08. 12. private boolean visible = false;
09. public Carro(Resources resources,int id) { 13.
10. super(resources,id); 14. public CarroF(Resources resources, int id) {
11. setY(400); 15. super(resources, id);
12. Log.i(Y,String.valueOf(getHeightScreen()) + - +String. 16. }
valueOf( getHeight())); 17.
13. } 18. public void inicializa() {
14. 19. Random generator = new Random();
15. // Atualiza a posio x do carro 20. speed = generator.nextInt((int) 30) + 5;
16. public void move(float x) { 21. setY(0);
17. setX(getX() + x); 22. setX((generator.nextInt((int) 6) + 1) * 40);
18. } 23. visible = true;
19. 24. }
20. // seta o valor de x, fazendo as verificaes necessrias para 25.
que o carro 26. @Override
21. // no saia da tela 27. public void draw(Canvas canvas) {
22. @Override 28. if (this.visible)
23. public void setX(float x) { 29. super.draw(canvas);
24. if (x< getWidth()) 30. }
25. x = getWidth(); 31.
26. if (x> (getWidthScreen() - getWidth())) 32. public void move() {
27. x = getWidthScreen() - getWidth(); 33. setY(getY() + speed );
28. super.setX(x); 34. }
29. } 35.
30. } 36. // Seta posio y do carro verificando, caso tenha alcanado o final
da tela seta o carro
37. // para no visvel
38. @Override
A classe CarroF (apresentada na Listagem 11), estendida da
39. public void setY(float y) {
classe Sprite, utilizada para controlar os carros adversrios. 40. if (y > (getHeightScreen() - getHeight()))
Nas linhas 18 at 31 temos o mtodo inicializa, que sorteia uma 41. this.visible = false;
42. super.setY(y);
velocidade aleatria. O deslocamento dos carros adversrios se 43. }
d no eixo y, sendo assim, definimos o incio para zero. 44.
A rotina tambm faz o sorteio da posio x do carro. O mtodo 45. public boolean isVisible() {
46. return visible;
draw foi sobrescrito, pois o carro deve ser desenhando apenas 47. }
enquanto estiver visvel na View. O mtodo move foi implemen- 48. }
tado para atualizar a posio y adicionando-se a velocidade em
cada passo. Nas linhas entre 38 e 43 temos a sobrescrita do mtodo
setY(), pois temos um comportamento diferente da classe Sprite, Como foi explorado anteriormente, na classe Barra, podemos
verificando se o valor da propriedade y ultrapassou o tamanho da fazer a animao de outra forma tambm, utilizando-se uma
tela menos o tamanho do carro. Se maior, define a propriedade imagem nica, contendo vrias outras imagens. Conforme vemos
visible para false, pois no mais necessrio desenhar o carro, e na Figura 8, temos uma grande figura contendo 20 frames.
ele ser reaproveitado, reincializando-o.
Para visualizarmos uma faixa simulando uma rua, com uma
faixa, criamos a classe Barra, estendida da classe Sprite, conforme a Figura 8. Sprite utilizado na exploso
Listagem 12. A classe Barra representa um sprite animado, contro- E a animao ocorrer fazendo-se a iterao sobre cada uma. O
lando o frame que deve ser desenhado. A cada iterao, l o respectivo mtodo update faz a atualizao da propriedade currentFrame
bitmap, que ocorre no mtodo atualizaBarra entre as linhas 18 e 42. e verifica se chegou ou no ao fim da animao. Caso o objeto
Esta forma de animao bem simples, porm temos vrios ar- deva ficar em loop, define-se currentFrame para zero, caso con-
quivos de imagens. A classe SpriteAnimado traz outra abordagem trrio define-se a propriedade dispose para True, indicando que
de animao conforme podemos observar na Listagem 13. a animao terminou.

16 WebMobile Magazine - Edio 39


Listagem 12. Arquivo Barra.java

01. package br.com.carrace; 27. setBitmap(BitmapFactory.decodeResource(getResources(),


02. R.drawable.barra2));
03. import android.content.res.Resources; 28. break;
04. import android.graphics.BitmapFactory; 29. case 3:
05. 30. setBitmap(BitmapFactory.decodeResource(getResources(),
06. R.drawable.barra3));
07. public class Barra extends Sprite{ 31. break;
08. private int frame; 32. case 4:
09. 33. setBitmap(BitmapFactory.decodeResource(getResources(),
10. R.drawable.barra4));
11. public Barra(Resources resources,int id) { 34. break;
12. super(resources,id); 35. case 5:
13. setCenterAtMiddle(); 36. setBitmap(BitmapFactory.decodeResource(getResources(),
14. frame=1; R.drawable.barra5));
15. } 37. break;
16. 38.
17. // Atualiza a barra (faixa) 39. default:
18. public void atualizaBarra(){ 40. setBitmap(BitmapFactory.decodeResource(getResources(),
19. frame++; R.drawable.barra1));
20. if (frame>5) frame = 1; 41. }
21. 42. }
22. switch (frame) { 43.
23. case 1: 44. public void move(float x, float y) {
24. setBitmap(BitmapFactory.decodeResource(getResources(), 45. setX(getX() + x);
R.drawable.barra1)); 46. setY(getY() + y);
25. break; 47. }
26. case 2: 48.
49. }

Listagem 13. Arquivo SpriteAnimado.java

01. package br.com.carrace; 33. this.sRectangle.bottom = height;


02. 34. this.sRectangle.left = 0;
03. import android.graphics.Bitmap; 35. this.sRectangle.right = width;
04. import android.graphics.Canvas; 36. this.fps = 300 / fps;
05. import android.graphics.Rect; 37. this.numFrames = frameCount;
06. 38. this.loop = loop;
07. public class SpriteAnimado { 39. }
08. private Bitmap bitmap; 40.
09. private int x; 41. public int getX() {
10. private int y; 42. return x;
11. private Rect sRectangle; 43. }
12. private int fps; 44.
13. private int numFrames; 45. public int getY() {
14. private int currentFrame; 46. return y;
15. private long frameTimer; 47. }
16. private int height; 48.
17. private int width; 49. public void setX(int value) {
18. private boolean loop; 50. x = value - (width/2);
19. public boolean dispose; 51. }
20. 52.
21. public SpriteAnimado() { 53. public void setY(int value) {
22. sRectangle = new Rect(0, 0, 0, 0); 54. y = value - (height/2);
23. frameTimer = 0; 55. }
24. currentFrame = 0; 56.
25. dispose = false; 57. // faz a atualizao do frame a ser visualizado
26. } 58. public void update(long gameTime) {
27. 59. if( gameTime > frameTimer + fps) {
28. public void inicializa(Bitmap bitmap, int height, int width, int fps, 60. frameTimer = gameTime;
int frameCount, boolean loop) { 61. currentFrame += 1;
29. this.bitmap = bitmap; 62. // Verifica se acabou a animao, seta o curretFrame para o primeiro
30. this.height = height; 63. if( currentFrame >= numFrames ) {
31. this.width = width; 64. currentFrame = 0;
32. this.sRectangle.top = 0; 65. // Verifica se a animao deve ou no ficar em loop

Edio 39 - WebMobile Magazine 17


Construindo um jogo de Corrida de Carros em Android

Continuao: Listagem 13. Arquivo SpriteAnimado.java

66. if(!loop)
67. dispose = true;
68. }
69.
70. sRectangle.left = currentFrame * width;
71. sRectangle.right = sRectangle.left + width;
72. }
73. }
74.
75. // Desenha o recorte do bitmap.
76. public void draw(Canvas canvas) {
77. Rect dest = new Rect(getX(), getY(), getX() + width, getY() + height);
78. canvas.drawBitmap(bitmap, sRectangle, dest, null);
79. }
80. }
81.
Listagem 14. Arquivo FPSCounter.java Figura 9. Visualizao do jogo
01. package br.com.carrace;
02. Alguns pontos no foram cobertos pelo artigo tais como a utili-
03. import java.text.DecimalFormat; zao de double buffering, surfaceView, interface para definio
04. import android.os.SystemClock;
05. do sprite, dentre outros. Espero que estes pontos possam ser
06. public class FPSCounter { utilizados como sugesto para melhoria futura em seu jogo.
07.
08. public static final DecimalFormat format = new DecimalFormat(###0.00);
09. Luiz Fernando Barbosa
10. private float frames;
11. private String fps;
luizfbarbosa@gmail.com
12. private long start; graduado em Cincia da Computao pela Unitri (Centro Universi-
13. private long current; trio do Triangulo). Trabalha com mobilidade desde 1999, desen-
14. volvendo sistema de fora de vendas. Como hobby desenvolve jogos,
15. public FPSCounter() {
16. start = SystemClock.uptimeMillis(); para PALMOS e Android. Possui MBA em Administrao & Marketing pela
17. frames = 0; FPU (Faculdade Politcnica de Uberlndia), Pos-graduado em Gerncia de Projetos pela
18. fps = ???; Unitri e Pos-graduado em Desenvolvimento JAVA pela Unitri.
19. }
20.
21. public void update() {
22. frames ++; http://code.google.com/android/intro/installing.html
23. current = SystemClock.uptimeMillis();
24. if( current - start > 1000 ){
Descreve a instalao passo a passo do SDK Android
25. fps = format.format(frames);
26. frames = 0;
http://code.google.com/android/intro/anatomy.html
27. start = current; Descreve a anatomia de uma aplicao android.
28. }
29. } http://code.google.com/android/reference/android/app/Activity.html
30.
31. public String getFPS() {
Descreve uma Atividade e seu ciclo de vida
32. return fps;
33. }
http://developer.android.com/guide/topics/ui/menus.html
34. } Descreve a criao de menus
http://developer.android.com/guide/topics/media/index.html
O mtodo draw desenha o respectivo frame na tela. Particular- Descreve o funcionamento do framework de multimdia do sistema
mente esta abordagem mais interessante e at poderia servir de Android
base para a classe Sprite.
http://android-er.blogspot.com/
Para finalizar temos a classe FPSCounter, que pode ser visualizado
Site com bastante contedo e cdigos de exemplo
na Listagem 14. Sua finalidade podermos visualizar a taxa de
atualizao em Frame Rate do jogo.
Aps digitar todas estas classes e executar o seu projeto, o resul- D seu feedback sobre esta edio! eu
Feedback
s

tado ser como o visualizado na Figura 9.


D

A Mobile Magazine tem que ser feita ao seu gosto. Para isso, precisamos
sobre e

saber o que voc, leitor, acha da revista!


Concluso
s

ta
edio

Neste artigo foram apresentados vrios recursos para o desen- D seu voto sobre este artigo, atravs do link:
volvimento de um jogo simples no Android, e atravs da aplicao www.devmedia.com.br/webmobile/feedback
desenvolvida foi ilustrada a aplicao destes conceitos.

18 WebMobile Magazine - Edio 39


Desenvolvendo aplicaes p
Criando um gerenciador de corridas

C Resumo DevMan
om a disseminao dos smartphones e o uso cada vez
mais frequente da internet, difcil no estar conectado
na rede, acessando o e-mail ou redes sociais, como Face- De que se trata o artigo:
book e Twitter. Todos estes servios disponibilizam um aplicativo Apresentaremos neste artigo a implementao de um aplicativo para o
para uso em smartphones, seja ele Android, iOS ou outro sistema sistema operacional Android utilizando as tecnologias HTML, CSS e JavaS-
operacional. Tais aplicativos so chamados de webapps, ou seja, cript. Para isso, analisaremos como montar o ambiente de desenvolvimento
precisam estar conectados internet para disponibilizarem os utilizando a IDE Eclipse e o Android SDK.
seus servios. Pensando nisso, nesse artigo iremos conhecer o
PhoneGap, um framework que nos auxiliar na criao de apli- Em que situao o tema til:
cativos desse tipo. Este tema til ao abordar mais uma importante ferramenta para o desen-
O PhoneGap um framework voltado para o desenvolvimento volvimento de aplicaes mveis. Apesar de termos estudado apenas a codi-
de aplicaes para dispositivos mveis, open source, multiplata- ficao de um exemplo Android, o PhoneGap tambm pode ser adotado para
forma, com suporte para os sistemas operacionais iOS, Google criar aplicativos para dispositivos como iPhone, BlackBerry, entre outros.
Android, Palm, Symbian e BlackBerry. Com ele possvel desen-
volver aplicaes utilizando as tecnologias JavaScript, HTML Desenvolvendo aplicaes para Android com PhoneGap:
5 e CSS3, dispensando assim o uso de SDKs ou compiladores, Neste artigo destacaremos o desenvolvimento de um aplicativo para o
bastando apenas adicionar um arquivo JavaScript e um JAR para sistema operacional Android utilizando o framework PhoneGap e as tecnolo-
ter acesso a vrias funes de seu smartphone. gias HTML, CSS e JavaScript. Nele, analisaremos tambm o uso do framework
O JavaScript tem se transformado na linguagem de progra- jQuery Mobile para criar uma interface mais amigvel e como configurar um
mao mais popular da web. Inicialmente, no entanto, muitos ambiente de desenvolvimento utilizando a IDE Eclipse e o Android SDK.
profissionais denegriram a linguagem. Com o advento do Ajax,
o JavaScript teve sua popularidade de volta e recebeu mais aten- de informao, tais como o contedo de um correio eletrnico,
o profissional. O resultado foi a proliferao de frameworks e para o servidor. A tendncia mais ampla de programao em Ajax
bibliotecas, prticas de programao melhoradas e o aumento no explora de maneira similar este ponto forte.
uso do JavaScript fora do ambiente de navegadores bem como o Uma JavaScript engine (tambm conhecida como interpretador
uso de plataformas de JavaScript server-side. JavaScript ou uma implementao JavaScript) interpreta cdigo
O uso primrio de JavaScript escrever funes que so em- fonte JavaScript e o executa de forma adequada. A primeira im-
barcadas ou includas em pginas HTML e que interagem com plementao JavaScript foi criada por Brendan Eich na Netscape
o Document Object Model(DOM) da pgina. Alguns exemplos Communications Corporation, para o Navegador Netscape. A
deste uso so: implementao, nomeada SpiderMonkey, implementada em C e
abrir uma nova janela com controle programtico sobre seu vem sendo atualizada para estar em conformidade com a edio 3
tamanho, posio e atributos; do ECMA-262. A implementao Rhino, criada primariamente por
v alidar valores de um formulrio para garantir que so aceitveis Norris Boyd (ex-empregado da Netscape; agora no Google) uma
antes de serem enviados ao servidor; implementao de JavaScript em Java. Rhino, como SpiderMoneky,
m udar imagens medida que o mouse se movimenta sob elas. est em conformidade com a terceira edio do ECMA-262.
Por ser o JavaScript a nica linguagem que a maioria dos na-
Pelo fato do cdigo JavaScript rodar localmente no navegador vegadores populares suportam, tem se tornado uma linguagem
do usurio, e no em um servidor remoto, o navegador pode alvo para muitos frameworks em outras linguagens, a despeito
responder a tais aes rapidamente, aprimorando desta forma o do fato de no ter sido planejado para tal.
tempo de resposta para o usurio. Alm disso, o cdigo JavaScript Atualmente o PhoneGap se encontra na verso 1.0, e alguns dos
pode detectar aes de usurio que o HTML sozinho no poderia, destaques deste release so:
tais como teclas pressionadas individualmente. Aplicaes como API mais estvel;
Gmail tomam vantagem disso: muito da lgica da interface do Arquitetura plugvel, permitindo a criao de componentes;
usurio escrita em JavaScript, e o JavaScript envia requisies Compatibilidade com acesso a dados padronizados pelo W3C;

20 WebMobile Magazine - Edio 39


ara Android com PhoneGap
Mayron Cachina

Possibilidade de manipulao dos contatos da agenda telefnica. facilidade de configurao. Para podermos utilizar os recursos
do Android no Eclipse, o Google disponibiliza um SDK que for-
Alm destes, o framework oferece diversos recursos que auxi- nece uma mquina virtual, suporte para mdias de udio, vdeo
liam o seu uso. A Figura 1 apresenta os recursos suportados em e imagem, nos formatos MPEG4, H.264, MP3, AAC, AMR, JPG,
cada plataforma. PNG, GIF, bem como acelerador grfico 3D, baseado no OpenGL.
Deste modo, faa o download do SDK no link http://developer.
android.com/sdk/index.html.
Agora, acesse o diretrio onde foi realizada a instalao do
Android SDK, execute o aplicativo SDK Manager, escolha a opo
Available Packages e a plataforma Android 2.1. Por fim, selecione
Install Selected, conforme a Figura 2.

Figura 1. Recursos suportados por cada plataforma

O PhoneGap j est sendo utilizado por diversas empresas, como


o caso da Adobe, que integrou o framework ao Adobe Dreamwe-
Figura 2. SDK Manager, download da plataforma
aver, facilitando a criao de aplicativos para dispositivos mveis,
podendo ainda testar estes aplicativos em emuladores a partir do
prprio editor do Dreamweaver. Aps a instalao do SDK, preciso configurar o Eclipse com o
Para as prximas verses, os desenvolvedores do PhoneGap plugin ADT - Android Developer Tools. Assim, no Eclipse, selecione
esto planejando suporte a outras plataformas e novas APIs, que o menu Help > Install New Software, clique em Add..., e em Lo-
podero ter acesso a funcionalidades como calendrio do smart cation, informe o endereo: https://dl-ssl.google.com/android/eclipse/,
phone, websockets, criptografia, entre outras. como apresentado na Figura 3. Depois de encerrada a instalao,
Nesse artigo, iremos apresentar, passo a passo, como configu- reinicie o Eclipse.
rar o ambiente de desenvolvimento para a implementao com
Android e iniciar a codificao de um aplicativo utilizando o
framework PhoneGap. O objetivo de nosso sistema ser auxiliar
corredores a gerenciar seus treinos.

Preparando o ambiente de desenvolvimento


Neste momento, poderamos optar pelo desenvolvimento para
iOS, Symbian ou outras plataformas, mas como nosso objetivo
apresentar o PhoneGap, adotaremos o Android devido sua Figura 3. Adicionando a URL do plugin ADT

Edio 39 - WebMobile Magazine 21


Desenvolvendo aplicaes para Android com PhoneGap

Para finalizar a configurao, acesse o menu Window > Prefe-


rences e depois a opo Android, para informar o local onde foi
instalado o SDK, como mostra a Figura 4.

Figura 4. Configurando o path do Android SDK no Eclipse

Criando uma mquina virtual


Para executar as aplicaes desenvolvidas com PhoneGap, pre-
cisamos ainda criar uma mquina virtual, que ser responsvel
por emular o ambiente Android (ler Nota DevMan 1). Para isso,
selecione no menu do Eclipse Window > Android SDK and AVD
Manager, clique em New... e informe a configurao da mquina,
de acordo com a Figura 5.
Figura 5. Configurando a mquina virtual

Nota do DevMan 1 Iniciando o projeto


Para iniciar a implementao de nosso aplicativo, devemos agora
Mquina Virtual criar um projeto Android. Para isso, abra o Eclipse e selecione File
O termo mquina virtual foi descrito na dcada de 1960 utilizando um termo de sistema > New >Other > Android Project, conforme a Figura 6.
operacional: uma abstrao de software que enxerga um sistema fsico (mquina real).
Com o passar dos anos, o termo englobou um grande nmero de abstraes por
exemplo, Java Virtual Machine JVM que no virtualiza um sistema real.
Ao invs de ser uma mquina real, isto , um computador real feito de hardware e
executando um sistema operacional especfico, uma mquina virtual um computador
fictcio criado por um programa de simulao. Sua memria, processador e outros
recursos so virtualizados. A virtualizao a interposio do software (mquina virtual)
em vrias camadas do sistema. uma forma de dividir os recursos de um computador em
mltiplos ambientes de execuo.
Os emuladores so mquinas virtuais que simulam computadores reais. So bastante
conhecidos os emuladores de vdeo games antigos e os emuladores de microcomputadores,
como o VMware, o Bochs e o VM VirtualBox, software livre da Oracle.
Algumas das vantagens que se tem ao se trabalhar com mquinas virtuais so:
Facilita o aperfeioamento e testes de novos sistemas operacionais;
Possibilita a comparao de vrios sistemas operacionais utilizando o mesmo
equipamento; Figura 6. Criando o projeto Android
Executa diferentes sistemas operacionais sobre o mesmo hardware, simultaneamente;
Simula alteraes e falhas no hardware para testes ou reconfigurao de um sistema No campo Project Name (ver Figura 7), informe um nome para
operacional, provendo confiabilidade e escalabilidade para as aplicaes.
o projeto, como HelloWorld, em Build Target, selecione a verso
Diminuio de custos com hardware; da API que ir trabalhar, no nosso caso, Android 2.1-update1.
Facilidades no gerenciamento, migrao e replicao de computadores, aplicaes ou Por ltimo, defina em Package name um pacote chamado br.com.
sistemas operacionais; cachina, e o nome da Activity, neste caso, HelloWorldActivity.
Confiana e disponibilidade: A falha de um software no prejudica os demais servios. Lembrando que podemos ter quantas activities forem necessrias,
no entanto, possvel executar apenas uma por vez.

22 WebMobile Magazine - Edio 39


aplicao no seja reiniciada (o mtodo onCreate() executado
toda vez que acontece este evento). Precisamos tratar eventos como
esse para no ter problemas de ficar reiniciando nosso programa.
Na Listagem 3, segue o cdigo para evitar que isso acontea.

Listagem 1. Configurando o PhoneGap na Activity.

package br.com.devmedia;

import android.os.Bundle;

import com.phonegap.*;

public class HelloWordActivity extends DroidGap {


/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.loadUrl(file:///android_asset/www/index.html);
}
}

Listagem 2. Permisses de acesso do aplicativo.

Figura 7. Criando o novo projeto ...


<uses-sdk android:minSdkVersion=8 />

Para poder utilizar o PhoneGap, preciso adicionar algumas <supports-screens android:largeScreens=true


bibliotecas e configurar o nosso projeto. android:normalScreens=true android:smallScreens=true
android:resizeable=true android:anyDensity=true />
Deste modo, baixe a verso mais nova no endereo http://code.
<uses-permission android:name=android.permission.VIBRATE />
google.com/p/phonegap/downloads/list e descompacte o arquivo <uses-permission
zip. O arquivo conter todas as bibliotecas para as diversas plata- <uses-permission android:name=android.permission.INTERNET />
<uses-permission android:name=android.permission.
formas. Neste exemplo, iremos precisar da pasta XML e de mais
WRITE_EXTERNAL_STORAGE />
dois arquivos que esto dentro da pasta Android, denominados <uses-permission android:name=android.permission.
phonegap-1.0.0.js e phonegap-1.0.0.jar. ACCESS_NETWORK_STATE />
...
Crie uma pasta chamada lib na raiz do projeto e coloque o arquivo
JAR dentro dela. Agora, crie outra pasta chamada www dentro Listagem 3. Activity auxiliar para no reiniciar a aplicao ao rodar a tela.
da pasta asserts, coloque o arquivo js nesta pasta e a pasta XML
...
dentro da pasta res. Em seguida, adicione o JAR do PhoneGap <category android:name=android.intent.category.LAUNCHER />
ao Build Path. </intent-filter>
Por fim, abra o arquivo HelloWorldActivity.java. Ele o arquivo </activity>

necessrio para iniciar o nosso aplicativo, e se encontra dentro <activity android:name=com.phonegap.DroidGap android:label=
da pasta src. Assim, altere o cdigo, conforme a Listagem 1, para @string/app_name android:configChanges=orientation|keyboardHidden>
<intent-filter>
que possamos utilizar os recursos do PhoneGap.
</intent-filter>
Explicando o cdigo, adicionamos o pacote com.phonegap.*, que </activity>
contm todas as classes contidas no JAR do PhoneGap. Tambm
</application>
alteramos a herana da classe HelloWorldActivity para a classe
...
DroidGap, e por fim, substitumos o mtodo setContentView()
por loadUrl(). Com esse mtodo, informamos ao nosso programa
que o PhoneGap deve carregar sua interface e executar cdigo Agora que configuramos nosso projeto, o prximo passo ser criar o
HTML. arquivo index.html na pasta /asserts/www/. Para isso, acesse a opo de
Feito isso, vamos adicionar no arquivo AndroidManifest.xml as menu File > New > File. Esse arquivo ser a primeira pgina a ser exibida
permisses que nosso programa poder acessar no smartphone, pela aplicao. Como podemos analisar na Listagem 4, um arquivo
como pode ser visto na Listagem 2. Essa etapa muito impor- no formato HTML, onde foi adicionada a tag <script type=text/ja-
tante se voc estiver pensando em distribuir o seu aplicativo no vascript charset=utf-8 src= phonegap.js></script>, responsvel
Android Market. A Tabela 1 mostra os tipos de permisses que por carregar na pgina as funes do framework.
podemos adicionar. Para verificar o resultado, execute o cdigo no emulador. Por-
Ainda no AndroidManifest.xml, necessrio adicionar uma Ac- tanto, clique com o boto direito sobre o projeto e no menu Run
tivity para que, caso o usurio mude a orientao do aparelho, a > Run As > Android Application. Dessa forma ser iniciado um

Edio 39 - WebMobile Magazine 23


Desenvolvendo aplicaes para Android com PhoneGap

emulador que ir instalar e executar a aplicao. Uma vez o emula-


dor iniciado, no preciso fech-lo para ficar testando a aplicao,
basta execut-la novamente pelo Eclipse. Como voc poder notar,
o emulador demora um bom tempo para iniciar.
Dando continuidade ao desenvolvimento de nossa aplicao, que
servir para auxiliar os exerccios de esportistas cuja atividade
fsica o atletismo, a interface dever conter um cronmetro onde
ser informado o tempo previsto da corrida. Figura 8. Executando a aplicao no emulador
Deste modo, vamos modificar o arquivo index.html conforme a
Listagem 5. Este cdigo tem por finalidade criar uma estrutura Listagem 4. Cdigo do arquivo index.html.
HTML para implementao de um cronmetro utilizando cdigo
<!DOCTYPE HTML>
JavaScript. A tag <span id=chronotime> ser atualizada atravs <html>
da funo chrono() constantemente com a contagem do tempo. <head>
Tambm adicionaremos dois botes, Start e Reset, que chamam <title>PhoneGap</title>
<script type=text/javascript charset=utf-8 src=phonegap.js>
as funes chronoStart(), chronoContinue() e chronoReset(), </script>
que fazem referncia ao JavaScript para iniciar, parar e resetar o </head>
cronmetro, respectivamente. <body>
<h1>Hello World</h1>
Aps finalizar esta codificao, ao executar o nosso cdigo, o </body>
resultado deve ser igual ao da Figura 8. </html>

Adicionando o jQuery Mobile


Visando aprimorar a interface e a usabilidade de nosso siste- site do projeto e coloc-los dentro das pastas asserts/js e asserts/
ma, utilizaremos o framework JavaScript jQuery Mobile. Este css, respectivamente.
um framework web para desenvolvimento de aplicativos para Para utilizar este framework, no arquivo index.html, adicione na
smartphones e tablets, construdo com jQuery e jQuery UI (ler tag <header> as chamadas para os arquivos JavaScript (phonegap-
Nota DevMan 2). O jQuery Mobile tem como principal objetivo 1.0.0.js, js/jquery-1.6.4.js e js/jquery.mobile-1.0b3.min.js) e CSS (style/
fornecer ferramentas para a construo de interfaces touch. E para jquery.mobile-1.0b3.min.css), conforme a Listagem 6.
isso, o framework disponibiliza vrios recursos, tais como: listas, O jQuery Mobile disponibiliza recursos de tags HTML para
painis, eventos, drag-and-drop e uma imensa gama de controles estilizar a pgina. E para tal, ele nos sugere a estrutura bsica
de formulrios e widgets UI, o que simplifica e muito a vida do apresentada na Listagem 7.
desenvolvedor Dentro da tag <body>, a pgina identificada com um elemento
Para adicionar ao nosso projeto o framework, precisamos rea- <div> contendo o atributo data-role=page. Dentro do container
lizar o download do arquivo do jQuery Mobile e do jQuery no page, todas as tags HTML vlidas podem ser utilizadas, mas nas

Permisso Descrio
android.permission.CAMERA Permite acesso aos recursos da cmera.
android.permission.VIBRATE Permite acesso aos recursos de vibrao do aparelho.
android.permission.ACCESS_COARSE_LOCATION Permite acesso aos recursos de nveis de preciso de latitude (menos preciso).
android.permission.ACCESS_FINE_LOCATION Permite acesso aos recursos de nveis de preciso de latitude (mais preciso).
android.permission.READ_PHONE_STATE Permite acesso leitura da ligao em andamento.
android.permission.INTERNET Permite acesso internet.
android.permission.RECEIVE_SMS Permite acesso a receber SMS.
android.permission.RECORD_AUDIO Permite gravao de udio.
android.permission.MODIFY_AUDIO_SETTINGS Permite acesso configurao de udio.
android.permission.READ_CONTACTS Permite acesso aos contatos telefnicos.
android.permission.WRITE_CONTACTS Permite acesso a gravar contatos telefnicos.
android.permission.WRITE_EXTERNAL_STORAGE Permite acesso a gravar arquivos.
android.permission.ACCESS_NETWORK_STATE Permite acesso rede.
android.permission.GET_ACCOUNTS Permite acesso s contas.
Tabela 1. Permisses de acesso do aparelho para a aplicao

24 WebMobile Magazine - Edio 39


Listagem 5. Adicionando o cronmetro ao index.html.

<!DOCTYPE HTML> document.chronoForm.startstop.onclick = chronoStop


<html> document.chronoForm.reset.onclick = chronoReset
<head> start = new Date()
<title>PhoneGap</title> chrono()
<script type=text/javascript charset=utf-8 src=phonegap.js></script> }
</head> function chronoContinue(){
<script language=JavaScript> document.chronoForm.startstop.value = stop!
<!-- document.chronoForm.startstop.onclick = chronoStop
var startTime = 0 document.chronoForm.reset.onclick = chronoReset
var start = 0 start = new Date()-diff
var end = 0 start = new Date(start)
var diff = 0 chrono()
var timerID = 0 }
function chrono(){ function chronoReset(){
end = new Date() document.getElementById(chronotime).innerHTML = 0:00:00:000
diff = end - start start = new Date()
diff = new Date(diff ) }
var msec = diff.getMilliseconds() function chronoStopReset(){
var sec = diff.getSeconds() document.getElementById(chronotime).innerHTML = 0:00:00:000
var min = diff.getMinutes() document.chronoForm.startstop.onclick = chronoStart
var hr = diff.getHours() }
if (min < 10){ function chronoStop(){
min = 0 + min document.chronoForm.startstop.value = start!
} document.chronoForm.startstop.onclick = chronoContinue
if (sec < 10){ document.chronoForm.reset.onclick = chronoStopReset
sec = 0 + sec clearTimeout(timerID)
} }
if(msec < 10){ //-->
msec = 00 +msec </script>
} <body>
else if(msec < 100){ <h1>Cronometro</h1>
msec = 0 +msec <span id=chronotime>0:00:00:00</span>
} <form name=chronoForm id=chronoForm>
document.getElementById(chronotime).innerHTML = hr + : + min <input type=button name=startstop value=start! onClick=chronoStart() />
+ : + sec + : + msec <input type=button name=reset value=reset! onClick=chronoReset() />
timerID = setTimeout(chrono(), 10) </form>
} </body>
function chronoStart(){ </html>
document.chronoForm.startstop.value = stop!

Listagem 6. Chamadas a arquivos CSS e JavaScript.


Nota do DevMan 2
...
<title>PhoneGap</title>
jQuey

O jQuery uma biblioteca JavaScript capaz de adicionar interatividade e dinamismo s pginas web <link rel=stylesheet href=style/jquery.mobile-1.0b3.min.css />
sem complicar a vida do programador, ao contrrio, o objetivo proposto de acordo com o seu lema
Write less, do more (Escreva menos, faa mais). A biblioteca foi criada dentro dos Padres Web <script type=text/javascript charset=utf-8 src=phonegap-1.0.0.js>
estipulados pela W3C, por este motivo uma biblioteca Cross-Browser, ou seja, compatvel com </script>
qualquer navegador de internet.
<script src=js/jquery-1.6.4.js></script>
O grande diferencial do jQuery est no suporte total ao CSS3 que permite o uso de seletores para <script src=js/jquery.mobile-1.0b3.min.js></script>
localizar elementos de marcao no HTML da pgina, em sua arquitetura compatvel com a instalao ...
de plug-ins e extenses, na extensibilidade que permite a adio de novas funcionalidades, e na
integrao com o Ajax e linguagens server-side que permitem buscar informaes em um servidor Listagem 7. Template do jQuery Mobile.
remoto sem precisar recarregar a pgina. E por esses e outros motivos, o jQuery considerado por
muitos uma ferramenta simples e eficaz no desenvolvimento de RIAs (Rich Internet Applications). <div data-role=page>
<div data-role=header>
O diferencial do jQuery est: ...
no suporte total ao CSS3 que permite o uso de seletores para localizar elementos de marcao no </div>
HTML da pgina; <div data-role=content>
...
em sua arquitetura compatvel com a instalao de plug-ins e extenses; </div>
<div data-role=footer>
na extensibilidade que permite a adio de novas funcionalidades;
...
e na integrao com o Ajax e linguagens que permitem buscar informaes em um servidor remoto </div>
sem que seja necessrio recarregar a pgina. </div>

Edio 39 - WebMobile Magazine 25


Desenvolvendo aplicaes para Android com PhoneGap

pginas que utilizarem o jQuery Mobile, o filho imediato de uma caso voc deseje alinhar os botes. Por padro, um elemento
page so divs contendo tags data-roles header, content preenche toda a tela.
e footer, sendo estas, respectivamente, cabealho, contedo e
rodap.
Para montarmos as nossas pginas, precisamos seguir essa
sequncia do template. Na tag <div> com data-role=header,
colocamos informaes referentes ao cabealho, um nome
para a aplicao ou informaes adicionais. J a tag <div data-
role=content> definir o contedo principal; no nosso caso, as
informaes do cronmetro e os botes do formulrio. Por fim, na
<div data-role=footer>, poderemos inserir os menus ou outras Figura 10. Alinhando os botes da interface.
informaes. A Listagem 8 apresenta o cdigo que emprega os
recursos do jQuery Mobile em nosso projeto. Para finalizar a interface do cronmetro vamos customizar os
seus botes. Portanto, crie um arquivo de folha de estilo (cronome-
Listagem 8. jQuery Mobile em ao.
tro.css) conforme a Listagem 10 dentro da pasta asserts/css.

<div data-role=page>
<div data-role=header> Listagem 9. Adicionando recursos do jQuery Mobile.
<h1>Cronometro</h1>
</div> <header>
<div data-role=content> ...
<span id=chronotime>0:00:00:00</span> <link rel=stylesheet href=style/cronometro.css />
<form name=chronoForm id=chronoForm> ...
<input type=button name=startstop value=start! </header>
onClick=chronoStart() />
<input type=button name=reset value=reset! ...
onClick=chronoReset() /> <form name=chronoForm id=chronoForm>
</form> <input type=button name=startstop value=start!
</div> data-inline=true data-theme=b onClick=chronoStart() />
<div data-role=footer>...</div> <input type=button name=reset value=reset! data-inline=
</div> true onClick=chronoReset() />
... </form>

Listagem 10. Cdigo do arquivo cronometro.css.

#chronotime {
Ao executarmos novamente a aplicao, teremos o resultado font-size: 90px;
apresentado na Figura 9. }

#chronoForm {
margin-left: 100px;
}

Agora, execute novamente a aplicao e veja o resultado destas


pequenas mudanas na Figura 11.

Figura 9. Aplicativo com jQuery Mobile

Agora, com pequenas modificaes, podemos usar as funcio-


nalidades do jQuery Mobile e adicionar um estilo aos botes,
deixando-os alinhados e melhorando a interface de nosso apli-
cativo, como demonstra a Figura 10. Figura 11. Cronmetro funcional
Dessa forma, adicione ao index.html o cdigo da Listagem 9. O
arquivo cronometro.css ser comentado posteriormente. A principal Concluso
modificao nesse cdigo est nas tags <input>, onde foi adicio- O desenvolvimento para dispositivos mveis continua em as-
nado o atributo data-inline =true. Ele deve ser empregado censo, sendo puxado agora principalmente pelas plataformas

26 WebMobile Magazine - Edio 39


Android e iOS. Por causa disso, a quantidade de ferramentas Pgina do projeto PhoneGap
para simplificar este trabalho tambm no para de aumentar. No http://www.phonegap.com/
entanto, algo que ainda no recebia tanta importncia comeou a
ser tratado com o devido respeito, a interface do usurio. Download PhoneGap
Neste contexto, neste artigo aprendemos a configurar o ambiente http://code.google.com/p/phonegap/downloads/list
de desenvolvimento para criar sistemas Android e a montar um W3C HTML5 Tutorial
pequeno exemplo utilizando os frameworks PhoneGap e jQuery http://www.w3.org/TR/html5/
Mobile, que alm de facilitar o desenvolvimento para varias
plataformas, possibilitam a elaborao de interfaces de boa usa-
W3C CSS3
http://www.w3schools.com/css3/default.asp
bilidade e aparncia.
jQuery Mobile
Mayron Cachina http://jquerymobile.com
mayroncachina@gmail.com
Bacharel em Sistemas de Informao, Ps graduado em Desen- Feedback
D seu feedback sobre esta edio! eu
volvimento de Sistemas Corporativos. Professor de cursos tcnicos

s
D
de programao e membro dos grupos Java-RN e PSL-RN. A Mobile Magazine tem que ser feita ao seu gosto. Para isso, precisamos

sobre e
saber o que voc, leitor, acha da revista!

s
ta
edio
D seu voto sobre este artigo, atravs do link:
www.devmedia.com.br/webmobile/feedback
Utilizando sons e imagen

O Resumo DevMan
uso de mdias nos aplicativos extremamente comum,
desde sinais de alertas em aplicativos convencionais at
sua vital importncia em jogos. Podemos encontrar desde De que se trata o artigo:
simples toques polifnicos at mesmo sons em trs dimenses, O artigo mostra uma parcela pequena da API de mdia do Android utilizando
com diversos efeitos sonoros, mudando consideravelmente a per- dois exemplos. O primeiro um aplicativo de streaming de mdia, que pode
cepo do usurio em relao ao aplicativo que ele est usando. ser facilmente transformado em uma aplicao completa para rdios. O
O uso da mdia tambm est sendo utilizado na entrada de segundo exemplo mostra um lbum de fotos capturadas e persistidas pela
dados. Alm dos teclados convencionais, as telas touchscreen, j prpria aplicao. Este artigo pode ser utilizado por programadores iniciantes
encontramos sites e aplicativos que requisitam que o usurio fale na tecnologia Android, que visam tornar mais atrativo suas aplicaes a partir
a informao que deseja inserir no software. de recursos multimdias.
Para telefones celulares e smartphones a importncia das
mdias se torna ainda maior devido ateno que o usurio Em que situao o tema til::
pode dar ao aparelho. Por exemplo: o motorista est dirigindo A grande maioria dos aplicativos, sejam eles Android ou outra plataforma,
pela auto-estrada quando recebe uma mensagem de SMS. Caso ter em algum ponto uma interao com o usurio atravs de mdias, sejam
ele precise olhar para o visor do aparelho, estar deixando de elas udio, vdeo ou apenas imagens. Sendo assim, o conhecimento aqui
prestar ateno onde mais importa, na estrada. Se a mensagem reproduzido pode ser produzido em um nmero muito grande de casos.
fosse lida de forma automtica e reproduzida no sistema de
som do prprio automvel, o risco de um acidente diminuiria Utilizando sons e imagens em aplicaes Android:
consideravelmente. Este artigo cria dois aplicativos, um para acessar o streaming de udio de
Outro ponto muito importante na ajuda a deficientes visuais. uma rdio e, o segundo, para capturar e armazenar um conjunto de fotos.
Apesar da conscincia em relao usabilidade e acessibilidade Iremos trabalhar principalmente com a classe MediaPlayer, que permite tocar
ter aumentado nos ltimos anos, ainda pouco provvel encon- arquivos de mdias internos e externos e, criar um player de streaming de
trarmos um aplicativo para celular ou smartphone que mostre msica. Alm disso, tambm veremos como trabalhar com um importante
duas informaes na forma textual e oral. conceito do Android, um Service.
Temos alguns poucos exemplos que podem ser citados aqui.
LookTel: assistncia a cegos e deficientes visuais. Aparelhos
celulares so usados para reconhecer e identificar de maneira Conhecendo o Android
audvel objetos e locais, de forma quase instantnea; A plataforma Android, criada por um consrcio de empresas
SeeScan: possui o mesmo objetivo do anterior. lideradas pelo Google, fornece um sistema operacional, um am-
biente de desenvolvimento completo para programadores e uma
Mas, felizmente para ns programadores, todas as plataformas loja virtual com milhares de opes. Seu ncleo baseado em
mobile de hoje apresentam APIs que nos permitem inserir e cap- Linux e a grande maioria das bibliotecas que compe o Android
turar udio e vdeo em nossos aplicativos. At mesmo algumas de cdigo aberto.
tecnologias um pouco mais antigas j permitiam isso, como o O Android pode ser dividido em partes, como mostrado na Figura 1.
caso do Java ME. Algumas delas mais atuais fornecem suporte No seu ncleo mais bsico temos o kernel Linux. Alm disso, os
inclusive a Text to Speech e Speech to Text. O Android no foge drivers que gerenciam todos os processos e fazem a ligao da
a regra. parte de software com as partes de hardware que compe o device.
A plataforma do Google fornece um conjunto de classes e m- Logo acima teremos as bibliotecas (libraries), que permitem aos
todos completos para trabalho com mdia. desenvolvedores acessarem um banco de dados relacional SQLIte,
Neste artigo vamos falar do suporte a udio e vdeo dentro da por exemplo. Ou ainda, criar interfaces grficas complexas com
plataforma do Google, alm disso, tambm discutiremos como OpenGL e SurfaceManager. O Android Runtime contm a mquina
trabalhar com Text to Speech. Para facilitar o aprendizado, o texto virtual Java, chamada no ambiente criado pelo Google de Dalvik.
acompanhar o desenvolvimento de dois aplicativos como provas A camada de Application Framework utilizada pelos aplicativos
de conceito. nativos do aparelho, como por terceiros que desejem criar software

28 WebMobile Magazine - Edio 39


s em aplicaes Android
Ricardo Ogliari e Robison Cris Brito

para a plataforma. Um ponto interessante do Android est no fato ento, inicio uma aplicao que verifica o nmero de discagem e
das aplicaes terem o mesmo poder, a mesma importncia dentro mostra um som caso o nmero seja igual a determinado nmero.
da arquitetura. Isso difere bastante do Java ME, onde, os nossos Service: Definio de um servio que rodar em background.
aplicativos eram tratados quase que como vrus pelo Symbian. Alm disso, o mesmo s ser descartado pelo sistema operacional
e seu gerenciamento de memria em caso extremamente crtico.
Content Resolver: Permite que dados de uma aplicao se tor-
nem visveis a outros aplicativos, sejam eles de terceiros ou no.

Platform Version API Level VERSION_CODE Notes


Android 4.0 14 ICE_CREAM_SANDWICH Platform Highlights
Android 3.2 13 HONEYCOMB_MR2
Android 3.1.x 12 HONEYCOMB_MR1 Platform Highlights
Android 3.0.x 11 HONEYCOMB Platform Highlights
Android 2.3.4
10 GINGERBREAD_MR1
Android 2.3.3
Android 2.3.2 Platform Highlights
Android 2.3.1 9 GINGERBREAD
Android 2.3
Android 2.2.x 8 FROYO Platform Highlights
Android 2.1.x 7 ECLAIR_MR1
Android 2.0.1 6 ECLAIR_0_1 Platform Highlights
Figura 1. Arquitetura Android Android 2.0 5 ECLAIR
Android 1.6 4 DONUT Platform Highlights
No final de 2008, o primeiro smartphone com Android foi lan- Android 1.5 3 CUPCAKE Platform Highlights
ado no mercado. O t-Mobile G1 chegou com a verso 16 (Donut) Android 1.1 2 BASE_1_1
do sistema operacional. De l para c, no s o hardware dos Android 1.0 1 BASE
aparelhos mudou significativamente, mas tambm as verses Tabela 1. Plataformas disponveis
do Android. Veja na Tabela 1 as plataformas disponveis at o
momento da escrita deste artigo. Alm disso, os nmeros nos mostram que no mercado atual, duas
Falando mais em relao a software e as APIs disponveis aos plataformas dominam solidamente: iOS e Android. A plataforma
desenvolvedores, importante e vital o conhecimento de cinco do Google chegar em breve a marca de 1 milho de ativaes
conceitos: ao dia, alm disso, bateu marcas consagradas em seus prprios
Activity: A activity pode ser interpretada como uma tela dentro territrios. Um bom exemplo disso o mercado americano, for-
do aplicativo. Por exemplo, em uma aplicao com uma tela de temente dominado pela RIM durante anos e, agora, pertencente
login, uma lista de pessoa e uma tela de envio de SMS, temos trs aos domnios do Android.
activitys.
Intent: Descreve a inteno do programador em realizar Estudos de caso
algo. Esta tarefa pode ser interpretada e executada pelo sistema Dando uma rpida olhada pelas lojas virtuais de aplicativos,
operacional. Por exemplo, a inteno pode ser de abrir o browser no somente da plataforma Android, fica claro o recente interesse
mostrando o endereo http://ww.mobildadetudo.com. Ou ainda, por players de rdios. Ou ainda, por aplicaes que misturam
a inteno pode ser de transferir o usurio para uma tela (activity) um leitor de feeds de notcias com uma barra inferior, permitindo
especfica do aplicativo que o usurio escute uma rdio ou podcast enquanto l algo.
Broadcast Receiver: possvel interceptar mensagens enviadas O primeiro exemplo trata justamente disso, um aplicativo de uma
pelo sistema operacional e fazer algo com isto. Por exemplo, o An- rdio fictcia, utilizando um streaming de udio em segundo plano,
droid pode nos avisar que uma ligao acabou de ser encerrada, fazendo uso de um Service.

Edio 39 - WebMobile Magazine 29


Utilizando sons e imagens em aplicaes Android

O segundo aplicativo um repositrio de imagens que podem


ser tiradas pelo prprio aplicativo. Com isso, ser possvel ver Nota do DevMan 1
no s como trabalhar com a cmera e como invocar um servio
nativo, mas como tambm trabalhar diretamente no sistema de Eclipse e Android
arquivos do sistema operacional. Seu uso pode ser estendido O Android oferece um plugin customizado para o Eclipse, chamado ADT (Android Development
para diversos fins. Tools, Ferramenta de desenvolvimento Android), que foi desenvolvido para fornecer um ambiente
poderoso e integrado para a construo de aplicaes Android.
Primeiro Aplicativo - Rdio O ADT estende os recursos do Eclipse para permitir que voc configure rapidamente projetos
O primeiro aplicativo ser apenas um player de rdio. Teremos Android, crie uma aplicao, adicione componentes baseados na API do framework Android,
depure suas aplicaes usando as ferramentas do SDK e at exporte APK assinadas (ou no) para
interfaces grficas muito simples, apenas com um boto de play distribuir sua aplicao.
e stop. Alm disso, veremos como transformar o streaming de
Em geral, usar o Eclipse com o ADT a forma mais recomendada de desenvolver aplicaes Android
udio em um servio que roda em background permitindo ao e o jeito mais rpido de comear. Se voc usa Eclipse, o plugin ADT lhe fornecer um bom comeo
usurio trabalhar com outras tarefas. Veja a Figura 2 com a nica no desenvolvimento de aplicaes Android.
tela do aplicativo. Para instalar e atualizar o plugin ADT, voc pode tirar vantagem do recurso de atualizao
remota do Eclipse. Configurando um site de atualizao, voc pode facilmente baixar, instalar e
verificar atualizaes do ADT. Alternativamente, voc pode baixar a ltima verso do ADT para seu
computador como um arquivo local.

Listagem 1. Definio do arquivo main.xml

01: <?xml version=1.0 encoding=utf-8?>


02: <LinearLayout xmlns:android=http://schemas.android.com/apk/
res/android
03: android:orientation=vertical
04: android:layout_width=fill_parent
05: android:layout_height=fill_parent >
06: <ImageView android:layout_width=wrap_content
07: android:id=@+id/img
08: android:layout_height=wrap_content
09: android:layout_gravity=center_horizontal
10: android:layout_marginTop=15px/>
11: </LinearLayout>

Listagem 2. Definio da classe activity

01: public class Radio extends Activity{


02:
03: public void onCreate(Bundle savedInstanceState) {
04: super.onCreate(savedInstanceState);
05: setContentView(R.layout.main);
Figura 2. nica tela do aplicativo 06:
07: ImageView img = (ImageView) findViewById(R.id.img);
08: img.setImageResource(android.R.drawable.ic_media_play);
Ao criar o projeto no seu ambiente de desenvolvimento, que na 09: img.setOnClickListener(new View.OnClickListener() {
grande maioria dos casos ser a IDE Eclipse, a mesma gerar auto- 10:
11: @Override
maticamente a estrutura de pastas e arquivos (ler Nota DevMan 1). 12: public void onClick(View v) {
Dentro de res teremos nossos recursos. Mais especificamente em 13: play();
layout poderemos encontrar um arquivo main.xml. O primeiro passo 14: }
15: });
alterar este arquivo conforme o cdigo apresentado na Listagem 1. 16:
Perceba que definimos a interface grfica com um LinearLayout 17: }
18: }
(linha 2), que ocupar toda a largura (linha 4) e toda a altura
(linha 5) do display. Seu nico widget um ImageView. O mesmo
ocupar apenas o tamanho necessrio para desenhar a imagem O ciclo de vida de uma aplicao Android sempre tem seu
(linhas 6 e 8, respectivamente). Seu alinhamento ser centrali- ponto inicial no OnCreate. Sendo assim, quando este mtodo for
zado horizontalmente (linha 9). Alm disso, teremos um espao chamado, informamos que a Activity deve ter como contedo a
no topo de 15 pixeis (linha 10) e seu id (linha 7). View especificada no recurso de layout main.
Em seguida, definimos a classe Radio. A classe Radio no ter Posteriormente, recuperamos a instncia de ImageView definida
nenhum segredo inicialmente e deve ser definida conforme no xml. No mtodo setImageResource estamos indicando qual a
Listagem 2. imagem que a widget ir apresentar ao usurio. Perceba que no

30 WebMobile Magazine - Edio 39


indicamos um recurso do nosso projeto, em vez disso, usamos um
da prpria plataforma Android (linha 8). Na linha 9 definimos Nota do DevMan 2
a ao que ser tomada quando o usurio clicar neste boto. O
mtodo play ainda no foi definido. MediaPlayer
O mtodo play ser onde realmente comearemos a fazer uso Para saber mais sobre a classe MediaPlayer, visite a pgina da documentao oficial do Android:
das bibliotecas de mdias do Android. A API nos permite tocar http://developer.android.com/reference/android/media/MediaPlayer.html
uma mdia de uma das seguintes fontes:
Recursos locais;
URIs internas, geralmente utilizadas em conjunto com um A classe MediaPlayer nos traz um ciclo de vida que tambm pre-
ContentProvider. ContentProviders encapsulam dados que po- cisa ser conhecido para evitar aborrecimentos e comportamentos
dem ser compartilhados entre aplicaes. Isso serve tanto para estranhos em nosso aplicativo. Para comear a falar deste tema,
aplicaes nativas como aplicativos de terceiros. Na arquitetura observe a Figura 3.
Android, esta a nica maneira de conseguir este compartilha-
mento, visto que cada aplicao roda em um processo nico e no
existe um local comum ao sistema operacional onde dados so
armazenados e todos os pacotes Android podem acessar.
URLs externas.

Por exemplo, para tocar um arquivo de mdia local, armazenado


na pasta raw, poderamos usar as seguintes linhas de cdigo:

MediaPlayer mp = MediaPlayer.create(getApplicationContext(), R.raw.som);


mp.start();

Na primeira linha estamos criando uma instncia da classe


MediaPlayer, passando como parmetro um contexto e um iden-
tificador de recurso. Porm, no nosso caso no poderemos traba-
lhar desta forma porque estaremos buscando os bytes de udio
de um streaming externo. Logo, nosso mtodo play ter o cdigo
apresentado na Listagem 3.

Listagem 3. Cdigo do mtodo play

try {
1: String url = http://xxx.xxx.xx.xxx:50000/; // your URL here
2: MediaPlayer mp = new MediaPlayer();
3: mp.setDataSource(url);
4: mp.prepare();
5: mp.start();
} catch (IllegalArgumentException e) {
} catch (IllegalStateException e) {
} catch (IOException e) {
}
Figura 3. Ciclo de vida MediaPlayer

Na primeira linha cria-se uma instncia de String apontando Por exemplo. Ao chamar o mtodo setDataSource, o player pas-
a localizao do recurso externo. Logo em seguida feita a ini- sa para o estado Initialized. Neste momento podemos chamar o
cializao do objeto MediaPlayer, porm, chamando o construtor mtodo prepare() que far com que o estado mude para Prepared e
padro, sem argumentos. Na linha 3 utilizamos o mtodo setDa- posteriormente, ao chamar start(), o estado passa para Started.
taSource passando como parmetro a varivel url j criada. Desta Alguns pontos importantes que merecem destaque. Ao cha-
forma, o player de msica saber de onde ler a informao de mar o mtodo prepare(), como dito anteriormente, ele ir buscar
mdia. e decodificar os dados oriundos da fonte de dados informada.
O mtodo prepare da linha 4 bem sugestivo. Isso porque sua Porm, a mdia por ser muito extensa, ou ainda, a conexo com
funo preparar o incio da mdia, ou seja, ele quem busca a a internet naquele momento pode estar muito debilitada, atra-
mdia e decodifica os dados. Finalmente, depois de tudo arquite- sando o incio do player. Caso isso ocorra, nossa aplicao iria
tado e organizado pelo mtodo anterior, basta chamar o mtodo ficar travada ocasionando o erro chamado de Application Not
start (ler Nota DevMan 2). Responding (ANR).

Edio 39 - WebMobile Magazine 31


Utilizando sons e imagens em aplicaes Android

A boa notcia que a API j nos fornece um meio de fazer este


tratamento de forma adequada e com poucas linhas de cdigo. Nota do DevMan 3
Volte a analisar a Figura 3. Quando a mdia est no estado Ini-
tialized, perceba que tem dois caminhos: um com o prepare() e Uso do Implements
outro com o prepareAsync. Este ltimo j faz com que a busca e Na linguagem de programao Java, ao usar o implements com uma classe, teremos que estar de
decodificao do data source seja feita em background, no oca- acordo com seu contrato. Ou seja, a classe implementada define alguns mtodos que, de forma
obrigatria, devem ser implementados pela classe que a utilizar.
sionando o congelamento do aplicativo. Alm disso, a prpria
API nos avisa no exato momento em que o processo de prepare foi
finalizado. Ou seja, totalmente assncrono. Veja agora a Listagem
Listagem 4. Cdigo do mtodo play considerando o prepareAsync.
4 como nosso mtodo play fica considerando esta facilidade.
Perceba que os mtodos prepare e start desaparecem. No lugar try {
deles temos duas novas linhas de cdigo. Na primeira estamos String url = http://189.76.158.139:50000/; // your URL here
configurando o OnPreparedListener para a instncia de MediaPlayer. MediaPlayer mediaPlayer = new MediaPlayer();
Como parmetro est sendo usado o this, logo, a classe tambm mediaPlayer.setDataSource(url);
sofrer duas importantes mudanas: mediaPlayer.setOnPreparedListener(this);
mediaPlayer.prepareAsync();
Primeira: Adio do implements (ler Nota DevMan 3):
}
catch (IllegalArgumentException e) {}
public class Radio extends Activity implements OnPreparedListener{
catch (IllegalStateException e) {}
catch (IOException e) {}
Segunda: implementao obrigatria do mtodo onPrepare():

public void onPrepared(MediaPlayer mp) { Player de Mdia como Servio


mp.start();
Apesar de controlarmos a liberao de recursos de nosso
}
aplicativo de rdio evitando um OutOfMemory, o leitor deve ter
Voltando ao mtodo play. Depois do setOnPrepareListener, estamos percebido claramente que ainda no estamos produzindo algo
chamando o prepareAsync. Quando o processo de preparao da realmente adequado ao feeling de um Radio App. O ideal seria ter-
mdia acabar, o mtodo onPrepare ser chamado e, neste ponto, mos um servio rodando em background com um aviso na barra
utiliza-se o mtodo start(). de notificaes do smartphone. Bem, vamos fazer isso agora.
Mas ainda temos um ponto a discutir, que tambm envolve o ciclo Na arquitetura Android, um servio representado pela classe
de vida da mdia. Quando sairmos do aplicativo a mdia ir continuar Service. Quem sabe o leitor deve estar se perguntando: Eu no
tocando. Isso no est correto no atual contexto do nosso cdigo. A poderia criar apenas uma Thread e executar uma tarefa em se-
mdia s deveria continuar processando caso fosse trabalhada como gundo plano? Na verdade poderia, mas um servio quase nunca
um servio background. descartado pelo sistema operacional, somente em casos extremos
Vamos pensar no primeiro caso. A Activity sempre chama o mtodo de falta de recursos. J uma thread facilmente eliminada pelo
onStop quando vai ser descartada pelo sistema operacional. Logo, gerenciamento de memria da plataforma.
poderemos sobrescrever este mtodo e tambm liberar os recursos Assim, teremos que fazer vrias alteraes no nosso aplicativo.
alocados pelo MediaPlayer. Veja: A primeira modificar o manifesto do aplicativo:

@Override
protected void onStop() {
<service android:name=.MyService/>
mediaPlayer.release();
mediaPlayer = null;
epare que devemos declarar um servio assim como o fazemos
R
super.onStop();
} com Activitys. Logicamente, a classe MyService j deve existir no
seu classpath e deve obrigatoriamente herdar da classe Service:
Mas o que isso tem a ver com o ciclo de vida da mdia? Depen-
dendo da arquitetura da aplicao e da forma de entrada e sada public class MyService extends Service {
@Override
do mesmo, a mdia no vai liberar todos os seus recursos quando
public IBinder onBind(Intent arg0) {
a tela chamar o onStop. Ela poder simplesmente querer pausar a // TODO Auto-generated method stub
mdia e quando a Activity for recriada, reiniciar a mesma. return null;
}
Neste caso, o mtodo stop() da MediaPlayer poderia ser chamado. }
Neste ponto o ciclo de vida da mdia iria para o estado Stopped.
Para tocar a mdia novamente posteriormente, deve-se preparar a O nico mtodo de implementao obrigatrio o onBind. Este,
mdia novamente. Uma simples chamada a start() quando a mdia por sua vez, retorna uma instncia de IBinder, permitindo uma
est Stopped vai gerar uma Exception. comunicao direta entre o cliente (no caso geralmente uma

32 WebMobile Magazine - Edio 39


Activity) e o servio. Esse mtodo usado somente para imple- Veja tambm como fica o mtodo play():
mentaes de servios mais complexos. No nosso caso poder
public void play(){
retornar apenas null. Porm, somente com este cdigo nada vai intent.setAction(com.example.action.PLAY);
acontecer. O prximo passo sobrescrever o mtodo onStartCom- startService(intent);
}
mand, da classe Service. Primeiramente veja a implementao na
Listagem 5 e, depois, vamos a explicao. O mtodo play configura o action da Intent. Agora deve ter

ficado ainda mais claro o teste IF que colocamos no servio. Em
seguida, chamamos o mtodo startService e a streaming de udio
Listagem 5. Cdigo do mtodo onStartCommand.
comear a ser ouvida no aplicativo.
@Override Se o aplicativo for executado neste exato momento ele ir tocar
1: public int onStartCommand(Intent intent, int flags, int startId) { a rdio em segundo plano. Mas ainda temos alguns problemas a
2: if (intent.getAction().equals(ACTION_PLAY)) {
3: String url = http://189.76.158.139:50000/; // your URL here resolver para trabalharmos da melhor forma possvel. Primeiro,
4: mediaPlayer = new MediaPlayer(); perceba que estamos iniciando o servio, mas nenhuma indicao
5: mediaPlayer.setOnPreparedListener(this);
mostrada ao usurio. Imagino que ele gostaria de saber que seu
6:
7: try { plano de dados continua em contagem regressiva mesmo depois
8: mediaPlayer.setDataSource(url); de sair do aplicativo. Ento, para isso, vamos colocar um aviso na
9: mediaPlayer.prepareAsync();
10: } catch (IllegalArgumentException e) {}
barra de notificaes. Veja a Figura 4.
11: catch (IllegalStateException e) {}
12: catch (IOException e) {}
13: }
14: return super.onStartCommand(intent, flags, startId);
15: }

Este mtodo ser chamado sempre que um cliente iniciar o ser-


Figura 4. Aviso de streaming na barra de notificaes
vio atravs do mtodo startService(Intent intent). Ou seja, quando
este mtodo for chamado o processo em segundo plano dever
comear a rodar. Quando o usurio clicar no smbolo do play, ele entrar nas
Na segunda linha do cdigo cria-se um teste IF com uma pro- notificaes, vendo ainda mais informaes sobre nosso servio.
priedade da Intent que originou a chamada a este servio. No Veja a Figura 5.
nosso aplicativo isso no ter muito efeito porque sabemos com
certeza que somente nosso aplicativo usar o MyService. Porm,
em casos onde um mesmo servio acionado diferentes vezes e
para diversos fins, este teste deve ser efetuado.
No nos esqueamos de colocar o mtodo onPrepared e fazer com
que a classe implemente a classe OnPreparedListener:

public class Radio extends Service implements MediaPlayer.OnPreparedListener{


...
Figura 5. Notificao completa do servio em background
public void onPrepared(MediaPlayer player) {
player.start();
} Primeiramente vamos dar uma rpida olhada no cdigo que
...
tornar isto possvel, conforme Listagem 6.
cdigo dentro do IF j conhecido.
O Na primeira linha instanciamos um objeto do tipo Notification.
Agora devemos alterar tambm a classe Radio. O primeiro Esta classe serve apenas para persistir notificaes que sero mos-
passo criar uma varivel global de Intent e inicializ-la dentro tradas ao usurio usando o NotificationManager. Na linha 2 define-
do onCreate(). Isto deve ser feito para que possamos informar ao se o ticketText. Este texto ser mostrado uma nica vez quando a
sistema operacional a nossa inteno. Na instncia fica claro que notificao enviada para a barra de status. Posteriormente, na
queremos chamar o servio definido pela classe MyService. linha 3, indicamos qual ser o cone da notificao.
Na linha 5 trabalhamos com uma PendingIntent. Diferentemente
private Intent intent;
da sua co-irm Intent, esta apenas define uma inteno ao sistema
public void onCreate(Bundle savedInstanceState) { operacional, e, alm disso, define uma ao alvo para trabalhar
super.onCreate(savedInstanceState);
com ela. Os quatro parmetros do mtodo getActivity so: uma
setContentView(R.layout.main);
intent = new Intent(this, MyService.class); instncia de Context, um inteiro que define um requestCode, uma
Intent e possveis flags. No nosso exemplo estamos usando a

Edio 39 - WebMobile Magazine 33


Utilizando sons e imagens em aplicaes Android

opo FLAG_UPDATE_CURRENT. Esta flag dita que se esta A interface grfica extremamente simples. Prova disso o ar-
PendingIntent j existir, o mesmo ser mantido, porm, seus dados quivo xml que representa a tela apresentado na Listagem 7.
sero atualizados.
A linha 7 define as informaes visuais da notificao (Figura 5). Listagem 7. Arquivo de layout.
No primeiro parmetro do mtodo setLatestEventInfo passamos
uma instncia de Context. Na sequncia, o ttulo. Depois o texto 1: <?xml version=1.0 encoding=utf-8?>
2: <LinearLayout xmlns:android=http://schemas.android.com/apk/res/
que descreve a notificao. Por fim, uma instncia de PendingIntent, android
que ser utilizada quando o usurio clicar ou tocar na notificao android:orientation=vertical android:layout_width=match_parent
expandida na tela. android:layout_height=match_parent>
3: <Gallery xmlns:android=http://schemas.android.com/apk/res/android
android:id=@+id/gallery android:layout_width=fill_parent
android:layout_height=wrap_content />
Listagem 6. Cdigo para apresentar a notificao. 4: <ImageView android:id=@+id/img
android:layout_width=wrap_content android:layout_height=
1:Notification notification = new Notification(); wrap_content/>
2:notification.tickerText = Streaming udio; 5: </LinearLayout>
3:notification.icon = android.R.drawable.ic_media_play;
4:
5:PendingIntent pi = PendingIntent.getActivity(getApplicationContext(), 0,
new Intent(getApplicationContext(), WorkingWithMediaActivity.class), Na segunda linha temos um LinearLayout com orientao
PendingIntent.FLAG_UPDATE_CURRENT);
6:
vertical (android:orientation). Na linha 3 definimos uma galeria
7:notification.setLatestEventInfo(getApplicationContext(), Rdio, (Gallery). Por fim, na linha 4 definimos uma tag ImageView.
Playing: Streaming Rdio, pi); O funcionamento do aplicativo muito simples. Ao capturar
8:
9:startForeground(19, notification);
uma foto a galeria da parte superior atualizada, ao clicar em
um dos thumbs a imagem visualizada em tamanho maior no
centro da tela.
Por fim, a linha 9 chama o mtodo startForeground para fazer o Na pasta res do projeto adicione uma pasta chamada menu.
servio ser executado em primeiro plano, fornecendo uma notifi- Dentro da mesma, crie um arquivo chamado menu.xml. Popule-o
cao passada por parmetro enquanto este estado for mantido. com o seguinte cdigo:
Com isso, finalizamos nosso primeiro estudo de caso sobre uso
de mdias em Android. <?xml version=1.0 encoding=utf-8?>
<menu xmlns:android=http://schemas.android.com/apk/res/android>
<item android:id=@+id/menuCapturar
Segundo Aplicativo - lbum de Fotos android:icon=@android:drawable/ic_menu_add
android:title=Capturar />
Nosso segundo aplicativo mostrar apenas um lbum de fotos
</menu>
de imagens capturadas apenas pelo nosso cdigo. Infelizmente o
simulador tem problemas ao trabalhar com captura de imagens, O nico ponto de ateno no android:icon. No estamos usan-
porm, ele funciona perfeitamente no aparelho. A Figura 6 mostra do uma imagem que est no res/drawable do nosso projeto, mas
o aplicativo funcionando em um Samsung Galaxy S. sim, nos recursos do prprio Android. Para que a explicao
fique clara. Veja a Figura 7. Ela mostra a estrutura de um pro-
jeto Android tpico. Para acessarmos as imagens que esto no
nosso path, ou seja, nas pastas que iniciam com drawable, basta
usar a notao @drawable/nome_da_imagem. Mas o Android nos
permite ir alm, acessando as imagens que so usadas pelo
prprio sistema operacional. Para tanto, basta utilizar a notao
@android:drawable/_nome_da_imagem.
A Activity tem seu escopo bsico j conhecido pelo leitor e est
apresentada na Listagem 8. O mtodo onCreate ser chamado
no incio do ciclo de vida da activity, ento, mostraremos o seu
contedo grfico (linha 8). Estamos usando a classe R que defi-
ne os recursos. Perceba que apontamos para o caminho layout,
e, para seu arquivo main.xml. Logo que o projeto construdo
este arquivo j construdo de forma automtica pela IDE.
O primeiro passo na construo do aplicativo sobrescre-
ver os mtodos onCreateOptionsMenu e onOptionsItemSelected
conforme Listagem 9. O primeiro define os itens de menu e o
Figura 6. Aplicativo de fotos no Galaxy S segundo chamado quando o usurio seleciona o menu.

34 WebMobile Magazine - Edio 39


aplicativo que tenha acesso ao sistema de arquivos do aparelho
para ter certeza disso.

Listagem 8. Cdigo da Activity.

public class AlbumFotosActivity extends Activity {

1: private Gallery gallery;


2: private ImageView imgView;
3:
4: private Vector<Bitmap> imgs;
5:
@Override
6: public void onCreate(Bundle savedInstanceState) {
Figura 7. Estrutura do projeto Android 7: super.onCreate(savedInstanceState);
8: setContentView(R.layout.main);
Na linha 1 criamos a instncia de MenuInflater. Esta classe trans- 9: }
}
forma um arquivo XML que indica os itens de menu em objetos
Menu. Para tanto, basta chamar seu mtodo inflate, passando como Listagem 9. Sobrescrevendo os mtodos.
parmetro o id do recurso de menu.
@Override
Quando o usurio selecionar o nico item de menu da nossa public boolean onCreateOptionsMenu(Menu menu) {
aplicao, o mtodo onOptionsItemSelected ser chamado. Neste 1: MenuInflater inflater = getMenuInflater();
momento, chamamos o mtodo takePhoto. Este mtodo est apre- 2: inflater.inflate(R.menu.menu_galeria, menu);
sentado na Listagem 10. 3: return true;
}
Logo na primeira linha estamos criando uma Intent. Uma Intent
est presente em todos os lugares e representa uma mensagem @Override
da aplicao para o sistema operacional solicitando que algo seja public boolean onOptionsItemSelected(MenuItem item) {
realizado, e representa um importante papel na arquitetura do 4: takePhoto();
Android para integrar diferentes aplicaes. Cabe ao sistema 5: }
}
operacional interpretar esta mensagem e tomar as providncias
necessrias que pode ser para abrir uma simples aplicao, fazer Listagem 10. Mtodo takePhoto.
uma ligao para determinado nmero ou at abrir o browser em
private void takePhoto() {
uma determinada pgina da internet. 1: final Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Uma Intent tambm pode ser entendida como uma descrio de 2: intent.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(getTempFile(this)));
uma operao a ser realizada. Quem saber decifrar esta descrio 3: startActivity(intent);
e tornar isso real o prprio sistema operacional do Android. }
private File getTempFile(Context context) {
Depois de toda esta introduo ao Intent, ficar fcil entender a li-
1: final File path = new File(Environment.getExternalStorageDirectory(),
nha 1. Estamos solicitando ao Android que efetue a ao de capturar 2: albumfotos);
imagem. Simples assim. Na linha 2 informamos uma informao 3: if (!path.exists()) {
extra para esta inteno. Posteriormente vamos entender melhor o 4: path.mkdir();
mtodo getTempFile, mas, por hora, basta saber que estamos decla- 5: }
6: Date date = new Date();
rando o local onde a imagem capturada dever ser salva.
7: return new File(path, image + date.getTime() + .tmp);
Na linha 3 iniciamos esta atividade. Pode parecer at simples }
demais, mas o Android nos fornece uma arquitetura muito robusta
e simples, sendo possvel capturar uma imagem diretamente do
aplicativo nativo de cmera com poucas linhas de cdigo. Na linha 3 verificamos se o path indicado existe, caso a resposta
Agora vamos examinar o mtodo getTempFile. Na primeira linha for negativa, chamamos o mtodo mkdir para criar este caminho.
criamos uma instncia de File. Este construtor recebe dois par- Depois disso, criamos uma instncia de Date na linha 6 e, por
metros. O primeiro um local dentro do arquivo de diretrio do fim, na linha 7, retornamos a instncia de outro File. Desta vez
aparelho. O segundo o nome de uma pasta referenciada dentro adicionamos o nome de um arquivo ao primeiro caminho que
deste caminho. Perceba que estamos usando o Environment.getEx- criamos. Usamos a data para no criar um arquivo sempre com
ternalStorageDirectory(). Este retorna o diretrio de armazenamento o mesmo nome e acontecer a sobreposio de imagens.
externo, geralmente o SDCard. A partir deste ponto j estamos tirando fotos e guardando no
Depois de executar o aplicativo e capturar uma foto o usurio sistema de arquivos. Porm, nossa interface grfica do aplicativo
perceber que uma nova pasta foi criada. Basta acessar qualquer ainda no sofrer as alteraes. Mas vamos mudar isso nesse exato

Edio 39 - WebMobile Magazine 35


Utilizando sons e imagens em aplicaes Android

momento. No mtodo onCreate, vamos adicionar um try-catch (ler Na linha 1 definimos uma constante que aponta para o path
Nota DevMan 4): onde todas as capturas de tela esto sendo armazenadas. A linha
3, j dentro do mtodo, faz uso desta varivel para criar uma
public void onCreate(Bundle savedInstanceState) { instncia de File.
super.onCreate(savedInstanceState);
setContentView(R.layout.main); A classe File tem um mtodo muito til: listFiles. Seu retorno um
vetor de instncia da mesma classe. Mas, neste caso, teremos todos
try {
os arquivos persistidos dentro da pasta. Logo, nossas imagens.
readSDCard();
} catch (Exception e) {} O vetor criado na linha 6 ir armazenar as instncias de Bitmap. A
} linha 7 apresenta um lao for, que vai desde o ndice 0 at o nmero
de files encontrado no path especificado na constante FILE_PATH.
Na linha 8 apenas recuperamos a instncia de File do Vector.
Nota do DevMan 4 Na linha 10 estamos literalmente criando um Bitmap. A classe
Media nos oferece um mtodo getBitmap, este, por sua vez, aceita
Activity: Uma Activity tambm possui um ciclo de vida bem definido.Para entend-lo completamente dois parmetros: uma instncia de ContentResolver e, uma URI.
acesse este link: http://developer.android.com/reference/android/app/Activity.html. Este caminho foi especificado pelo mtodo fromFile da classe
Neste momento, o importante entender o papel do onCreate: o mesmo chamado quando a URI. Com isso, pegamos a representao textual do caminho
activity criada pela primeira vez, ou, quando a orientao da tela muda. E o mais importante, especificado pelo File.
quando a activity removida da visualizao do usurio e depois volta ao foreground, o onCreate
chamado novamente. Na linha 13 recuperamos o ImageView declarado no XML de
layout. Na linha seguinte definimos que a imagem que esta view
receber o primeiro elemento do vetor de Bitmaps recm criado.
O OnCreate constri a tela. Isso quer dizer que, uma vez que o Isso porque em um primeiro momento a galeria ter seu primeiro
layout definido no main.xml mostrado ao usurio, neste mo- ndice selecionado.
mento que devemos buscar no sistema de arquivos do aparelho as Na linha 16 recuperamos o Gallery declarado no main.xml. Na
fotos capturadas pelo nosso aplicativo. O mtodo readSDCard faz linha seguinte definimos seu adaptador. Este conceito est muito
exatamente isto conforme podemos observar na Listagem 11. presente no Android. Um adapter faz a ligao entre a interface
de um componente e suas informaes. Para quem programou
Listagem 11. Mtodo readSDCard. com o Java Swing, existe uma semelhana com o modelo MVC
adotado por esta (ler Nota DevMan 5).

1:public final String FILE_PATH = Environment


.getExternalStorageDirectory().toString() + /albumfotos; Nota do DevMan 5

Interfaces no Java: Quando definimos a interface grfica de uma tela da aplicao em um arquivo
2:private void readSDCard() throws FileNotFoundException, IOException { XML e queremos manipular os componentes via cdigo Java, necessrio ter uma ponte entre a
3: File f = new File(FILE_PATH); linguagem de marcao e a linguagem de programao. E esta justamente a funo do mtodo
4: File[] files = f.listFiles(); findViewById.
5:
6: imgs = new Vector();
7: for (int i = 0; i < files.length; i++) {
8: File file = files[i];
Na linha 19 criamos o listener que ouvir as aes de clique na
9:
10: imgs.add(Media.getBitmap(getContentResolver(), Uri.fromFile(file))); galeria. Quando um item for selecionado, o mtodo onItemClick
11: } da linha 20 ser acionado. Neste momento, alteramos a imagem
12: do centro da tela usando o ndice selecionado na galeria (linha
13: imgView = (ImageView) findViewById(R.id.img);
de cdigo 21).
14: imgView.setImageBitmap(imgs.elementAt(0));
15:
Mas ainda no explicamos uma coisa. Na linha 17 estamos pas-
16: gallery = (Gallery) findViewById(R.id.gallery); sando como adapter uma instncia da classe AddImgAdp. Veja na
17: gallery.setAdapter(new AddImgAdp(this)); Listagem 12 o cdigo correspondente.
18: A classe BaseAdapter uma implementao comum para a
19: gallery.setOnItemClickListener(new AdapterView.OnItemClickListener() {
funo de adaptador. A ListAdapter (utilizada em ListView) e a
20: public void onItemClick(AdapterView parent, View v,
int position, long id) { SpinnerAdapter (usada no Spinner) so subclasses desta. Ao criar
21: imgView.setImageBitmap(imgs.elementAt(position)); uma classe filha de BaseAdapter devemos implementar de forma
22: } obrigatria quatro mtodos:
23: });
getCount: retorna o nmero de itens no conjunto de dados re-
24: }
presentados pelo adaptador;

36 WebMobile Magazine - Edio 39


getItem(int position): retorna um item associado a uma posio Agora olhem mais uma vez a Figura 5. Percebam que a galeria
especificada por parmetro; apresenta um background em cada imagem de seu adaptador. Isso
getItemId(int position): retorna o id de um item associado a uma foi conseguido com o mtodo setBackgroundResource (linha 26).
posio especificada por parmetro; Estamos usando um recurso do prprio sistema operacional do
getView(int position, View convertView, ViewGroup parent): retorna Android. Com isso, finalizamos nosso segundo estudo de caso.
uma instncia de View (classe herdada por todas as classes de
componentes de UI) que mostra os dados de uma determinada Concluso
posio do data set do adaptador. A API do Android nos fornece uma quantidade muito grande
de recursos. Neste artigo tivemos a oportunidade de conhecer
apenas duas delas. Streaming de vdeo e captura e armazenamento
Listagem 12. Classe AddImgAdp.
de fotos.
1:public class AddImgAdp extends BaseAdapter { Para o programador, facilmente perceptvel a baixa curva de
2: int GalItemBg;
3: private Context cont;
aprendizado na utilizao de mdia nos aplicativos Android. E
4: isso por que no tratamos dos recursos mais simples da API,
5: public AddImgAdp(Context c) { como reproduo de tons musicais, arquivos internos de vdeo e
6: cont = c;
7: }
captura de fotos sem persistncia.
8: Logo, fica clara a possibilidade latente para os programadores
9: public int getCount() { e para as empresas que trabalham com a plataforma Android.
10: return imgs.size();
11: } Seus aplicativos podem ter um trabalho bem elaborado de mdia
12: utilizando uma API fcil e sucinta.
13: public Object getItem(int position) {
14: return position; Ricardo Ogliari
15: } rogliariping@gmail.com
16:
17: public long getItemId(int position) {
Graduado em Cincia da Computao, ps-graduando em Web
18: return position; e analista de sistemas mobile na MobMidia | Grupo Pontomobi,
19: } autor de mais de cem publicaes veiculadas em anais de eventos
20: nacionais e internacionais, sites especializados e revistas. Palestrante
21: public View getView(int position, View convertView, ViewGroup parent) {
em eventos como JustJava, Java Day, GeoLivre, ExpoGPS, FISL, FLISOL e FITE, sempre
22: ImageView imgView = new ImageView(cont);
23: imgView.setImageBitmap(imgs.elementAt(position)); abordando temas relacionados a computao mvel.
24: imgView.setScaleType(ImageView.ScaleType.FIT_XY);
25: imgView.setLayoutParams(new Gallery.LayoutParams(200, 200)); Robison Cris Brito
26: imgView.setBackgroundResource(android.R.drawable.
alert_light_frame);
robison@utfpr.edu.br
27: return imgView; Mestre em Engenharia Eltrica e Informtica Industrial pela Uni-
28: } versidade Tecnolgica Federal do Paran, onde ministra aulas sobre
29: } tecnologia Java, Computao Mvel e Sistemas Distribudos. Escreve
artigos para as revistas Java Magazine e WebMobile Magazine, onde
tambm elabora vdeo aulas semanais sobre Java ME, foi palestrante de eventos como
O ltimo destes mtodos de longe o mais importante. ele que JavaOne, M3DDLA, FISL, WebMobile Tech Week, Webdays e no JustJava. Evangelista da
define o comportamento visual que o adaptador oferece a galeria. tecnologia, procura ministrar palestras e mini cursos em universidades e eventos.
Aqui poderamos retornar at mesmo um TextView. Porm, sempre
associamos este componente a imagens. Porm, poderamos criar www.netbeans.org
inclusive um menu de opes com poucas alteraes no getView. Pgina oficial da IDE Netbeans
Mas vamos analisar o nosso cdigo. Na primeira linha criamos
um ImageView, passando por parmetro uma instncia de Contexto, www.devmedia.com.br
recebida por parmetro (linha 6). Na linha 7 definimos a imagem Tutoriais, artigos e vdeo aulas sobre Java ME
desta View. Como esta classe interna podemos acessar o vetor developer.android.com
de Bitmaps que criamos no mtodo readSDCard. Utilizamos o Portal oficial da plataforma Android, com ferramentas, dicas e tutoriais
primeiro parmetro do getView para saber qual ndice da galeria
est selecionado e qual a imagem correta deve ser mostrada. Feedback
D seu feedback sobre esta edio! eu
Na linha 24 definimos a escala do componente. A classe Image-
s
D

View.ScaleType tem constantes para diferentes tipos. O que estamos A Mobile Magazine tem que ser feita ao seu gosto. Para isso, precisamos
sobre e

saber o que voc, leitor, acha da revista!


usando faz com que a imagem tenha o tamanho da View que por
s

ta
edio
acaso especificado na linha anterior. Se a imagem for menor que D seu voto sobre este artigo, atravs do link:
200x200 ser escalada para ficar maior e, caso contrrio, escalada www.devmedia.com.br/webmobile/feedback
para ficar menor.

Edio 39 - WebMobile Magazine 37


Trabalhando com dados mul
CLDC/MIDP com Java ME

M Resumo DevMan
ultimdia um termo que se refere tecnologia digital
utilizadas para criar, manipular, armazenar e pesqui-
sar contedos que foge do tradicional contedo texto. De que se trata o artigo:
No incio, esse recurso era quase que exclusivo dos programas Este artigo apresenta a utilizao de dados multimdia em aplicaes Java
Desktop, j que a Internet na poca era muito limitada, sendo que ME. Para exemplificar estes recursos, so utilizados imagens simples e din-
a maioria das pessoas acessavam a rede utilizando modem que micas, execuo de sons nativos do aparelho celular e sons de arquivos, e por
chegavam no mximo a 56 Kpbs, inviabilizando com isso a trans- fim, reproduo de arquivos de vdeo e animao. Em alguns momentos, a
misso de vdeos, sons e muitas vezes at imagens maiores. Mobile Media API foi utilizada.
Porm, a informtica evoluiu muito daquela poca para os dias
de hoje, assim como as redes de comunicao. Hoje possvel Em que situao o tema til:
assistir vdeos online em sites de compartilhamento de contedo, Este artigo pode ser til a acadmicos e estudantes que desejam utilizar
ouvir rdios de todas as partes do mundo atravs da Internet, e dados multimdia em suas aplicaes, bem como a desenvolvedores mais
at mesmo assistir algumas emissoras de TV, isso graas evo- experientes que desejam fazer uso destes recursos.
luo da rede de comunicao, aos softwares de compactao de
vdeo, som e imagem, e principalmente aos computadores, que Trabalhando com dados multimdia em aplicaes CLDC/MIDP com Java ME:
deixaram de ser dispositivos limitados e passaram a ser fonte de Este artigo apresenta de forma simples a utilizao dos recursos bsicos
entretenimento. de multimdia em aplicaes Java ME. Dessa forma, pode ser utilizado por
Da mesma forma, a telefonia celular evoluiu muito, e contamos programadores iniciantes na tecnologia, uma vez que o exemplo apre-
hoje com aparelhos que so verdadeiros computadores, com alta sentado desenvolvido passo a passo, procurando facilitar ao mximo o
velocidade de processamento, grande capacidade de armaze- desenvolvimento do aplicativo completo. Aos usurios avanados, poss-
namento, telas grandes e de alta resoluo para visualizao de vel visualizar em poucas linhas de cdigo a apresentao e reproduo de
contedo, alto falantes polifnicos para reproduo de sons ainda recursos multimdia.
mais sofisticados, inclusive sons estreos e com efeitos 3D, sem
contar com o acesso a uma rede cada vez mais rpido, onde no Nesse novo cenrio, os aplicativos para celulares podem utilizar
necessrio conexo via cabo ou wi-fi, dessa forma, podemos ter recursos at ento presentes apenas nos computadores mais avan-
acesso a rede de dados da operadora com custo cada vez menor. ados, e com certeza o maior de todos os recursos a integrao
Na Figura 1 so apresentados alguns exemplos de telas de jogos das vrias mdias: som, vdeo e imagem, que juntas permitem o
com recursos multimdia disponveis para aparelhos celulares desenvolvimento de softwares e jogos cada vez mais atraentes.
hoje. E na grande revoluo que estamos vivendo na telefonia mvel,
uma linguagem tradicional ainda recebe destaque: a linguagem
Java ME, esta madura, estando no mercado a mais de 10 anos.
Com Java ME possvel desenvolver aplicativos para vrios
tipos de dispositivos, incluindo aparelhos celulares (dos antigos
celulares que ainda no contavam com cmera digital, bluetooth
ou recursos multimdia) at os mais modernos smartphones, que
dispem de inmeros sensores, receptores GPS, conectividade via
bluetooth, wi-fi, GPRS, infravermelho, cabo, carto de memria,
etc, etc e etc.
Alm disso, esta tecnologia permite o desenvolvimento de apli-
caes para uma grande quantidade de outros dispositivos limita-
dos, porm, nem sempre pequenos, como a TV Digital, os Smart
Cards, a utilizao em circuitos digitais com tecnologias como
TINI, at sua utilizao em brinquedos, como Lego Mindstorm
Figura 1. Exemplos de jogos com recursos multimdia utilizados em aplicaes para celular (http://mindstorms.lego.com/), este apresentado na Figura 2.

38 WebMobile Magazine - Edio 39


timdia em aplicaes

Robison Cris Brito e Ricardo Ogliari

quais possuem a opo de mostrar imagem representando cada


um dos elementos da lista), alm de poder apresentar esta imagem
diretamente em um componente Form ou Alert.
Outra forma de utilizar imagens em Java ME a partir do
Canvas, sendo este uma biblioteca para desenho de baixo nvel
(pixel a pixel) na tela do celular. Com esta biblioteca, que tem um
funcionamento muito semelhante ao Canvas de outras linguagens
de programao, possvel desenhar uma Image na tela e tambm
desenhar elementos como pontos, crculos, linhas, quadrados, po-
lgonos, alm de poder pintar e colocar efeitos de preenchimento.
Esta estratgia a favorita para os desenvolvedores de jogos.
Tambm possvel com canvas alternar as imagens apresenta-
das na tela do aparelho celular, fazendo com que alternem entre
10 e 15 vezes por segundo. Essa rpida mudana de imagens
pode causar o efeito de uma animao, ou vdeo, permitindo a
Figura 2. Configurao humanide do Lego Mindstorm
movimentao de elementos da tela e inclusive a interao desses
elementos com o usurio.
Assim, este artigo apresenta a utilizao de dados multimdia Basicamente, nas primeiras verses do Java ME, os vdeos s
em aplicaes para celular utilizando a tecnologia Java ME, apre- eram possveis em aplicaes para celular utilizando a alternn-
sentando como se pode tirar proveito de recursos como imagens, cia de imagens na tela, o que acarreta na ocupao de boa parte
vdeos e sons em aplicativos mveis. do processamento dos limitados processadores existentes nos
aparelhos celulares daquela poca.
Dados multimdia em aplicaes para dispositivos mveis Embora esse recurso ainda seja usado hoje no desenvolvimento
Dentre os dados multimdias existentes, com certeza a mais anti- de alguns jogos computacionais, o ideal que se possa executar
ga e mais fcil de utilizar so as imagens. Hoje, existe uma grande vdeos desenvolvidos a partir de ferramentas ou software de
quantidade de tipos de arquivos de imagens, destacando-se os manipulao de vdeo, ou ainda, vdeos capturados de filmadoras
formatos JPEG, BMP, GIF e PNG. Porm, o formato aconselhvel ou cmeras digitais. Infelizmente, de forma nativa, o Java ME no
para aplicaes mobile o PNG, por se tratar de um formato de dispe deste recurso (execuo de vdeos como AVI ou MPEG),
imagem multiplataforma, compatvel com a grande maioria dos isso s possvel utilizando API especficas, porm, hoje supor-
aparelhos celulares, inclusive os mais antigos, por possuir um tadas pela maioria dos celulares que executam Java. Isso acontece
algoritmo de compresso de imagem muito avanado, lembrando para manter a compatibilidade dos aplicativos at mesmo com os
que, principalmente os aparelhos mais antigos, possuem limi- aparelhos mais antigos.
tao no poder de processamento, e mesmos os aparelhos mais No que diz respeito execuo de som, como os primeiros ce-
modernos, ao trafegar dados na rede, costumam ser tarifados pela lulares possuam um auto-falante muito limitado (monofnico),
quantidade de bytes trafegados, assim, quanto menor os arquivos no era possvel a execuo de msicas ou sons polifnicos, sendo
de imagem, barato e rpido ser o aplicativo mvel. naquela poca os sons resumidos a beeps. Assim, de forma nativa,
Para apresentar um arquivo de imagem, por exemplo, com a a nica maneira de executar um som no Java ME (que na verdade
extenso PNG, pode ser utilizada a classe Image, que se encontra a execuo de um beep), a partir da classe AlertType, o qual
dentro do pacote java.io presente no Java MicroEdition. A partir d a opo de executar sons de erros, informativos, ateno, entre
da instncia desta classe, possvel passar esse objeto por par- outros.
metro aos componentes visuais que esperam imagens, como por E assim como a execuo dos vdeos, para executar um som di-
exemplo, os componentes tradicionais do pacote de componentes ferente em um aparelho celular, como uma msica MP3 ou WAV,
visuais javax.microedition.lcdui, destacando-se o componente necessrio a utilizao de APIs especficas, isso para manter a
ImageItem, List e ChoiceGroup (que so componentes de lista, os compatibilidade do aplicativo com os aparelhos mais antigos.

Edio 39 - WebMobile Magazine 39


Trabalhando com dados multimdia em aplicaes CLDC/MIDP com Java ME

Resumidamente, para trabalhar com dados multimdia em Java


ME necessrio trabalhar com os recursos nativos deste (muito Nota do DevMan 1
limitados, porm, suportados at mesmo pelos aparelhos antigos),
ou utilizar APIs de manipulao de dados multimdia, como Se voc estiver trabalhando no Windows VISTA, ser necessrio executar o Visual Web Developer
por exemplo a JSR-135, popularmente conhecida como Mobile como administrador, para que a aplicao tenha direitos suficientes para gravar no log de Eventos.
Media API. Para executar o Visual Web Developer como administrador, clique com o boto direito sobre o seu
cone no menu, e escolha a opo Executar como administrador ou Run as administrator.

Mobile Media API JSR 135


A Mobile Media API foi a primeira API a fornecer recursos
multimdia para a plataforma mvel, seu release foi entregue
a comunidade em 2002 e desde ento seu nmero de usurios
no parou de crescer. J sua evoluo, a Advanced Multimedia
Supplements, data de 2005.
Com a Mobile Media API, tambm chamada de MMAPI,
possvel utilizar de forma avanada recursos como vdeo, som e
imagem. O mais interessante que alm do suporte a apresen-
tao dessas mdias ao usurio da aplicao mvel, ela tambm
Figura 3. Arquitetura Mobile Media API
permite a captura delas, como a gravao de fotos e vdeos usando
a cmera digital do celular.
A MMAPI foi projetada de tal forma que suporta um grande A MMAPI tambm possui um modelo de estados do objeto
nmero de protocolos de contedo de mdia, dessa forma, se Player (ver Figura 4). Inicialmente, um objeto Player est no es-
compatvel com o aparelho celular que ser executado, possvel tado UNREALIZED. Ao chamar o mtodo realize(), que possui a
executar vrios formatos de sons e vdeos. funo de obter as informaes que so exigidas para encontrar os
Outra caracterstica interessante desta API a utilizao no recursos da mdia, que podem estar em um servidor de streaming,
apenas de dados armazenados no aparelho celular, como arquivos um arquivo, etc. Com a execuo do mtodo realize(), a instncia
armazenados no carto de memria, mas tambm a manipulao de Player passa para o estado REALIZED.
em tempo real da cmera e do auto-falante do aparelho celular, Existe ainda o estado PREFETCHED, que chamado se o mtodo
alm de informaes localizadas remotamente, nos servidores da prefetch() for acionado. Programadores fazem uso deste mtodo
internet, permitindo assim a reproduo de vdeo em tempo real quando o Player, mesmo depois de realizado, ainda precisa ad-
(RTSP - Real Time Streaming Protocol). quirir recursos escassos ou exclusivos, preencher buffer dados ou
Para minimizar os problemas com a portabilidade do aplicativo, outra tarefa inicial. Finalmente, pode-se chamar o mtodo start()
a MMAPI possui tambm mtodos para identificar os recursos e transferir o objeto para o estado STARTED (lembrando que o
disponveis no aparelho, por exemplo, possvel identificar em PREFETCHED opcional), nesse momento a mdia tocada at o
tempo de execuo, atravs das propriedades do sistema, se o seu final. Depois disso, o fluxo de estados pode ir para o CLOSED,
aparelho permite a captura de imagem, ou se o aparelho possui liberando todos os recursos adquiridos. Nesse momento, o objeto
uma cmera digital, ou ainda se o mesmo suporta reproduo de Player no pode mais ser reutilizado.
vdeo. Esse recurso permite que o programador saiba o que pode A MMAPI tambm permite a criao de listeners para atua-
ser utilizado na plataforma em execuo (ler Nota DevMan 1). lizao dos estados de um Player (ler Nota DevMan 2). Dessa
A arquitetura bsica da Mobile Media API simples. A classe maneira, o aplicativo pode ser informado quando um Player entra
Manager utilizada para criar uma instncia da classe Player. em estado de execuo ou pra. Para tanto, precisa-se registrar
Esta responsvel pela reproduo de uma mdia e recebe como o listener PlayerListener a uma classe, e implementar o mtodo
parmetro uma fonte, especificada pela classe DataSource. playerUpdate. Lembre-se que a implementao no garante a
A classe Player a responsvel por efetuar as aes com os dados entrega imediata do aviso de atualizao de estado, ou seja, no
multimdia, como, por exemplo, apresentar no display do celular momento que o mtodo recebe uma notificao de estado para
a cmera do aparelho ou tocar arquivos de som. Alm disso, a API STARTED, o estado real da mdia j pode ser CLOSED.
fornece classes que so chamadas de controles (Control), como
por exemplo: FramePositionControl, GUIControl, MIDIControl, Exemplificando o uso de Multimdia em aplicaes Java ME
PitchControl, RecordControl, StopTimeControl, ToneControl, Para exemplificar o uso dos recursos multimdia em Java ME,
VideoControl e VolumeControl, dentre outros. ser desenvolvido um aplicativo didtico, este desenvolvido na
A maioria dos controles so auto-explicativos, como por exemplo, IDE de desenvolvimento Netbeans, verso Full, o qual j possui
a VolumeControl permite que o desenvolvedor aumente e abaixe integrado o kit de desenvolvimento Java ME, chamado do WTK
o volume da mdia que est sendo executada. A Figura 3 mostra (Wireless Toolkit) at a verso 6.5 do Netbeans e em todas as ver-
uma representao grfica da MMAPI para a arquitetura MIDP. ses Linux. Para as demais verses utilizado o Java ME Plataform

40 WebMobile Magazine - Edio 39


SDK 3.0, sendo este uma evoluo do Wireless Toolkit at ento
s compatvel com o sistema operacional Windows.

Nota do DevMan 2
Listener: Um listener pode ser entendido como um rob que fica esperando que alguma ao ocorra
para avisar o seu aplicativo que algo ocorreu. Falando especificamente da MMAPI, esse rob espera
por mudanas no estado de um Player, como as que ocorrem quando voc chama o mtodo start().

Figura 5. Iniciando um projeto Java ME na IDE Netbeans

Na tela seguinte, deve-se informar o nome do projeto, para o


exemplo foi utilizado UsandoMultimidia, selecionando a pasta ou
diretrio onde ser armazenado o projeto, assim como marcando
as opes para Configurar como Projeto Principal e Criar MI-
Dlet Ola, que respectivamente deixar o projeto como padro,
podendo este ser executado pelo boto Executar Main Project
da IDE, alm de criar um MIDlet automaticamente.
Aps a criao do projeto, apresentado no modo fluxo da IDE
o MIDlet criado, conforme Figura 6.

Figura 4. Modelo de estados de um Player

Para baixar a IDE Netbeans, basta acessar a pgina www.netbe-


ans.org, escolhendo para Download a verso completa (full) do
ambiente, que possui em torno de 300 MB (depende do sistema
operacional desejado). Vale lembrar que para a instalao da IDE
Netbeans necessrio que j esteja instalado em sua mquina
o JSDK (Kit de desenvolvimento Java padro), disponvel para
download em http://www.oracle.com/technetwork/java/javase/
downloads.
Basicamente, o exemplo desenvolvido apresenta a utilizao Figura 6. MIDlet principal criado automaticamente pela IDE
de multimdia de vrias formas, primeiro utilizado imagens
recuperados de um arquivo PNG para apresent-lo em um Formu- Neste momento deve-se alterar a aplicao para que a mesma
lrio, ImageItem, ChoiceGroup e Alert, sendo estes componentes utilize os recursos multimdia de vdeo, som e imagem. Inicial-
tradicionais da plataforma Java ME. Seguindo, apresentado um mente deve-se criar trs novos pacotes em Pacotes de cdigo fonte,
exemplo de desenho utilizando canvas na tela do celular. sendo os pacotes:
Referente execuo de som, apresentado o procedimento para res.audio
executar um som simples padro do aparelho celular, tanto para res.image
Erro como Ateno, e na sequncia utilizada a MMAPI para res.video
execuo de um som WAV.
J para reproduo de vdeo, utilizada uma animao simples Para criar o pacote, clica-se com o boto direito sobre Pacotes de
desenvolvida a partir de canvas, sendo finalizada a apresentao cdigo fonte, escolhendo a opo Novo Pacote Java...
com a execuo de um filme MPEG, a partir da MMAPI. Para o exemplo, foi utilizado trs imagens com a extenso PNG, um
Para iniciar um projeto novo, seleciona-se na IDE Netbeans o som com a extenso WAV e por fim um vdeo com a extenso MPEG.
menu Arquivo Novo Projeto, na tela apresenta escolhe-se Java A estrutura do projeto, aps copiar os arquivos de mdia para as
ME Aplicativo Mvel, conforme Figura 5. respectivas pastas apresentada na Figura 7 (ler Nota DevMan 3).

Edio 39 - WebMobile Magazine 41


Trabalhando com dados multimdia em aplicaes CLDC/MIDP com Java ME

O prximo passo desenvolver o fluxo componente que deve ser renomeado para da linha 06 pode gerar uma exceo, se a
da aplicao, para isso, deve-se utilizar os fmImagem receber apenas um Comando imagem est referenciada de forma errada
componentes visuais presentes na catego- Voltar, este presente na categoria Coman- (caminho errado ou diferena entre mais-
ria Exibies. O resultado do modo fluxo dos da paleta de componentes. cula e minscula no nome da imagem).
apresentado na Figura 8. Voltando ao lsPrincipal, a segunda opo A linha 06 tem a funo de criar um obje-
Como pode ser observado, aps o incio Exemplo Som, que apresentar uma lista to do tipo javax.microedition.lcdui.Image.
apresentada a tela lsPrincipal, este um chamada lsSom. Esta lista possui os Ele- Esta imagem criada a partir do caminho
componente Lista (categoria Exibies da mentos da Lista Som Erro, Som Ateno, passado por parmetro (a imagem foi co-
Paleta de Componentes). Este componente Som Wav e Voltar. piada para a pasta do projeto, dentro do
formado por 4 Elementos da Lista, pre- Por fim, a opo Exemplo Vdeo do ls- pacote res.image).
sentes na categoria Elementos da paleta de Principal apresentar uma lista chamada Na linha 08 esta imagem adicionada ao
componentes. So eles: Exemplo Imagem, lsVideo, contendo os Elementos da Lista formulrio fmImagem, que por sua vez
Exemplo Som, Exemplo Vdeo e Sair (ler Animao Canvas, Vdeo MPEG e Voltar exibida na linha 10. Caso ocorra alguma
Nota DevMan 4). (ler Nota DevMan 5). exceo, o cdigo do catch executado
Ao ser selecionada a opo Exemplo Ima- Uma vez desenvolvido o fluxo, vamos (linha 13), o qual apresentar na console de
gem, uma nova lista ser apresentada, esta adicionar a lgica no clique de cada opo desenvolvimento a mensagem de erro.
chamada lsImagem, contendo os seguintes de tela existente neste aplicativo. Iniciando J o mtodo usandoImageItem() faz uso
Elementos da Lista: Usando Form, Usando pela apresentao das imagens, necess- de um componente visual de formulrio,
ImageItem, Usando ChoiceGroup, Usando rio clicar com o boto direito sobre cada este presente em javax.microedition.lcdui.
Alert, Usando Canvas e Voltar. Esta lista opo do lsImagem, selecionando Ir para
tem a opo de apresentar imagem nos o Cdigo Fonte. Cada opo executar um
componentes visuais mais utilizados da mtodo especfico, conforme apresentado
plataforma Java ME tradicional. na Listagem 1.
Nota do DevMan 3
Para apresentar os componentes visuais apresentado erro no cdigo fonte re-
Tamanho dos arquivos: Devido a uma limitao dos aparelhos
citados, necessrio adicionar ao fluxo ferente a chamada dos mtodos, isto por mais antigos, bem como do emulador, deve-se evitar arquivos
um componente Formulrio (Categoria que estes no foram codificados ainda, com tamanho grande. Procure, sempre que possvel, utilizar
Exibies da paleta de componentes). Este dessa forma, ao final do cdigo fonte, os arquivos de at 100Kb, j que os aparelhos antigos possuem um
tamanho de jar que deve ser respeitado..
mtodos devem ser codificados, conforme
Listagem 2.
Inicialmente foi codificado o mtodo
usandoForm(), o qual tem a funo de Nota do DevMan 4
criar uma imagem e coloc-la diretamente
dentro de um componente Formulrio. Programao Visual no Netbeans: Para um melhor
Assim, inicialmente na linha 03 so ex- aproveitamento deste artigo, interessante que se conhea
cludos todos os componentes visuais do a programao visual do ambiente Netbeans, sendo este
apresentado com detalhes na Revista Web Mobile nmero 6.
formulrio fmImagem. Neste, so apresentadas dicas de como renomear os componentes
Como o trabalho com arquivos pode visuais, que conseguido clicando duas vezes sobre o nome do
componente ou ainda selecionando este e clicando com o boto
gerar erro (excees), obrigatria a codifi-
direito opo Renomear. Outra dica importante realizar
cao do try-catch (linha 05), pois o cdigo chamada de novas telas no modo fluxo do aplicativo, para isso,
Figura 7. Estrutura de pasta com os arquivos de mdias
basta clicar no comando/item que gera o evento, arrastar o mouse
e soltar sobre a tela que ser apresentada.

Nota do DevMan 5
Formato dos arquivos: O exemplo do artigo utiliza os formatos
de arquivos aconselhados para aplicaes mveis, sendo eles o
formato PNG para imagens, WAV para sons e MPEG para vdeo,
sendo que a maioria dos aparelhos celulares, mesmos os mais
antigos, do suporte a estes arquivos. Porm, outros tipos de
arquivos tambm podem ser utilizados, como o formato JPEG
ou GIF para imagens, GIF animado para vdeo e MP3 para som.
Entretanto, importante verificar se o aparelho que executar sua
aplicao compatvel com estes ltimos formatos citados.
Figura 8. Visualizao do modo fluxo do aplicativo desenvolvido

42 WebMobile Magazine - Edio 39


Listagem 1. Chamada dos mtodos responsveis pela apresentao das imagens.

01. public void lsImagemAction() { 17. } else if (__selectedString.equals(Usando Alert)) {


02. // enter pre-action user code here 18. usandoAlert();
03. String __selectedString = getLsImagem(). 19.
getString(getLsImagem().getSelectedIndex()); 20. // write post-action user code here
04. if (__selectedString != null) { 21. } else if (__selectedString.equals(Usando Canvas)) {
05. if (__selectedString.equals(Usando Form)) { 22. usandoCanvas();
06. usandoForm(); 23.
07. 24. // write post-action user code here
08. // write post-action user code here 25. } else if (__selectedString.equals(Voltar)) {
09. } else if (__selectedString.equals(Usando ImageItem)) { 26. // write pre-action user code here
10. usandoImageItem(); 27. switchDisplayable(null, getLsPrincipal());
11. 28. // write post-action user code here
12. // write post-action user code here 29. }
13. } else if (__selectedString.equals(Usando ChoiceGroup)) { 30. }
14. usandoChoiceGroup(); 31. // enter post-action user code here
15. 32. }
16. // write post-action user code here

Listagem 2. Mtodos responsveis pelo uso de Imagens

01. private void usandoForm() { 51.


02. 52. cgItens.append(Primeira Opo, imagem1);
03. getFmImagem().deleteAll(); 53. cgItens.append(Segunda Opo, imagem2);
04. 54. cgItens.append(Terceira Opo, imagem3);
05. try { 55.
06. Image imagem = Image.createImage(/res/image/imagem1.png); 56. getFmImagem().append(cgItens);
07. 57.
08. getFmImagem().append(imagem); 58. getDisplay().setCurrent(fmImagem);
09. 59.
10. getDisplay().setCurrent(fmImagem); 60. } catch (IOException e) {
11. 61. e.printStackTrace();
12. } catch (IOException e) { 62. }
13. e.printStackTrace(); 63.
14. } 64. }
15. 65.
16. } 66. private void usandoAlert() {
17. 67. getFmImagem().deleteAll();
18. private void usandoImageItem() { 68.
19. 69. try {
20. getFmImagem().deleteAll(); 70. Image imagem = Image.createImage(/res/image/imagem1.png);
21. 71.
22. try { 72. Alert alImagem = new Alert(Usando Imagem);
23. Image imagem = Image.createImage(/res/image/imagem1.png); 73. alImagem.setImage(imagem);
24. 74.
25. ImageItem iiImagem = new ImageItem(Minha Imagem, 75. getDisplay().setCurrent(alImagem, lsImagem);
26. imagem, ImageItem.LAYOUT_CENTER, 76.
27. Texto Alternativo); 77. } catch (IOException e) {
28. 78. e.printStackTrace();
29. getFmImagem().append(iiImagem); 79. }
30. 80.
31. getDisplay().setCurrent(fmImagem); 81. }
32. 82.
33. } catch (IOException e) { 83. private void usandoCanvas() {
34. e.printStackTrace(); 84.
35. } 85. getDisplay().setCurrent(new Canvas() {
36. 86.
37. 87. protected void paint(Graphics g) {
38. } 88.
39. 89. g.setColor(0, 0, 0);
40. private void usandoChoiceGroup() { 90. g.fillRect(0, 0, this.getWidth(), this.getHeight());
41. 91.
42. getFmImagem().deleteAll(); 92. g.setColor(0, 0, 255);
43. 93. g.drawLine(50, 50, 300, 300);
44. try { 94.
45. Image imagem1 = Image.createImage(/res/image/imagem1.png); 95. }
46. Image imagem2 = Image.createImage(/res/image/imagem2.png); 96. });
47. Image imagem3 = Image.createImage(/res/image/imagem3.png); 97.
48. 98. }
49. ChoiceGroup cgItens = new ChoiceGroup(Opes, 99. } //fim da classe principal - MIDlet
50. ChoiceGroup.EXCLUSIVE);

Edio 39 - WebMobile Magazine 43


Trabalhando com dados multimdia em aplicaes CLDC/MIDP com Java ME

ImageItem. Para utiliz-lo necessrio ins- Seguindo, das linhas 52 a 54 so adicionados imagens disponveis na pasta do projeto.
tanciar um objeto de imagem (linha 23), as- ao ChoiceGroup suas opes, estas formadas Para o exemplo, foi utilizado PNG, mas
sim como instanciar o objeto ImagemItem por um texto e uma imagem. Finalizando o outros tipos tambm so suportados em
(linha 25). Este objeto espera por parmetro mtodo, na linha 56 adicionado ao formu- alguns aparelhos, como JPEG e GIF, sendo
em seu construtor o ttulo para a imagem, a lrio fmImagem o componente ChoiceGroup, que o procedimento para usar estes forma-
imagem instanciada na linha 23, um layout assim como o formulrio tela (linha 58). tos o mesmo que o utilizado para PNG.
(para o exemplo, a imagem foi apresentada Outro componente visual que tambm J no mtodo usandoCanvas() linha
centralizada) e um texto alternativo, caso a utiliza imagem o Alert, que utilizado 83 utilizado um recurso avanado de
imagem no consiga ser apresentada. para apresentar um texto informativo por desenho em tela, que a partir do Canvas
Em seguida, este ImageItem adicio- alguns segundos ao usurio. Assim, o mto- permite desenhar na interface do aparelho
nado ao formulrio (linha 29), sendo o do usandoAlert() exemplifica sua utilizao, utilizando recursos de baixo nvel, sendo
formulrio adicionado a tela do celular sendo criada uma imagem na linha 70 e um este o procedimento preferido para o desen-
(linha 31). componente do tipo javax.microedition. volvimento de jogos e telas que fogem dos
O terceiro mtodo faz uso de outro com- lcdui.Alert na linha 72. Este componente componentes tradicionais do Java ME.
ponente visual que permite imagens, este Alert espera em seu construtor apenas o Sendo assim, um canvas deve ser apre-
chamado ChoiceGroup, assim, para este ttulo da Janela. sentado na tela do celular, e para o exem-
exemplo, trs componentes Image foram Seguindo, na linha 73 adicionada a plo, foi utilizado um objeto annimo,
criados (linhas 45 a 47), sendo na linha 49 imagem ao componente Alert, sendo este este passado por parmetro no mtodo
instanciado um objeto javax.microedition. apresentado no display do celular pelo co- setCurrent() linha 85.
lcdui.ChoiceGroup. O construtor desta mando da linha 75. O segundo parmetro do No canvas, obrigatrio o desenvolvi-
classe espera um texto para o componente, comando informa que tela ser exibida aps mento do mtodo paint, que ser respons-
bem como um modo de funcionamento, o Alert desaparecer. vel por pintar a tela do dispositivo. Nesse
que para o exemplo foi utilizado EXCLU- Nos cdigos apresentados at o mo- contexto, a tela do dispositivo represen-
SIVE (apenas um elemento pode ser sele- mento, foram utilizados componentes da tada pelo objeto Graphics linha 85.
cionado de cada vez). plataforma Java ME para apresentao de Para se desenhar na tela, deve-se utili-
zar sempre definir a cor para desenho e
em seguida realizar a operao desejada.
Isto exemplificado neste mtodo, ini-
cialmente, na linha 89, definida a cor de
desenho para preto, sendo que o mtodo
setColor() espera os parmetros referentes
ao RGB (Red, Green e Blue, em portugus,
Vermelho, Verde e Azul). Como todos os
parmetros foram passados como 0, isso
indica a cor preta.
Seguindo, a linha 90 desenha um retn-
gulo preenchido, este iniciando na posio
0 e 0 da tela (eixo x e y), se estendendo at
a largura e altura da tela, estes recupera-
dos pelos mtodos this.getWidth() e this.
getHeight().
J as linha 92 e 93 definem a cor de dese-
nho para azul (255 o valor mximo permi-
tido para um parmetro de cor, desta forma,
a cor formada no possui informaes para
vermelho, verde e possui o valor mximo
para azul), sendo desenhada uma linha
reta, que inicia na posio 50 e 50 (x e y), se
estendendo at a posio 300 e 300 da tela.
Executando o programa, o mesmo apre-
senta as telas correspondentes aos com-
ponentes visuais e as imagens, conforme
Figura 9.
Figura 9. Exemplos de talas utilizando imagens em Java ME.

44 WebMobile Magazine - Edio 39


Para a utilizao de sons, no obrigatrio componente visual na Listagem 3. Chamada dos mtodos responsveis pela execuo do som.
tela, uma vez que o som uma mdia no visual, por este motivo,
01. public void lsSomAction() {
ao clicar nas respectivas opes da Lista lsSom, o som executado 02. // enter pre-action user code here
mas no alterada a tela. 03. String __selectedString = getLsSom().getString(getLsSom().
Para a codificao e chamada dos mtodos, deve-se clicar com getSelectedIndex());
04. if (__selectedString != null) {
o boto direito sobre as opes de som: Som Erro, Som Ateno e 05. if (__selectedString.equals(Som Erro)) {
Som Wav, escolhendo a opo Ir para o Cdigo Fonte, fazendo a 06. executarSomErro();
chamada aos respectivos mtodos, conforme Listagem 3. 07.
08. // write post-action user code here
Da mesma maneira que o tratamento das imagens, esses mto- 09. } else if (__selectedString.equals(Som Aten\u00E7\u00E3o)) {
dos apresentam erro de compilao, j que no foram codificados 00. executarSomAtencao();
ainda. Para codificar, avance at o final do cdigo fonte e insira 01.
02. // write post-action user code here
os mtodos da Listagem 4. 03. } else if (__selectedString.equals(Som Wav)) {
O mtodo executarSomErro() utiliza a classe javax.microedition. 04. executarSomWav();
05.
lcuid.AlertType, que possui algumas funcionalidade especficas,
06. // write post-action user code here
inclusive a execuo de sons. O interessante que ela executa o som 07. } else if (__selectedString.equals(Voltar)) {
padro do dispositivo dado um determinado tipo, por exemplo, o 08. // write pre-action user code here
09. switchDisplayable(null, getLsPrincipal());
som de ERROR corresponde ao som padro do dispositivo para er-
00. // write post-action user code here
ros, mesma coisa para o som de WARNING, INFO, etc. Dessa forma, 01. }
a linha 02 executa o som de erro e a linha 06 o som de Ateno. 02. }
03. // enter post-action user code here
J o cdigo do mtodo executarSomWav() faz uso de um arquivo 04. }
do tipo WAV que est na pasta do projeto, desta forma, na linha
12 realizada a leitura deste arquivo, e convertido em Stream, Listagem 4. Mtodos responsveis pela execuo do som

na sequncia utilizado recursos da MMAPI, a partir da classe 01. private void executarSomErro() {
Player. Assim, a classe Manager instancia um player passando por 02. AlertType.ERROR.playSound(getDisplay());
03. }
parmetro o Stream e o tipo do udio, no formato de MIME type.
04.
A Tabela 1 apresente os tipos de arquivos compatveis com Java 05. private void executarSomAtencao() {
ME, bem como seus MIME type. 06. AlertType.WARNING.playSound(getDisplay());
07. }
08.
MIME Type Descrio
09. private void executarSomWav() {
audio/midi Scalable Polyphony MIDI 10.
11. try {
audio/x-tone-seq MIDP 2.0 tone sequence
12. InputStream is = getClass().getResourceAsStream
audio/x-wav WAV PCM sampled audio (/res/audio/som.wav);
13.
image/gif FIG 89a (animated GIF) 14. Player tocaSom = Manager.createPlayer(is, audio/x-wav);
video/mpeg MPEG vdeo 15.
16. tocaSom.start();
video/vnd.sun.rgb565 Video capture 17.
18. } catch (IOException e) {
Tabela 1. Tipos de arquivos compatveis 19. e.printStackTrace();
20. } catch (MediaException e) {
Para finalizar, o player executado na linha 16 a partir do co- 21. e.printStackTrace();
22. }
mando start(). 23. }
Finalizando o aplicativo, vamos fazer uso de vdeo no Java ME. 24. } //fim da classe principal - MIDlet
Assim como os recursos anteriores, necessrio clicar com o
boto direito sobre as opes Animao Canvas e Vdeo MPEG,
realizando a chamada dos respectivos mtodos que so apresen- O segredo da animao est na linha 07, onde foi criada uma
tados na Listagem 5. nova Thread que ser executada em paralela ao programa. Dentro
Inicialmente ser apresentado o procedimento para criar uma desta Thread, mais especificamente no mtodo run() linha 09,
animao em Canvas, desta forma, ao longo do tempo, sero rea- executado um looping infinito (linha 11), que ir redesenhar a tela,
lizadas vrias execues dessa rotina em um segundo, alterando porm, para no ser executado muito rpido, na linha 16 acontece-
a posio de um desenho na tela do computador, o que dar a r uma pausa de 80 mili-segundos na execuo, que corresponde
impresso de um vdeo. a uma frequncia de 12 fps (frames por segundo).
Para isso, necessrio trabalhar com Canvas, sendo criada uma J a classe ExecutaAnimacaoCanvas linha 33 possui duas va-
classe chamada ExecutaAnimaoCanvas (linha 33), esta instan- riveis de classe chamadas x e y (linhas 35 e 36) que correspondem
ciada na linha 03 e apresentada na tela na linha 05. a posio onde o objeto ser desenhado. Dessa forma, no mtodo

Edio 39 - WebMobile Magazine 45


Trabalhando com dados multimdia em aplicaes CLDC/MIDP com Java ME

paint(), este chamado inmeras vezes pela linha 13 do cdigo, de- No ExecutaVideoCanvas, em seu mtodo construtor, instancia-
senha na tela um retngulo branco (linhas 40 e 41), que corresponde do um Stream com as informaes contidas no arquivo de vdeo
ao fundo da tela. Este ocupa a tela toda (canto superior esquerdo MPEG armazenada na pasta do projeto Linha 57.
corresponde a 0 e 0, canto inferior direito corresponde a largura Na linha 59 criado um objeto Player, este da MMAPI, que recebe o
e altura da tela). Seguindo, definida a cor de desenho para azul Stream correspondente ao vdeo e o tipo do arquivo. Na linha seguinte
(linha 43) e realizado o desenho de um quadro, este na posio (linha 61) preparado o vdeo para execuo, e criado um objeto de
referente s variveis x e y, com a largura/altura de 10 pixeis. VideoControl, que permite apresentar o vdeo em um Canvas.
No final do mtodo, as variveis x e y so atualizadas para na Se o VideoControl foi instanciado com sucesso linha 65, defi-
prxima interao o objeto ser desenhado em uma nova posio da nido o mesmo para o modo de vdeo direto, j que ser apresen-
tela. Dessa forma, tem-se o efeito de movimento de um quadrado tado em um Canvas, definido tambm o tamanho da rea de
azul, no sentido cima-baixo esquerda-direita que se repete at o visualizao do vdeo que ser igual ao tamanho da tela (linha
quadrado ultrapassar as fronteiras da tela. Essa tcnica costuma 67) e definida sua propriedade visible para true. Por fim, o vdeo
ser muito utilizada nos jogos. executado com o comando start() linha 71.
J o mtodo executarVideo linha 28, tambm apresenta um Caso ocorra alguma exceo, a mesma tratada das linhas 73 a 77.
objeto Canvas na tela, este objeto da classe ExecutaVideoCanvas O mtodo paint() linha 81, mesmo sem ter cdigo deve ser co-
e codificado na linha 52. dificada, pois obrigatrio em classes do tipo canvas.

Listagem 5. Mtodos responsveis pela execuo do som

01. private void executarAnimacaoCanvas() { 44. g.fillRect(x, y, 10, 10);


02. 45.
03. final ExecutaAnimacaoCanvas animacao = 46. x++;
new ExecutaAnimacaoCanvas(); 47. y++;
04. 48.
05. getDisplay().setCurrent(animacao); 49. }
06. 50. }
07. new Thread(new Runnable() { 51.
08. 52. class ExecutaVideoCanvas extends Canvas {
09. public void run() { 53.
10. 54. public ExecutaVideoCanvas() {
11. while (true) { 55.
12. 56. try {
13. animacao.repaint(); 57. InputStream is = getClass().getResourceAsStream
14. (/res/video/phantom.mpg);
15. try { 58.
16. Thread.sleep(80); 59. Player player = Manager.createPlayer(is, video/mpeg);
17. } catch (Exception e) { 60.
18. e.printStackTrace(); 61. player.realize();
19. } 62.
20. 63. VideoControl control = (VideoControl) player.
21. } getControl(VideoControl);
22. 64.
23. } 65. if (control != null) {
24. }).start(); 66. control.initDisplayMode(VideoControl.USE_DIRECT_VIDEO, this);
25. 67. control.setDisplaySize(this.getWidth(), this.getHeight());
26. } 68. control.setVisible(true);
27. 69. }
28. private void executarVideo() { 70.
29. ExecutaVideoCanvas executa = new ExecutaVideoCanvas(); 71. player.start();
30. getDisplay().setCurrent(executa); 72.
31. } 73. } catch (IOException e) {
32. 74. e.printStackTrace();
33. class ExecutaAnimacaoCanvas extends Canvas { 75. } catch( MediaException e ) {
34. 76. e.printStackTrace();
35. private int x = 0; 77. }
36. private int y = 0; 78.
37. 79. }
38. public void paint(Graphics g) { 80.
39. 81. public void paint(Graphics g) {
40. g.setColor(255, 255, 255); 82. }
41. g.fillRect(0, 0, this.getWidth(), this.getHeight()); 83. }
42. 84.
43. g.setColor(0, 0, 255);

46 WebMobile Magazine - Edio 39


xecutando o aplicativo, temos o resultado de dois vdeos, con-
E Ricardo Ogliari
forme apresentado na Figura 10. rogliariping@gmail.com
Graduado em Cincia da Computao, ps-graduando em Web
e analista de sistemas mobile na MobMidia | Grupo Pontomobi,
autor de mais de cem publicaes veiculadas em anais de eventos
nacionais e internacionais, sites especializados e revistas. Palestrante
em eventos como JustJava, Java Day, GeoLivre, ExpoGPS, FISL, FLISOL e FITE, sempre
abordando temas relacionados a computao mvel.

Robison Cris Brito


robison@utfpr.edu.br
Mestre em Engenharia Eltrica e Informtica Industrial pela Uni-
versidade Tecnolgica Federal do Paran, onde ministra aulas sobre
tecnologia Java, Computao Mvel e Sistemas Distribudos. Escreve
artigos para as revistas Java Magazine e WebMobile Magazine, onde
Figura 10. Apresentao de vdeos na tela do celular
tambm elabora vdeo aulas semanais sobre Java ME, foi palestrante de eventos como
JavaOne, M3DDLA, FISL, WebMobile Tech Week, Webdays e no JustJava. Evangelista da
Concluso tecnologia, procura ministrar palestras e mini cursos em universidades e eventos.
Como pode ser observado neste artigo, os recursos de multimdia
presentes hoje enriquecem consideralmente qualquer tipo de apli-
cativo, desde os tradicionais aplicativos Desktop at os inovadores www.netbeans.org
aplicativos para aparelhos celulares e smartphones. Pgina oficial da IDE Netbeans
Dentre estes dispositivos, ainda recebe um destaque especial www.devmedia.com.br
os aparelhos celulares, mesmo limitados, eles esto presente no Tutoriais, artigos e vdeo aulas sobre Java ME
bolso de muitas pessoas, uma vez que so aparelhos baratos e
muitas vezes so entregues de graa pela operadora. Estes apa-
Feedback
relhos conseguem executar muitos tipos de aplicaes, inclusive D seu feedback sobre esta edio! eu

s
D
aplicaes com recursos de multimidia. A Mobile Magazine tem que ser feita ao seu gosto. Para isso, precisamos

sobre e
Assim, este artigo apresentou de forma didtica a utilizao dos saber o que voc, leitor, acha da revista!

s
ta
trs recursos multimdia existentes hoje: som, vdeo e imagem. edio
D seu voto sobre este artigo, atravs do link:
Sendo utilizado desde imagens simples e estticas, como arquivos
PNG at a criao de imagens dinmicas utilizando recursos de www.devmedia.com.br/webmobile/feedback
canvas.
J referente a execuo do som, foi visto a utilizao de sons
simples, que na maioria dos celulares so monofnicos, at a
reproduo de arquivos de audio, como por exemplos sons WAV,
utilizando para isto a MMAPI.
Para finalizar, tambm utilizando a MMAPI foi apresentada
a execuo de um vdeo MPEG, assim como a criao de uma
animizao dinmica, utiliznado para isso recursos de Thread
e Canvas.

Edio 39 - WebMobile Magazine 47


MVVM no Windows
Conhea os bons princpios que podem g

O Resumo DevMan
desenvolvimento para dispositivos mveis sempre foi
considerado um desenvolvimento diferenciado, seja por
restries do hardware ou recursos disponveis da lin- De que se trata o artigo:
guagem utilizada. A plataforma .NET diminuiu essas diferenas Desenvolver sistemas mais do que criar classes a esmo, formulrios e
quando lanou na poca o .NET Compact Framework, que permi- colocar tudo ali. pensar no problema, possveis solues e unir tudo em
tia ao desenvolvedor usufruir de recursos de forma mais fcil. O algo que no cause mais problemas. Por isso existem os bons princpios para
prprio sistema operacional mvel da Microsoft sofreu mudanas desenvolvimento de softwares orientados a objetos. Neste artigo vamos
ao longo do tempo, e hoje uma nova e remodelada plataforma estudar como separar a camada de interface do restante do aplicativo.
nasce, o Windows Phone. Esta evoluo aproveita todo o conhe-
cimento em XAML do desenvolvedor, mais os recursos do .NET Em que situao o tema til:
Framework, aliados a um nico ambiente de desenvolvimento. Desenvolver um sistema flexvel bom para voc, como desenvolvedor,
o sonho de consumo de qualquer desenvolvedor, que agora pode e bom para seu cliente. Para voc bom porque levar menos tempo para
aplicar os mais diversos recursos do ambiente, incluindo o uso ajustar o sistema e o far com segurana. Para seu cliente bom porque ele
da orientao a objetos em si (ler Nota DevMan 1). ver que o sistema que ele utiliza estvel e que no vai deix-lo na mo.
Sempre se fala da orientao a objetos como se esta fosse a bala
de prata para todos os problemas, desde anlise programao. MVVM no Windows Phone:
No entanto, apesar de podermos desenvolver para o Windows Criar uma separao entre as camadas lgicas de um aplicativo muito bom,
Phone aplicando a orientao a objetos, colocar tudo em classes desde que se evite dependncia excessiva entre as classes, duplicao de
no resolve o problema, podendo at mesmo piorar a situao, cdigo e outros problemas mais. Neste artigo vamos estudar o padro MVVM
pois um software orientado a objetos mal construdo sinnimo e com um exemplo prtico ele ser aplicado para que voc leitor assimile e
de dor de cabea. possa utilizar no seu dia-a-dia.
Neste momento estamos considerando que todo leitor j sabe
o que uma classe, uma propriedade, um mtodo. J conhecem
estruturalmente a orientao a objetos, e o que falta saber como Nota do DevMan 1
modelar tudo isso de forma adequada para poder criar um sis-
tema flexvel e que responda rpido s mudanas das regras de Orientao a Objetos: A orientao a objetos surgiu com a necessidade de se criar um
negcio. paradigma de programao simples baseado na percepo humana dos objetos ao seu redor. Este
novo paradigma no apenas um modo de programar, mas uma maneira de pensar e conceber as
As regras de negcio mudam constantemente, isto fato, e faz ideias. Neste paradigma, o software composto por uma coleo de objetos que interagem entre
com que seja um desafio construir um aplicativo que responda si atravs de mensagens, simulando as aes que ocorrem no mundo real.
rpido s mudanas apresentadas. Toda essa exigncia por mu- A partir dos conceitos do paradigma orientado a objetos possvel fazer uma anlise dos requisitos
danas pode levar-nos a desenvolver algo que no tenha a quali- do sistema, investigando as entidades que o compem. O sistema pode ser quebrado em unidades
de objetos e a partir da possvel entender como eles se relacionam. Nesta etapa ser feita a
dade desejada. Os aplicativos bem desenvolvidos podem oferecer anlise de requisitos para serem construdos modelos que representem o sistema.
vantagem competitiva para seus clientes, contudo o projeto mal
O importante o que ser feito, sem se preocupar em como ser feito, desprendendo-se de
modelado pode levar a prejuzos por enrijecer processos, j que qualquer tipo de tecnologia. O sistema assim precisa ser validado e verificado, para ter certeza de
no se adapta s mudanas de forma eficiente. Neste segmento, que os requisitos atendem as necessidades do cliente.
possvel identificar quando um aplicativo bem ou mal proje- Em um processo de desenvolvimento orientado a objetos, o resultado da analise so modelos que
tado, por isso vamos analisar os elementos de um bom design e representam as estruturas das classes de objetos componentes e modelos que especifiquem as
de um no to bom. funcionalidades do sistema. A nfase est em achar e descrever objetos (ou conceitos) no domnio
do problema. Por exemplo, num sistema acadmico alguns dos conceitos poderiam ser aluno,
matricula,curso.
Modelagem boa A utilizao deste mecanismo possibilita no somente equipe de desenvolvimento o
Aplicaes bem desenhadas oferecem rotinas que so robustas, entendimento do problema. Como este paradigma aproxima o mundo real do computacional,
de fcil manuteno e reutilizveis. Elas devem estar aptas a se ele traz tambm como benefcio uma melhor interpretao do cliente quanto ao documento de
requisitos especificado.
adequar s mudanas sem afetar sua modelagem. Um exemplo
disso seria uma aplicao onde necessrio exportar um arquivo

48 WebMobile Magazine - Edio 39


Phone
arantir qualidade
Paulo Quicoli

em um determinado formato. Adicionar novos formatos ao siste- Seja S.O.L.I.D.


ma atual deve ser uma tarefa fcil. Esta sigla um acrnimo para a palavra em ingls solid,
As trs caractersticas de um bom design so: que significa slido, solidez. Cada letra representa um acrni-
M anuteno Facilidade com que um sistema pode ser alterado mo de um princpio, ou seja, temos um acrnimo de um acr-
para aplicar novas regras de negcio, mas no apenas regras, como nimo. Esse conjunto o resultado de estudos e experincias
tambm melhorar seu desempenho, corrigir falhas e outras soli- de vrios desenvolvedores, e foi primeiramente catalogado
citaes. Aplicaes que possuem um bom design exigem poucos por Robert Uncle Bob Martin (veja seo Links), em seu
recursos (tempo, esforo e at mesmo capital) para realizar sua livro Applying Principles and Patterns. Vamos tratar aqui
devida manuteno; do primeiro princpio.
Reusabilidade Em um sistema bem projetado possvel que
os seus componentes possam ser reutilizados por outros sem Single Responsability Principle (SRP)
grandes dificuldades; Este o princpio da responsabilidade nica, que recomenda
Robustez Estabilidade do sistema em situaes extremas, do que uma classe s deva ter um motivo para sofrer alguma alte-
tipo: tratamento de entradas erradas por parte de usurios e carga rao. Sendo assim, podemos resumir que uma classe qualquer
mxima de dados em determinado momento do dia. em seu sistema deva ter uma tarefa nica e especfica. Isso,
contudo, no quer dizer que se tenha apenas um nico mtodo,
Modelagem ruim mas que todos os mtodos criados trabalhem juntos em um nico
Ningum desenvolve um software com problemas de projeto por- objetivo: atender a responsabilidade da classe. Outros autores
que quer. Isso decorrncia da inexperincia ou de uma modelagem tambm chamam este princpio de coeso.
feita s pressas para atender a um tempo limite de entrega. Para entendermos seu significado vamos imaginar um ce-
Sistemas construdos dessa maneira costumam apresentar os nrio que todos conhecem. Digamos que voc desenvolveu
seguintes problemas: um sistema e nele construiu uma interface muito bonita. Nos
Rigidez Dizemos que um sistema rgido quando uma alterao eventos de clique dos botes voc acessa um banco de dados,
nele difcil. E essa alterao considerada difcil porque rotinas monta consultas SQL, executa relatrios e tudo mais. Ou seja,
internas esto, muito provavelmente, entrelaadas a um ponto onde tudo est codificado de tal forma que alm de ter que exibir
alterar qualquer coisa leva a uma cascata de alteraes. Nessas informaes, essa tela agora tambm precisa acessar banco de
situaes, quando o sistema fica grande, difcil estimar o prazo dados, executar SQL e muito mais. Se pararmos para pensar,
para uma alterao, j que todo o impacto deve ser medido antes; voc acha que responsabilidade da UI saber tudo isso? Ape-
F ragilidade Por ter rotinas muito ligadas umas s outras, a sar da forma que foi construda, temos essa classe que gerou
alterao em uma leva a problemas nas outras. Quem aqui nunca a tela lidando com mais de uma situao e responsabilidades
alterou algo em um sistema que depois causou um problema em diferentes. Se amanh a estrutura do banco de dados alterada,
uma parte que parecia no estar relacionada com a alterao feita? preciso corrigir a classe. Se tambm algo muda na regra de
Corrigir esse tipo de problema pode levar a outros, desencadean- negcio referente a um campo que deva ser exibido, essa classe
do uma leva de ajustes que custam tempo e, consequentemente, tambm precisa ser corrigida, ou seja, temos aqui mais de um
dinheiro. Um sistema nessa situao perde sua credibilidade, pois motivo para essa classe ser alterada e isso no bom. No
vive em conteno de erros, impedindo que seus desenvolvedores bom porque cada responsabilidade um arco de mudanas,
mantenham uma qualidade futura ao projeto; que muito provavelmente esto entrelaadas. Estamos falando
Reusabilidade Neste caso, a falta da mesma. Quando for pre- aqui de responsabilidade, mas o que isso para uma classe?
ciso reutilizar alguma rotina, o trabalho pode ser to difcil que No contexto deste artigo, ela representa um motivo de
menos custoso desenvolver novamente essa rotina. mudana. Nem sempre fcil identificar responsabilidades
a mais em uma classe, isso porque estamos acostumados a
Agora que vimos como se parece, do ponto de vista arquitetural, ver um sistema como um todo, no distinguindo suas ca-
um bom sistema e um ruim, vamos conhecer alguns princpios madas. Tudo isto se aplica tambm ao desenvolvimento de
que podem determinar o sucesso de um design de software. aplicativos mveis.

Edio 39 - WebMobile Magazine 49


MVVM no Windows Phone

Separando em camadas Uma coisa interessante sobre os padres que eles mostram
A Engenharia de Software sugere que uma aplicao deva ser como resolver um problema de forma conceitual. Como imple-
separada em camadas lgicas, que no tenham dependncia mentar isso responsabilidade dos desenvolvedores. Por causa
direta entre si. Isso favorece a manuteno do software, pois disso, ao longo do uso do MVVM, vrios desenvolvedores perce-
quanto menos uma parte depender de outra, menos itens sofrero beram algumas dificuldades em aplicar os conceitos deste padro
mudanas. e at mesmo formas de melhorar sua aplicao. E pensando em
Uma das camadas que precisa ser separada do restante do sof- toda a comunidade de desenvolvedores, surgiram os chamados
tware a camada de interface, ou simplesmente UI. Ela deve ser Frameworks MVVM. Eles j possuem muita coisa implementada
responsvel apenas por apresentar os dados e nada mais. Assim, e resolvida, facilitando a aplicao do padro.
ela pode ser substituda ou redesenhada sem interferir nas regras Para desenvolver o exemplo apresentado neste artigo, vamos
de negcio, que tambm estaro em uma camada separada no utilizar um framework MVVM chamado MVVM Light (veja
sistema. Mas como podemos fazer essa separao em ambientes seo Links), que possui compatibilidade para WPF, Silverlight
mveis? e Windows Phone. Se voc ainda no instalou o SDK 7.1 RC do
Windows Phone e o Silverlight for Windows Phone Toolkit, no
Model-View-ViewModel (MVVM) se esquea de instal-los (veja seo Links).
Em 2005, John Gossman, ento arquiteto do WPF na Microsoft,
publicou em seu blog o padro Model-View-ViewModel, que tem
por finalidade separar a lgica da aplicao da camada de interface Nota do DevMan 2
com o usurio utilizando os recursos do WPF. A estrutura bsica
desse padro pode ser vista na Figura 1. Padro Command: O padro Command faz parte dos padres de projeto. Seu objetivo encapsular
qualquer ao que venha a ser chamada em um momento futuro. Essa ao torna-se um objeto que
pode ser reutilizado, contendo em si a complexidade da chamada da ao original. Ao aplicar esse
padro conseguimos uma flexibilidade maior no sistema, j que para adicionar novas aes (comandos)
no h necessidade de se alterar o design do projeto, apenas novos objetos so criados e associados
interatividade do sistema. Apesar dessa vantagem, existe uma desvantagem no seu uso. Como seu uso
implica na execuo de objetos que possuem como nica finalidade a execuo de uma ao, acabaremos
por ter um cdigo que se assemelha muito ao cdigo procedural, orientado aos comandos.

Lista de tarefas
Para demonstrar os conceitos envolvidos, nada melhor do
que p-los em prtica. Para isso vamos criar um aplicativo de
demonstrao bem simples, uma lista de tarefas a realizar. O
usurio poder incluir as tarefas e ainda categoriz-las como
sendo de casa ou do trabalho. A pgina principal da aplicao
exibe por padro todas as tarefas, contudo permite que se filtre
Figura 1. Estrutura do padro MVVM pela categoria (utilizando o controle Pivot). Nessa mesma pgina
ser possvel marcar quando a tarefa foi feita, incluir uma nova
Nesta estrutura, a View representa nossas janelas, o ViewModel ou excluir alguma. Com tudo isso em mente, podemos prototipar
nada mais que uma classe que contm as aes que uma View um layout como o apresentado na Figura 2.
pode tomar, encapsulando sua lgica. Ele responsvel por prepa- Aps iniciar um novo aplicativo do tipo Windows Phone Ap-
rar o Model para ser exibido pela View. Model representa nossas plication preciso instalar o MVVM Light. Isso pode ser feito via
classes de negcio e tudo o que precisa para a apresentao e lgica NuGet, que j automatiza o processo. Uma vez instalado, criada
dos dados. A View, por sua vez, se comunica com o ViewModel no projeto uma pasta denominada ViewModel. Nela j foram in-
atravs do mecanismo de Binding e atravs de Commands dis- seridas duas classes: MainViewModel e ViewModelLocator. A
ponibilizados pela infraestrutura do WPF. Quem j ouviu sobre primeira vai encapsular a lgica da pgina principal e a segunda
Model-View-Presenter (MVP) ou Model-View-Controller (MVC) uma espcie de localizador de ViewModels, que tem a funo de
vai perceber similaridades, contudo, neste, temos o uso avanado centralizar as instncias deles e disponibiliz-las para as Views.
dos recursos do WPF, como DataBinding e Commands (veja a
Nota DevMan 2). O Model
O MVVM o padro original, destinado ao WPF e suas tec- Como temos uma regra de negcio (criar tarefas e gerenci-las),
nologias. Com o tempo surgiu o Silverlight e agora o Windows melhor represent-las em um domnio, utilizando uma classe.
Phone. Ambas as tecnologias fazem uso de XAML e possuem um Assim, foi criada uma pasta Model no projeto e nela foi inserida
subconjunto dos recursos do WPF, assim, o mesmo padro pode a classe Tarefa. Essa classe bem simples, como se pode ver na
ser aplicado para as duas plataformas. Listagem 1.

50 WebMobile Magazine - Edio 39


O nico diferencial dessa classe que ela implementa a interface
INotifyPropertyChanged. Esta uma interface do framework
que utilizada nas operaes de Data Binding. O Data Binding
(que pode ser traduzido como ligao de dados) o mecanismo
que permite ligar os dados de um objeto a controles visuais, para
que sejam exibidos ao usurio. Basicamente este recurso contm
duas partes, o Target e o Source (veja a Figura 3).

Figura 3. Estrutura do DataBinding

Se vamos ligar, por exemplo, a propriedade Nome de um objeto


Pessoa propriedade Text de um TextBox, esse objeto o Source
Figura 2. Pgina principal e pgina de novas tarefas e o TextBox o Target. Em XAML isso ficaria assim:

<TextBox Text={Binding Path=objPessoa.Nome}/>


Listagem 1. Cdigo da classe Tarefa.
Veja como simples. possvel ainda determinar o fluxo dos
public class Tarefa: INotifyPropertyChanged
{ dados, ou seja, quem atualiza o que. Por exemplo, se apenas o
public Guid IdTarefa { get; set; } source que envia dados para o target, se apenas o target envia
private string _descricao = string.Empty; ou se ambos trocam informaes. Com esse comportamento po-
public string Descricao demos determinar uma espcie de binding somente leitura, onde
{
get { return _descricao; } um TextBox apenas apresenta os dados e no envia as alteraes
set para o objeto source.
{
_descricao = value; Os fluxos possveis so:
OnPropertyChanged(new PropertyChangedEventArgs(Descricao)); OneTime: atualiza o target com o valor do source quando o
}
} binding criado;
private CategoriaTarefa _categoria = CategoriaTarefa.Casa; O neWay: atualiza o target com o valor do source quando o
public CategoriaTarefa Categoria
{ binding criado e sempre que o valor no target alterado;
get { return _categoria; } TwoWay: atualiza ambos, target e source, em qualquer alterao,
set
{ seja ela feita no target ou no source.
_categoria = value;
OnPropertyChanged(new PropertyChangedEventArgs(Categoria));
} Para que o modo TwoWay ocorra, o source precisa implementar
}
private bool _estaCompleta;
INotifyPropertyChanged, como foi feito com a classe Tarefa.
public bool EstaCompleta Deste modo, se um objeto Tarefa sofre uma alterao a partir de
{
get { return _estaCompleta; }
um cdigo interno, por exemplo, algo como:
set
{ objTarefa.Descricao = Teste;
_estaCompleta = value;
OnPropertyChanged(new PropertyChangedEventArgs(EstaCompleta));
}
} ... e no da entrada de dados (feita pelo usurio), o mecanismo
public event PropertyChangedEventHandler PropertyChanged; de Binding ser notificado e ir atualizar a entrada de dados para
public void OnPropertyChanged(PropertyChangedEventArgs e)
{ refletir o novo valor do objeto.
if (PropertyChanged != null) Continuando com os requisitos do nosso projeto de demons-
{
PropertyChanged(this, e); trao, faz parte da regra de negcio salvar as tarefas criadas
} pelo usurio. muito comum nos sistemas tradicionais utilizar
}
public Tarefa() nesses casos um banco de dados relacional para manter dados
{ de um sistema. No desenvolvimento para dispositivos mveis
IdTarefa = Guid.NewGuid();
} tambm no diferente, mas tambm temos outras opes alm
} de um SGBD.

Edio 39 - WebMobile Magazine 51


MVVM no Windows Phone

Banco de dados sua criao o nome do banco. Para a criao das tabelas, por sua
No Windows Phone Mango temos disponvel o uso do SQL vez, utilizado o mtodo CreateTable(), que requer apenas uma
Server e do LINQ to SQL para manipular dados. O uso destas classe como parmetro. A tabela a ser criada guarda informaes
opes exige algumas implementaes extras que no fazem da classe informada. Por fim, caso o banco j exista, aberto pelo
parte do escopo do artigo e que causariam uma complexidade mtodo OpenDatabase().
no desejada no momento. Como temos poucos dados a serem
salvos, vamos partir para algo simples e que funciona. Neste ViewModels
artigo vamos utilizar um projeto chamado Windows Phone 7 Ao rever a Figura 1 possvel notar que temos classes que
Database. Para isso, faa seu download e referencie sua nica so o que chamamos de ViewModel. Elas so responsveis pela
DLL no projeto. Ele implementa um banco de dados simples no adaptao dos dados para a exibio, ou seja, preparam o Model
espao IsolatedStorage do aparelho, que pode conter vrias tabelas para ser exibido na View. O primeiro ViewModel criado o Main-
com vrios campos (veja a Nota DevMan 3). Para localizao dos ViewModel. Segundo nosso prottipo, temos trs listas distintas
dados salvos, pode-se utilizar LINQ to Objects. No projeto, foi de tarefas (todas, casa e trabalho) e duas aes: criar uma nova
criada uma pasta chamada DatabaseUtils e nela foi definida uma tarefa e excluir uma tarefa. Cada lista de dados a apresentar re-
classe DbHelper, responsvel pela criao e abertura do banco presentada por propriedades especficas no ViewModel. Nele, foi
de dados, como mostra a Listagem 2. implementado um mtodo que cria as listas esperadas, conforme
apresentado na Listagem 3.

Nota do DevMan 3 Listagem 3. Cdigo do mtodo AtualizarListas().

IsolatedStorage: Nada mais do que um sistema de arquivos protegido que pode ser acessado private void AtualizarListas()
programaticamente no Windows Phone. Quando um aplicativo faz uso de IsolatedStorage, seus {
dados ficam armazenados em compartimentos nicos para a aplicao, ou seja, se uma aplicao A var queryTodas = (from tarefa in _banco.Table<Tarefa>()
salva informaes, uma outra aplicao B no consegue acessar o que foi salvo por A e vice-versa. orderby tarefa.Descricao select tarefa);
TodasTarefas = new ObservableCollection<Tarefa>(queryTodas.ToList());

var queryCasa = (from tarefa in _banco.Table<Tarefa>()


where tarefa.Categoria == CategoriaTarefa.Casa
Listagem 2. Cdigo da classe DbHelper. orderby tarefa.Descricao
select tarefa);
public class DbHelper TarefasDeCasa = new ObservableCollection<Tarefa>(queryCasa.ToList());
{ var queryTrabalho = (from tarefa in _banco.Table<Tarefa>()
private const string DatabaseName = TarefasBD; where tarefa.Categoria == CategoriaTarefa.Trabalho
private static Database _bancoDados; orderby tarefa.Descricao
select tarefa);
public static Database GetDataBase() TarefasDoTrabalho = new ObservableCollection<Tarefa>
{ (queryTrabalho.ToList());
if (_bancoDados == null) }
{
if (!Database.DoesDatabaseExists(DatabaseName))
{
Cada lista o resultado de uma consulta LINQ ao banco de dados.
_bancoDados = Database.CreateDatabase(DatabaseName);
_bancoDados.CreateTable<Tarefa>(); Essas listas so do tipo ObservableCollection, que uma lista prepa-
_bancoDados.Save(); rada para ser utilizada em operaes de Binding. Para criar as aes,
}
foi utilizado um recurso do MVVM Light chamado RelayCommand.
else
{ Este, no nada mais que uma classe que implementa ICommand. A
_bancoDados = Database.OpenDatabase(DatabaseName, implementao padro disponibilizada pelo .NET Framework repre-
string.Empty, true);
}
sentada pela classe RoutedCommand. Para executar um RoutedCom-
} mand, o gerenciador de comandos (command manager) varre toda a
return _bancoDados; rvore visual que compe a janela/pgina que disparou o comando
}
}
para identificar qual elemento deve responder ao comando.
O modo como a classe RelayCommand foi implementada evita
essa iterao sobre os elementos visuais, apontando diretamente
Seu comportamento de um Singleton. Deste modo, ao acessar para o delegate que o executa. Os comandos, por sua vez, so
o mtodo GetDataBase(), verificado se o campo privado j foi declarados como propriedades (CmdCriarTarefa e CmdExcluir-
instanciado. Se ainda no, significa que o primeiro acesso ao Tarefa) que so instanciadas no construtor. No cdigo disponvel
banco de dados. Para saber se o banco de dados j foi criado, uti- para download no site da revista possvel conferir a declarao
lizado o mtodo DoesDatabaseExists(). Se ainda no foi, o mtodo dos mesmos. Para a excluso de uma tarefa utilizado o mtodo
CreateDatabase() invocado. O nico parmetro necessrio para DoExcluirTarefa(), que pode ser verificado a seguir:

52 WebMobile Magazine - Edio 39


private void DoExcluirTarefa(Tarefa tarefa) fas so exibidas esto definidas em um DataTemplate chamado
{
if (tarefa!=null) ToDoListBoxItemTemplate. Ele segue a prototipao sugerida an-
{ teriormente. Um trecho que merece ateno nesse DataTemplate
_banco.Table<Tarefa>().Remove(tarefa); o mostrado na Listagem 5. Isto porque ele mostra como utilizar
AtualizarListas();
} Commands em um DataTemplate (veja a Nota DevMan 4).
}

Este mtodo recebe a tarefa que ser excluda, e uma vez feita a Nota do DevMan 4
excluso, as listas so atualizadas. Mas como que tudo isso fica
ligado na View? Atravs de Binding. Data Template: Um DataTemplate especifica em XAML como determinado tipo de dado deve ser
apresentado. Controles visuais que possuem a finalidade de exibir colees de objetos necessitam de
Views um DataTemplate para saber como exibir os dados que contm.

As Views so responsveis pela exibio dos dados e nada mais. No cdigo a seguir temos a definio de um DataTemplate:
Essa a parte que o usurio final v de seu projeto, assim, uma <ListView ItemsSource={Binding ListaObjetos, Mode=TwoWay}
View deve cuidar da melhor forma de apresentar informaes. SelectedItem={Binding ObjetoSelecionado}>
Para isso, geralmente faz-se uso at mesmo de efeitos visuais,
<ListView.ItemTemplate>
grficos e infogrficos.
<DataTemplate>
Admite-se que o cdigo de uma View tenha lgica desde que
essa seja apenas relativa exibio de dados. Deste modo, toda a <StackPanel>
lgica de negcio fica centralizada nos ViewModels, pelos coman- <Label Content={Binding Codigo}/>
dos e suas propriedades. Uma View pode ser uma janela ou at <Label Content={Binding Descricao}/>
mesmo um UserControl. No projeto de exemplo ela a MainPage
</StackPanel>
do projeto, que realiza um Binding nas colees expostas pelo
ViewModel, como mostra a Listagem 4. </DataTemplate>
</ListView.ItemTemplate>

Listagem 4. Cdigo de MainPage. </ListView>


Qualquer elemento Visual pode ser utilizado para construir um DataTemplate, que definir a forma
<Grid x:Name=ContentPanel Grid.Row=1 Margin=12,0,12,0> de visualizao dos dados. No caso, o ListView exibe uma coleo chamada ListaObjetos, que contm
<controls:Pivot Margin=0, -36, 0, 0> vrios elementos do tipo Objeto. O tipo Objeto, por sua vez, possui duas propriedades: Codigo e
Descricao. A forma como essas propriedades sero exibidas determinada pelo DataTemplate, que
<controls:PivotItem Header=tudo> especificou o uso de um StackPanel e Labels para a exibio das mesmas. possvel criar qualquer
<ListBox forma de exibio.
x:Name=todasTarefasListBox
ItemsSource={Binding TodasTarefas}
Margin=12, 0, 12, 0 Width=440
ItemTemplate={StaticResource ToDoListBoxItemTemplate} /> O DataContext de cada linha do ListBox um objeto Tarefa que
</controls:PivotItem>
consta no ItemsSource. Por isso que no DataTemplate possvel
<controls:PivotItem Header=casa> referenciar de forma direta as propriedades da classe Tarefa (Esta
<ListBox
Completa e Descricao). Entretanto, o boto de excluso precisa
x:Name=tarefasCasaListBox
ItemsSource={Binding TarefasDeCasa} referenciar uma ao que no foi definida na classe Tarefa, mas
Margin=12, 0, 12, 0 Width=440 sim em um ViewModel, no caso o ViewModel que est associado
ItemTemplate={StaticResource ToDoListBoxItemTemplate} />
MainPage.
</controls:PivotItem>
Para que um boto possa executar um comando, a sua classe
<controls:PivotItem Header=trabalho> Button possui a propriedade Command. Nela ento foi aponta-
<ListBox
x:Name=tarefasTrabalhoListBox
do um Path (caminho) para o comando. Em nosso exemplo, foi
ItemsSource={Binding TarefasDoTrabalho} utilizado DataContext.CmdExcluirTarefa em conjunto com a
Margin=12, 0, 12, 0 Width=440 propriedade ElementName. Isso far com que o mecanismo de
ItemTemplate={StaticResource ToDoListBoxItemTemplate} />
</controls:PivotItem>
Bind localize o Path informado no nome do elemento passado
</controls:Pivot> em ElementName. Neste exemplo, foi utilizado o nome dado
</Grid> pgina MainPage.
Se nos lembrarmos bem, o comando de excluso espera por um
Cada ListBox utilizado nesta listagem possui sua propriedade parmetro que o objeto Tarefa a ser excludo. Isso tambm
ItemsSource ligada a uma ObservableCollection de Tarefa do resolvido por Binding atravs de um parmetro chamado Com-
MainViewModel. Dessa forma o contedo da lista apresentado mandParameter, que no caso foi ligado com o DataContext do
em cada ListBox; esse o DataBinding. A forma como essas tare- boto. Esse parmetro passa para o comando o que estiver ligado

Edio 39 - WebMobile Magazine 53


MVVM no Windows Phone

a ele. Uma vez que o ViewModel foi criado e ligado sua View, Listagem 6. Cdigo da classe NovaTarefaViewModel.
j possvel ver a execuo da pgina principal. Como ainda
public class NovaTarefaViewModel: ViewModelBase
no temos uma entrada de dados funcional, no ViewModel foi {
includo um mtodo chamado GeraDadosFicticios(), que cha- private Database _db = DatabaseUtils.DbHelper.GetDataBase();
mado em seu construtor para que tenhamos alguns elementos
public RelayCommand CmdSalvar { get; set; }
j carregados. public RelayCommand CmdCancelar { get; set; }

private void DoSalvar()


Listagem 5. DataTemplate de exibio de tarefas. {
if (NovaTarefa != null)
<CheckBox {
IsChecked={Binding EstaCompleta, Mode=TwoWay} NovaTarefa.Categoria = (ETarefaCasa) ? CategoriaTarefa.Casa :
Grid.Column=0 VerticalAlignment=Top/> CategoriaTarefa.Trabalho;
_db.Table<Tarefa>().Add(NovaTarefa);
<TextBlock _db.Table<Tarefa>().Save();
Text={Binding Descricao} Messenger.Default.Send<AtualizarListasMessage>
FontSize={StaticResource PhoneFontSizeLarge} (new AtualizarListasMessage());
Grid.Column=1 Grid.ColumnSpan=2 var msg = new GoToPageMessage() { PageName = MainPage,
VerticalAlignment=Top Margin=-36, 12, 0, 0/> OriginalDataContext = this };
Messenger.Default.Send<GoToPageMessage>(msg);
<Button }
Grid.Column=3 }
x:Name=deleteTaskButton
BorderThickness=0 private void DoCancelar()
Margin=0, -18, 0, 0 {
Command={Binding Path=DataContext.CmdExcluirTarefa, var msg = new GoToPageMessage() { PageName = MainPage,
ElementName=principal} OriginalDataContext = this };
CommandParameter={Binding .} Messenger.Default.Send<GoToPageMessage>(msg);
> }

<Image private Tarefa _novaTarefa;


Source=/Imagens/appbar.delete.rest.png public Tarefa NovaTarefa
Height=75 {
Width=75/> get { return _novaTarefa; }
set
</Button> {
_novaTarefa = value;
RaisePropertyChanged(NovaTarefa);
}
Para ligar o ViewModel ao DataContext da View, foi utilizado
}
o ViewModelLocator do MVVM Light, como mostra a linha de
cdigo a seguir, na chave de abertura da declarao da pgina private bool _eTarefaCasa = true;
public bool ETarefaCasa
principal: {
get { return _eTarefaCasa; }
DataContext={Binding Main, Source={StaticResource Locator}} set
{
_eTarefaCasa = value;
Criando uma nova Tarefa RaisePropertyChanged(ETarefaCasa);
preciso desenvolver para o usurio uma nova interface, para }
}
que ele possa criar uma nova tarefa no aplicativo. Assim, uma nova
classe foi adicionada pasta ViewModel, denominada NovaTarefa- private bool _eTarefaTrabalho;
ViewModel. Nela temos uma propriedade que representa a nova public bool ETarefaTrabalho
{
tarefa que ser criada e aes que o usurio pode tomar. Essas get { return _eTarefaTrabalho; }
aes so representadas por dois comandos: um que salva a tarefa set
{
e outro que cancela a incluso. No construtor deste ViewModel os
_eTarefaTrabalho = value;
comandos e a propriedade so instanciados. A Listagem 6 mostra RaisePropertyChanged(ETarefaTrabalho);
o cdigo completo. }
}
Como possvel notar, o padro de possuir propriedades na
public NovaTarefaViewModel()
classe que representam os dados a serem trabalhados continua. {
Propriedades foram utilizadas para representar a Tarefa a ser cria- CmdSalvar = new RelayCommand(DoSalvar);
CmdCancelar = new RelayCommand(DoCancelar);
da, incluindo o tipo da mesma (se de trabalho ou de casa). O que NovaTarefa = new Tarefa();
merece ateno nesse ViewModel o uso de um recurso do MVVM }
Light que implementa o design pattern Message Mediator. Seu uso }

54 WebMobile Magazine - Edio 39


est na implementao dos mtodos DoSalvar() e DoCancelar(). diator define. As mensagens tambm so enviadas atravs desse
Vamos entender esse padro. Veja a Nota DevMan 5. gerenciador de mensagens. Isso fica mais claro ao observar o
Quando desenvolvemos um aplicativo orientado a objetos, mtodo DoCancelar(). Nele instanciamos uma classe chamada
consequncia termos vrias classes interagindo entre si. Se GoToPageMessage, que contm o nome da pgina de destino e
certos princpios no forem seguidos, acabaremos gerando um o objeto DataContext, que dispara a mensagem. Essa classe fun-
cdigo confuso, com alto acoplamento e baixa coeso, ou seja, ciona como um contrato e ento enviada a todo o sistema pelo
classes que dependem diretamente umas das outras e que fazem mtodo Messenger.Default.Sender<T>(). Quem responder essa
mais do que deveriam fazer. Um desses princpios o do baixo mensagem ser uma View, no caso a View de incluso de nova
acoplamento, isto , que classes dependam o mnimo possvel tarefa. Ela foi criada na pasta Views com o nome de NovaTarefa-
uma das outras. View. A Listagem 7 mostra suas operaes de binding.

Listagem 7. Cdigo de NovaTarefaView.


Nota do DevMan 5 <StackPanel x:Name=ContentPanel Grid.Row=1 Margin=12,0,12,0>
<TextBlock Text=Descrio/>
Padres de Projeto: A gangue dos quatro, tambm conhecida como GoF, realizou um grande <TextBox Text={Binding Path=NovaTarefa.Descricao, Mode=TwoWay}/>
trabalho de pesquisa que resultou em uma classificao dos padres em trs categorias: Criacionais, <TextBlock Text=Categoria/>
Estruturais e Comportamentais.Esses padres so solues para problemas recorrentes na modelagem
de softwares orientados a objetos. Esses problemas esto relacionados a como orquestrar a utilizao <RadioButton Content=Casa GroupName=categoria
de objetos mantendo uma alta coeso e baixo acoplamento. As solues apresentadas so como uma IsChecked={Binding ETarefaCasa, Mode=TwoWay} Margin=10,0,0,0/>
receita que j foi testada e aprovada por vrios outros desenvolvedores, por isso so chamadas de <RadioButton Content=Trabalho GroupName=categoria
padro. IsChecked={Binding ETarefaTrabalho, Mode=TwoWay}
Margin=10,0,0,0/>
Um dos objetivos da literatura tcnica sobre padres de projeto registrar o conjunto de boas prticas
</StackPanel>
em projetos orientados a objetos que deram certo atravs de padres de projeto.
A catalogao dos padres de projeto apresenta suas caractersticas (elementos) como:
nome do padro de projeto que a forma de identificao do padro; Esta View deve mostrar seu interesse em responder s mensa-
o problema a que o padro de projeto se refere e onde interessante aplic-lo, ou seja, qual melhor gens enviadas, e isso feito em seu construtor, com o cdigo:
contexto ele se encaixa no projeto;
Messenger.Default.Register<GoToPageMessage>
a soluo que uma forma de resolver um problema com a aplicao deste padro, mas no sendo (
a nica forma para resolver o problema; this,
(action) => ReceiveMessage(action)
e as conseqncias que o resultado da anlise do uso do padro em um determinado ponto, bem );
como os prs e contra da sua utilizao naquele contexto.
Um formato especfico foi criado para descrever cada padro de uma forma que se torne mais fcil Esse cdigo utiliza o framework MVVM Light, que disponibiliza
entend-lo e aplic-lo, como uma espcie de gabarito para o padro de projeto. Este gabarito meios de registrarmos uma instncia para responder a um tipo de
formado por:
mensagem especfica. A classe Messenger, que o gerenciador
Nome do padro e sua classificao; de mensagens, mantm a mediao entre as classes envolvidas
Inteno e objetivo do padro: que mostra qual a funo do padro; (a classe que dispara a mensagem e a classe que responde men-
Tambm conhecido como: que a descrio dos outros possveis nomes que o padro pode ser sagem), ou seja, quem dispara no sabe quem vai responder, e
conhecido; quem vai responder, no sabe quem disparou; esto desacopladas.
Motivao para o uso do padro: que a definio de um problema de projeto no qual o padro Junto com o registro, tambm informado um mtodo que ser
pode ser aplicado; executado quando essa mensagem for recebida. No caso, o mtodo
Estrutura do padro: que sua representao grfica atravs de diagramas; utilizado foi chamado de ReceiveMessage(), que simplesmente
Participantes: que a definio de quais objetos e classes pertencem ao projeto e a responsabilidade faz o redirecionamento das pginas utilizando a classe Naviga-
que cada um assume, entre outras caractersticas dos padres de projeto. tionService. Estamos assim separando o que relativo logica
Adquirir conhecimento sobre os padres de projeto fundamental, pois munido disso, o desenvolvedor do que relacionado apresentao.
ser capaz de identificar situaes no sistema que esteja desenvolvendo, e assim saber escolher qual No relacionamento entre View e ViewModel, o ViewModel
padro melhor se encaixa neste contexto. no precisa conhecer nada da View, por outro lado, a View pode
conhecer o ViewModel. Isso pode ser visto na implementao
do evento OnNavigatedTo da View. Sempre que a pgina Nova-
Para minimizar o acoplamento, foi desenvolvido o padro TarefaView for a pgina em apresentao, ou seja, sempre que
Message Mediator. Ele funciona da seguinte forma: classes que algum cham-la, seu DataContext ser iniciado com uma nova
representam mensagens de notificao so criadas. Depois, se instncia de seu ViewModel.
alguma outra classe existente precisar receber uma notificao A incluso de uma nova tarefa est encapsulada em comandos
quando essa mensagem for disparada, ela registra seu interesse no ViewModel. Neste caso, temos comandos para salvar e para
nisso no gerenciador de mensagens que o padro Message Me- cancelar a incluso de uma nova tarefa, como apresentado na

Edio 39 - WebMobile Magazine 55


MVVM no Windows Phone

Listagem 8. Na incluso tambm feito o uso de mensagens. Ao ela pode querer responder somente quando um determinado
repensarmos o funcionamento da aplicao, sempre que uma ViewModel for o emitente da mesma. Portanto, deve ser criada
nova tarefa for includa, deve-se voltar para a tela principal que uma forma de identificar quem o emitente de uma mensagem.
mostrar as listas j atualizadas. Sendo assim, ao salvar uma nova No exemplo, na classe GoToPageMessage que foi criada, temos
tarefa, devemos disparar uma mensagem que avisa que as listas o DataContext que disparou a mensagem. Com isso, quem vai
devem ser refeitas e ento se dispara outra mensagem que trar responder pode verificar se a mensagem vinda de quem ela
novamente a pgina principal ao foco. precisa e ento responder de acordo. Foi isso o que desenvolvemos
na Listagem 9.
Listagem 8. Incluindo uma nova tarefa. Para finalizar nosso exemplo, os botes do tipo Application-
BarIconButton, nativos do Windows Phone, no possuem uma
private void DoSalvar()
{ propriedade Command para ligarmos os comandos Salvar e
if (NovaTarefa != null) Cancelar, ento simplesmente implementamos seu evento de Click
{
chamando os respectivos comandos.
NovaTarefa.Categoria = (ETarefaCasa) ? CategoriaTarefa.
Casa : CategoriaTarefa.Trabalho;
_db.Table<Tarefa>().Add(NovaTarefa); A arquitetura final
_db.Table<Tarefa>().Save();
A Figura 4 mostra um diagrama de camadas gerado pelo Visual
Messenger.Default.Send<AtualizarListasMessage> Studio. Como se pode observar, estamos respeitando a ordem das
(new AtualizarListasMessage()); camadas. No temos, por exemplo, ViewModel algum acessando a
var msg = new GoToPageMessage() { PageName = MainPage,
OriginalDataContext = this };
camada de apresentao, o que timo. Isso representado pelas
setas de navegao que so geradas automaticamente pelo Visual
Messenger.Default.Send<GoToPageMessage>(msg); Studio na anlise das classes para definio do diagrama. Note que
}
}
no h nenhuma seta bidirecional; elas seguem de cima para baixo.
Na arquitetura de sistemas, dito que camadas inferiores no de-
vem acessar camadas superiores. No entanto, talvez voc estranhe
A mensagem de atualizao de listas respondida pelo objeto o acesso da camada de dados camada Model, que est um nvel
MainViewModel, que registrou seu interesse em seu construtor, acima. Isso acontece porque nossos dados so o modelo em si.
como visto a seguir:

Messenger.Default.Register<AtualizarListasMessage>
(
this,
(action) => ReceiveMessage(action)
);

O mtodo ReceiveMessage(), por sua vez, executa o mtodo


AtualizaListas(). Como se pode notar, na troca de mensagens
no so apenas as Views que respondem as mensagens. Qualquer
classe/instncia pode responder, dependendo de como tudo est
orquestrado na sua aplicao. A resposta de MainPage exibida
na Listagem 9.

Listagem 9. Respondendo mensagem.

private void ReceiveMessage(GoToPageMessage action)


{
if (action.OriginalDataContext == this.DataContext)
{
var sb = new StringBuilder(/Views/); Figura 4. Arquitetura final do exemplo
sb.Append(action.PageName);
sb.Append(.xaml);
NavigationService.Navigate(
Concluso
new System.Uri(sb.ToString(), Aplicar uma boa separao de camadas em um aplicativo pode
System.UriKind.Relative)); acrescentar certa complexidade, porm, a sua vantagem ser
}
}
observada, principalmente, nos momentos de manuteno, pois
teremos classes coesas e desacopladas. A separao das camadas
tambm favorece a testabilidade. Visto que temos a camada de
Durante o ciclo de vida da aplicao possvel ter mais de uma interface separada pelo MVVM, podemos testar a lgica de uma
classe interessada em responder a uma mesma mensagem, porm interface sem ter a interface em si.

56 WebMobile Magazine - Edio 39


Mesmo sendo um aplicativo pequeno, para dispositivos mveis, Windows Phone SDK 7.1
preciso assegurar um processo de qualidade aplicando testes http://create.msdn.com/en-US/news/Windows_Phone_SDK_RC
automatizados que garantam no apenas o funcionamento, mas
que tambm assegurem ao desenvolvedor a possibilidade de efe-
MVVM Light
tuar refactoring. No exemplo construdo, existe um refactoring que
http://www.galasoft.ch/mvvm/
poderia ser realizado. Se observarmos o ViewModel, veremos que Silverlight for Windows Phone Toolkit
ele mesmo responsvel por salvar, localizar e excluir um item, http://silverlight.codeplex.com/
utilizando a camada de dados para realizar tudo isso. Poderamos
Windows Phone 7 Database
extrair esses acessos em uma camada que empregasse o padro de
http://winphone7db.codeplex.com/
projeto DAO (Data Access Object) para melhorar este projeto.
Abraos e at a prxima! Isolated Storage
http://msdn.microsoft.com/en-us/library/3ak841sy.aspx
Paulo Quicoli
pauloquicoli@gmail.com D seu feedback sobre esta edio! eu
Feedback
Editor tcnico das revistas ClubeDelphi e .NET Magazine. Formado

s
D
em processamento de dados pela FATEC-TQ. Atua como analista A Mobile Magazine tem que ser feita ao seu gosto. Para isso, precisamos

sobre e
saber o que voc, leitor, acha da revista!
e desenvolvedor da Siplan Control-M (www.siplancontrolm.com.br).

s
ta
edio
Entusiasta do desenvolvimento orientado a objetos e arquitetura, tem D seu voto sobre este artigo, atravs do link:
publicado vrios artigos sobre o assunto. Blog: http://quicoli.wordpress.com
www.devmedia.com.br/webmobile/feedback

Edio 39 - WebMobile Magazine 57


MVVM no Windows Phone

You might also like