Sei sulla pagina 1di 61

por tila Camura

2a Edio
27 de outubro de 2012

ii

Sumrio
1 Preparando o Ambiente de Desenvolvimento
1.1 Introduo . . . . . . . . . . . . . . . . . . . .
1.2 Instalao . . . . . . . . . . . . . . . . . . . .
1.2.1 Java JDK 6 . . . . . . . . . . . . . . .
1.2.2 Android SDK . . . . . . . . . . . . .
1.2.3 Android 2.2 API 8 . . . . . . . . . . .
1.2.4 Android Virtual Device (AVD) . . . .
1.2.5 Eclipse Juno . . . . . . . . . . . . . .
1.2.6 Plugin ADT . . . . . . . . . . . . . . .
1.2.7 Sqlite3 . . . . . . . . . . . . . . . . . .
1.2.8 Sqliteman . . . . . . . . . . . . . . . .
1.2.9 Inkscape . . . . . . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

1
1
2
2
3
3
4
4
4
6
6
7

2 Exemplo prtico
2.1 Primeira aplicao - Contatos . . . . . . .
2.1.1 AndroidManifest.xml . . . . . . . .
2.1.2 Activity . . . . . . . . . . . . . . .
2.1.3 Formulrios . . . . . . . . . . . . .
2.1.4 Construindo o Model da aplicao
2.1.5 Mostrando os dados na View . . .
2.1.6 Editando dados existentes . . . . .

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

9
9
9
10
12
14
16
20

.
.
.
.
.
.
.
.
.
.
.
.
.
.

23
23
23
25
27
28
29
32
32
32
33
33
34
35
36

.
.
.
.
.
.
.

3 Livro de Receitas
3.1 Mostrando Dilogos . . . . . . . . . . . . .
3.1.1 Editar/Excluir ao clicar e segurar na
3.1.2 Dilogo de confirmao . . . . . . .
3.1.3 Entrada de diferentes tipos de dados
3.1.4 Validao de dados . . . . . . . . . .
3.1.5 Fazendo uma ligao . . . . . . . . .
3.1.6 Enviando e-mail . . . . . . . . . . .
3.2 Internacionalizao (i18n) . . . . . . . . . .
3.2.1 Forando regio para teste . . . . . .
3.2.2 Forando regio pelo emulador . . .
3.3 Utilizando as Preferncias do Android . . .
3.3.1 Atualizando colunas de uma tabela .
3.3.2 Array de Strings . . . . . . . . . . .
3.3.3 Spinner, dilogo de seleo . . . . .
iii

.
.
.
.
.
.
.

. . . . . .
ListView
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

iv

SUMRIO

3.4

3.3.4
Grupo
3.4.1
3.4.2
3.4.3
3.4.4

A classe PreferenceActivity . . . . . . . .
de Contatos usando Grid . . . . . . . . .
Layout usando GridView . . . . . . . . .
Activity para visualizar os Grupos . . . .
Implementando o Adapter . . . . . . . . .
Selecionando contatos de um determinado

. . . .
. . . .
. . . .
. . . .
. . . .
grupo

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

37
41
41
42
45
46

A Sobre o Autor

49

Glossrio

51

Lista de Cdigos-fonte
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

Exemplo de banco de dados [exemplo-bd.sql] . . . . . . . . . . . .


Exemplo de query com subquery [exemplo-bd.sql] . . . . . . . . . .
Projeto inicial [AndroidManifest.xml] . . . . . . . . . . . . . . . . .
Layout principal [res/layout/main.xml] . . . . . . . . . . . . . . . .
Menu principal [res/menu/main menu.xml] . . . . . . . . . . . . .

Definir layout [MainActivity.java] . . . . . . . . . . . . . . . . . . .


Criando o menu [MainActivity.java] . . . . . . . . . . . . . . . . . .
Formulrio principal [res/layout/salvar.xml] . . . . . . . . . . . . .
Mudando de Activity [MainActivity.java] . . . . . . . . . . . . . . .
Utilizando EditTexts [SalvarActivity.java] . . . . . . . . . . . . . .
Mapear SalvarActivity [AndroidManifest.xml] . . . . . . . . . . . .
Helper da aplicao [ContatoHelper.java] . . . . . . . . . . . . . . .
Criar novo contato [ContatoHelper.java] . . . . . . . . . . . . . . .
Fim da iterao criar contato [SalvarActivity.java] . . . . . . . . .
Layout para cada linha da lista [res/layout/linha.xml] . . . . . . .
Listar contatos existentes [ContatoHelper.java] . . . . . . . . . . .
Classe Holder [MainActivity.java] . . . . . . . . . . . . . . . . . . .
Classe Adapter [MainActivity.java] . . . . . . . . . . . . . . . . . .
Popular ListView [MainActivity.java] . . . . . . . . . . . . . . . . .
Passagem de parmetros [MainActivity.java] . . . . . . . . . . . . .
Ler e atualizar dados existentes [ContatoHelper.java] . . . . . . . .
Usando Activity para criar ou atualizar [SalvarActivity.java] . . . .
Deletar dados existentes [ContatoHelper.java] . . . . . . . . . . . .
Adicionar Listener para click longo [MainActivity.java] . . . . . . .
Dilogo de confirmao ao deletar contato [MainActivity.java] . . .
Distino de dados [res/layout/salvar.xml] . . . . . . . . . . . . . .
Validao dos dados [SalvarActivity.java] . . . . . . . . . . . . . . .
Permisso de realizar chamadas [AndroidManifest.xml] . . . . . . .
Item chamar no dilogo [MainActivity.java] . . . . . . . . . . . . .
Item enviar e-mail no dilogo [MainActivity.java] . . . . . . . . . .
Forando regio [SalvarActivity.java] . . . . . . . . . . . . . . . . .
Nova coluna grupo na base de dados [ContatoHelper.java] . . . . .
Modificao nas queries [ContatoHelper.java] . . . . . . . . . . . .
Array de Strings [strings.xml] . . . . . . . . . . . . . . . . . . . . .
Adicionando elemento Spinner [res/layout/salvar.xml] . . . . . . .
Utilizao de Spinner [SalvarActivity.java] . . . . . . . . . . . . . .
XML descrevendo layout de preferncias [res/xml/preferencias.xml]
v

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

7
7
9
10
10
11
12
13
14
14
14
15
15
16
17
18
18
19
20
21
21
22
23
24
26
28
29
30
31
32
33
34
35
36
36
37
38

vi

LISTA DE CDIGOS-FONTE
38
39
40
41
42
43
44
45
46
47
48
49
50
51

Activity para mostrar preferncias [EditarPreferencias.java] . . . . . . . .


Mapeando Activity EditarPreferencias [AndroidManifest.xml] . . . . . . .
Adicionar item Preferncias ao menu principal [res/menu/main menu.xml]

Ir para Preferncias pelo menu principal [MainActivity.java] . . . . . . . .


Mudana em mtodo irParaSalvar [MainActivity.java] . . . . . . . . . . .
Obtem o valor padro definido nas Preferncias [SalvarActivity.java] . . .
Item do Layout de Grupos [res/layout/grupos item.xml] . . . . . . . . . .

Layout de Grupos [res/layout/grupos.xml] . . . . . . . . . . . . . . . . . .


Activity para visualizar Grupos [GruposActivity.java] . . . . . . . . . . . .
Adapter responsvel por cada item do Grid [GruposActivity.java] . . . . .
implementao do Adapter [GruposActivity.java] . . . . . . . . . . . . . .
Mtodo listar com parmetro grupo [ContatoHelper.java] . . . . . . . . .
Evento de clique em um item do grid [GruposActivity.java] . . . . . . . .
Captura de parmetro vindo de GruposActivity [MainActivity.java] . . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.

38
38
39
39
40
40
41
42
42
43
45
46
47
47

Lista de Tabelas
1.1

Tipos de dados do Sqlite . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2.1

Conveno para nome dos cones . . . . . . . . . . . . . . . . . . . . . . . . 11

3.1
3.2

Paleta de cores do Android . . . . . . . . . . . . . . . . . . . . . . . . . . . 44


Localizao e tamanho dos cones . . . . . . . . . . . . . . . . . . . . . . . . 44

vii

viii

LISTA DE TABELAS

Lista de Figuras
2.1

Layout linha da Lista

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

3.1

Tela de Grupos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48

ix

LISTA DE FIGURAS

Captulo 1

Preparando o Ambiente de
Desenvolvimento
1.1

Introduo

O desenvolvimento de aplicativos para a plataforma Android feito na linguagem Java.


Para esta apostila sero utilizados os seguintes aplicativos e bibliotecas:
I Ubuntu 10.04 ou 12.04
I Java JDK 6 ou 7
I Android SDK
I Android 2.2 API 8
I Eclipse Juno
I ADT Plugin
I Sqlite3
I Sqliteman
I Inkscape
Voc pode estar se perguntando: Por que utilizar essa configurao?. Bom, para
comear um ambiente de desenvolvimento precisa ser estvel, e para isso nada melhor que
o http://releases.ubuntu.com/lucid/ (Ubuntu 10.04) ou ainda o http://releases.
ubuntu.com/precise/ (Ubuntu 12.04) por serem LTS.
A IDE Eclipse funciona independente do sistema operacional, ento podemos utilizar
a verso mais recente. O mesmo para o plugin ADT.
Usaremos especificamente para os exemplos a seguir a verso 2.2 do Android. Essa
API uma tima escolha inicial, pois a mais utilizada pelos aparelhos mais simples que
rodam Android. claro que voc poder instalar outras verses e compilar seus aplicativos
para tablets, etc.
1

CAPTULO 1. PREPARANDO O AMBIENTE DE DESENVOLVIMENTO

1.2

Instalao

A instalao do Java JDK 6 no Ubuntu 10.04 no a mesma que no Ubuntu 12.04. Isso
porque na poca de lanamento do lucid, em 2010, a empresa que desenvolvia o Java
era a Sun Microsystems, que tinha um canal nos repositrios do Ubuntu como parceira
(partner). Ainda em 2010 a empresa Oracle comprou a Sun junto com seu software e
hardware. Nesse ponto o canal de parceria foi desligado.
Discusses a parte, vamos ver as duas maneiras de instalar o Java.

1.2.1

Java JDK 6

A instalao do Java no Ubuntu 10.04 bastante simples. Voc apenas ir precisar habilitar repositrio de terceiros, ou Partner. Isso pode ser feito atravs do aplicativo Synaptic.
No menu principal do Ubuntu clique em Sistema Administrao Gerenciador
de pacotes Synaptic.
No menu do Synaptic clique em Configurao Repositrios. Na aba Outro
Software temos vrios itens que representam repositrios. Marque os dois repositrios que
terminam com partner. Feche e depois clique em Editar Recarregar informaes
dos pacotes ou simplesmente Ctrl + R.
Aps a atualizao dos pacotes existentes nos repositrios j possvel encontrar o
Java JDK 6. No campo de Pesquisa rpida digite: sun-java6. Clique com boto
direito no pacote sun-java6-jdk e selecione a opo Marcar para instalao. Depois
basta Aplicar as mudanas. Para isso clique em Editar Aplicar as alteraes
marcadas ou Ctrl + P.
Para a instalao no Ubuntu 12.04 temos que habilitar um repositrio de terceiros,
tambm conhecido como PPA (Personal Package Archives). Abra um terminal e execute
os passos a seguir para adicionar um repositrio e instalar o Java:
$
#
#
#

sudo su
apt-add-repository ppa:flexiondotorg/java
apt-get update
apt-get install sun-java6-jdk

Um pouco de Linux
Para quem no est familiarizado com o ambiente Linux vamos a uma pequena explicao. Nos comandos acima aparecem dois caracteres que no devem ser escritos mas que
representam algo importante no mbito dos comandos, so eles $ e #. Estes caracteres
indicam qual o nvel do usurio; $ significa usurio comum, # representa super usurio
(root). No comando sudo su onde trocamos de usurio comum para super usurio.
Neste momento voc ter que entrar com sua senha de login.
Java JDK 7
Segundo a pgina de Requerimentos do Sistema (http://developer.android.com/sdk/
requirements.html) do site oficial do Android, necessrio uso do Java 6. Caso voc
queira utilizar o Java 7, voc ter que configurar seu projeto Android para ser compilado
com suporte a verso 6.

1.2. INSTALAO

A instalao do Java 7 no Ubuntu 12.04 pode ser feita da seguinte maneira:


$
#
#
#

sudo su
add-apt-repository ppa:webupd8team/java
apt-get update
apt-get install oracle-jdk7-installer

Aps criar o projeto clique com boto direito do mouse em seu projeto e selecione
Properties. Na lista de itens do lado esquerdo selecione Java Compiler. Da basta clicar
em Enable project specific settings e logo abaixo escolher o nvel de compilao em
Compiler compliance level, escolha 1.6.

1.2.2

Android SDK

Para o Android SDK comece pelo download http://developer.android.com/sdk/index.


html.
A instalao feita apenas colocando o SDK em um diretrio do sistema. Existem 2
bons locais para abrigar bibliotecas no Linux, so elas: /opt e /usr/local/lib. Nesse
exemplo vamos utilizar este ltimo. Abra um terminal e vamos aos comandos.
Se voc baixou o SDK para seu diretrio Downloads, proceda da seguinte maneira:
$
$
$
#
#
#
#
#

cd /home/usuario/Downloads
tar -xf android-sdk r18-linux.tgz

sudo su
mv android-sdk-linux /usr/local/lib
cd /usr/local/lib
ln -s android-sdk-linux android-sdk
cd android-sdk/tools
ln -s android /usr/local/bin/android

Obs.:

troque usuario na primeira linha pelo seu login do sistema.

O poder do Linux
D ateno ao uso do comando ln. Ele responsvel por criar links simblicos. Isso
muito til quando se instala um aplicativo ou biblioteca, pois proporciona atualizao sem
que outros ajustes sejam feitos. Neste caso basta linkar outra vez e pronto.
Note que no ltimo comando temos um link simblico para o diretrio /usr/local/bin.
nele que colocamos os executveis globais, ou seja, que so vistos a partir de qualquer
outro diretrio. Agora saindo do modo root e usando seu prprio usurio instalaremos a
API.

1.2.3

Android 2.2 API 8

Ainda no terminal, agora como usurio comum, vamos abrir o aplicativo que instala qualquer uma das API disponibilizadas pelo Android.
$ android

CAPTULO 1. PREPARANDO O AMBIENTE DE DESENVOLVIMENTO

O aplicativo Android SDK and AVD Manager ir aparecer. Clique em Avaliable


packages e procure pela verso 2.2 API 8 do Android. Selecione e clique em Install
Selected. Aps o download voc pode verificar a verso instalada em Installed packages,
um dos itens algo como SDK Plataform Android 2.2, API 8, revision 2.
Se voc quiser aproveite para baixar outras verses para utilizar em projetos futuros.

1.2.4

Android Virtual Device (AVD)

Vamos aproveitar e criar nosso AVD para testar pela primeira vez nosso emulador. Ainda
no Android SDK and AVD Manager clique em Virtual devices, depois em New...
D um nome. Voc pode usar qualquer nomenclatura, mas interessante que tenha
algo haver com a verso. Assim, caso voc tenha que testar seu cdigo em outras verses
voc poder saber qual emulador utilizar. Por exemplo use android-2.2. Em Target
escolha a verso, neste caso Android 2.2 - API Level 8. Pronto, apenas clique em
Create AVD.
Dicas
A opo Skin indica qual a resoluo da tela do aparelho. Como no possvel redimensionar a janela, em alguns monitores a janela fica maior que a tela do seu monitor.
A opo Snapshot quando habilitada, serve para salvar o estado do emulador. Isso faz
com que da segunda inicializao em diante se torne mais rpida.
A opo SD Card ideal caso sua aplicao necessite guardar dados como fotos, arquivos. O AVD ir reservar um espao em seu HD permitindo assim o acesso a dados pelo
emulador.

1.2.5

Eclipse Juno

O IDE Eclipse pode ser encontrada em http://www.eclipse.org/downloads/. Para o desenvolvimento de aplicativos para o Android a verso Eclipse IDE for Java Developers
ideal. Mas se voc tiver interesse em aplicativos Java para Web a opo baixar a verso
Eclipse IDE for Java EE Developers.
Em todo caso as duas vo servir para o desenvolvimento, pois ambas vem com suporte
a Java.
O Eclipse no possui instalador, no caso ele j vem pr-compilado. Basta apenas
descompactar e executar o arquivo eclipse.
Para sua comodidade voc pode adicionar o Eclipse no menu do Ubuntu. Isso pode
ser feito apenas clicando com o boto direiro do mouse no menu principal e escolhendo a
opo Editar menus. Ou voc pode usar a dica do blog MAD3 Linux
(http://www.mad3linux.org) - http://va.mu/VSgR. Essa dica ir lhe mostrar como
adicionar um item ao menu visvel a todos os usurios.

1.2.6

Plugin ADT

Para a instalao do plugin ADT vamos abrir o Eclipse, e em seu menu selecione Help
Eclipse Marketplace...
Busque por adt e escolha o Android Development Tools for Eclipse da Google,
Inc., Apache 2.0 e clique em Install. O Eclipse ir pedir confirmao sobre os itens

1.2. INSTALAO

a serem instalados, clique em Next. Agora basta aceitar os termos de uso e clicar em
Finish. Aps o download e a instalao, reinicie o Eclipse.
No Eclipse Marketplace voc pode encontrar outras ferramentas bastante teis para
um bom desenvolvimento. Clique na aba Popular e veja as ferramentas mais baixadas,
talvez exista uma que voc no conhea mas que sempre precisou.
Configurando o ADT
Agora que o plugin foi instalado temos que dizer ao Eclipse onde ns instalamos o Android
SDK. Isso pode ser feito clicando no menu Window Preferences. Selecione Android
no painel lateral esquerdo. Em SDK Location clique em Browse... e indique o diretrio
do SDK, caso no lembre, ele est em /usr/local/lib/android-sdk. Clique em Apply
na parte inferior direita para atualizar a lista de APIs disponveis.
Caso voc tenha mais dvidas d uma olhada na pgina oficial de instalao do plugin
ADT localizada em http://developer.android.com/sdk/eclipse-adt.html.
Testando o ADT
Para testar o Android Development Tools ou ADT crie um projeto Android. No menu
do Eclipse selecione File New Project...
Selecione Android Application Project e clique em Next. D um nome qualquer
ao seu aplicativo, por exemplo hello.android. Note que o ADT tenta dar um nome
ao seu pacote e ao diretrio de arquivos a partir do nome que voc digitou. Deixe como
est. Em Build SDK preciso escolher qual API vamos utilizar, em nosso caso escolha
a Android 2.2 (API 8). Em Minimum Required SDK escolha a API 8: Android 2.2
(Froyo) indicando que a verso mnima a API 8. Clique em Next.
Na verso do ADT para o Eclipse Juno, uma novidade apareceu. possvel criar o
cone lanador logo ao criar o aplicativo. Selecione da maneira que achar melhor e clique
em Next. Depois clique em Finish.
Aps isso clique com boto direito do mouse no projeto recm criado, e Run As
Android Application. Se tudo tiver dado certo possvel ver no emulador sua primeira
aplicao rodando.
Dicas
Uma vez que voc abriu o emulador no o feche. Voc ir notar que ao abrir pela primeira
vez ele leva um tempo para isso. Neste caso ao atualizar o cdigo-fonte apenas rode
o aplicativo novamente. O plugin ADT far com que o aplicativo seja reinstalado no
emulador.
Faa o teste com alguns atalhos bsicos:
Alt + Enter Maximiza o emulador. Ideal para demostraes.
Ctrl + F11 Muda a orientao do emulador, retrato ou paisagem.
F8 Liga/desliga a rede.
Outro elemento essencial o LogCat. Ele faz parte do ADT e responsvel por mostrar
as mensagens de log do emulador. Caso voc encontre problemas com seu cdigo o LogCat
ser seu melhor aliado. Para acess-lo no Eclipse clique no menu Window Show View
Other..., clique em Android LogCat.

CAPTULO 1. PREPARANDO O AMBIENTE DE DESENVOLVIMENTO

1.2.7

Sqlite3

Sendo o Sqlite o banco de dados embutido na plataforma Android, nada melhor do que
aprendermos um pouco sobre ele.
O Sqlite um banco de dados relacional bastante utilizado por dispositivos e sistemas
embarcados por ser leve, robusto, de fcil configurao e, acima de tudo, livre. Para a
instalao, abra um terminal como root e:
$ sudo su
# apt-get install sqlite3
Aps a instalao possvel utilizar o Sqlite via linha de comando. Faa logoff do
usurio root e faa os seguintes testes:
# exit
$ sqlite
SQLite version 2.8.17
Enter ".help"for instructions
sqlite>
Voc dever ver algo parecido. Para sair utilize o comando .exit. Veja outros detalhes
na pgina oficial do projeto: http://www.sqlite.org/.
Tipos de dados
Utilize a tabela abaixo para criar suas tabelas futuramente.
Nome

Descrio

INTEGER

valores inteiros, positivos ou negativos. Podem variar de 1 a 8 bytes.

REAL

valores reais ou decimais.

TEXT

usado para armazenar valores, no-limitado. Suporta vrias codificaes, por exemplo UTF-8.

BLOB

objetos binrios tais como imagens, arquivos de texto, etc. Tambm


possui tamanho no-limitado.

NULL

representa falta de informao.


Tabela 1.1: Tipos de dados do Sqlite

1.2.8

Sqliteman

Para uma gerncia mais produtiva usaremos o Sqliteman para acessar e modificar bancos
de dados. A instalao feita via linha de comando. Abra um terminal e:
$ sudo su
# apt-get install sqliteman

1.2. INSTALAO

Depois de instalado, acesse o aplicativo do menu principal do Ubuntu em Aplicativos


Escritrio Sqliteman. Faa alguns testes criando bancos de dados, depois crie
algumas tabelas. Ele possui assistentes que iro auxiliar nos primeiros momentos.
Por exemplo, crie uma base de dados e depois clique com o boto direito do mouse em
Tables. Utilize o assistente e veja como simples criar tabelas no sqlite.
1

-- Distribuies Linux

2
3
4
5
6
7
8

CREATE TABLE distros (


_id INTEGER PRIMARY KEY,
nome TEXT NOT NULL,
interface TEXT NOT NULL DEFAULT Gnome3 ,
deriva_de INTEGER REFERENCES distros(_id)
);

9
10
11
12
13
14
15
16
17
18

INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT

INTO
INTO
INTO
INTO
INTO
INTO
INTO
INTO
INTO

distros
distros
distros
distros
distros
distros
distros
distros
distros

VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES

(1,
(2,
(3,
(4,
(5,
(6,
(7,
(8,
(9,

Debian , Gnome3 , NULL);


Ubuntu , Unity , 1);
Linux Mint , Mate , 2);
Fedora , KDE , NULL);
Slackware , KDE , NULL);
Slax , KDE , 5);
Ubuntu Studio , XFCE , 2);
kUbuntu , KDE , 2);
xUbuntu , XFCE , 2);

Cdigo-fonte 1: Exemplo de banco de dados [exemplo-bd.sql]


Observe que podemos fazer auto-relacionamento na tabela. Assim somos capazes de
executar a seguinte SQL, contando o nmero de distros que derivam de uma outra original.
Veja:
1
2
3
4
5
6

SELECT d._id, d.nome, d.interface,


(
SELECT SUM( CASE WHEN aux.deriva_de = d._id THEN 1 ELSE 0 END )
FROM distros aux
) AS num_derivadas
FROM distros d
Cdigo-fonte 2: Exemplo de query com subquery [exemplo-bd.sql]
Mais informaes em: http://sqliteman.com/

1.2.9

Inkscape

Uma tima ferramenta de desenho vetorial o Inkscape. Ela ser bastante til pois o
desenvolvimento de aplicativos hoje em dia baseado muito em figuras para facilitar a
navegao, identidade visual, entre outras coisas.

CAPTULO 1. PREPARANDO O AMBIENTE DE DESENVOLVIMENTO


A instalao feita de forma simples. Num terminal:

$ sudo su
# apt-get install inkscape
Para dicas de como criar cones para os diversos elementos do Android veja a pgina
http://developer.android.com/design/style/iconography.html.

Captulo 2

Exemplo prtico
2.1

Primeira aplicao - Contatos

Baseado em 1.2.6 Testando o ADT, crie um novo aplicativo chamado Contatos. Use
contatos.app como o nome do pacote. Crie uma Activity inicial chamada MainActivity
e um layout inicial chamado main. Depois clique em Finish.
Este exemplo bastante til para aprendermos como funciona o Android. Voc s
poder criar algo se voc souber utilizar bem as ferramentas.

2.1.1

AndroidManifest.xml

Este o arquivo que define nossa aplicao, mapeia as Activitys, entre outras configuraes. Ao finalizar a criao do projeto, inicialmente este arquivo dever conter o seguinte
contedo:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

<?xml version="1.0" encoding="UTF-8"?>


<manifest xmlns:android= "http://schemas.android.com/apk/res/android"
package= "contatos.app"
android:versionCode= "1"
android:versionName= "1.0" >
<uses-sdk android:minSdkVersion= "8" android:targetSdkVersion= "8" />
<application android:icon= "@drawable/icon" android:label= "@string/app_name" >
<activity android:name= ".MainActivity" android:label= "@string/app_name" >
<intent-filter>
<action android:name= "android.intent.action.MAIN" />
<category android:name= "android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Cdigo-fonte 3: Projeto inicial [AndroidManifest.xml]
9

10

CAPTULO 2. EXEMPLO PRTICO

2.1.2

Activity

No existe mtodo main visvel ao programador no Android. Ao invs disso temos


Activitys. Para que o Android saiba qual ele deve iniciar primeiro utilizamos um
intent-filter como visto no trecho de cdigo acima da linha 09 a 12 . Para nossa
primeira Activity criaremos uma lista de contatos e um menu para criao de um novo
contato.
Para construir o layout inicial de nossa aplicao precisamos editar o arquivo main.xml
localizado em res/layout.
1
2
3
4
5
6
7
8
9
10

<?xml version="1.0" encoding="utf-8"?>


<LinearLayout xmlns:android= "http://schemas.android.com/apk/res/android"
android:orientation= "vertical"
android:layout_width= "fill_parent"
android:layout_height= "fill_parent" >
<ListView
android:id= "@+id/lv_contatos"
android:layout_width= "fill_parent"
android:layout_height= "wrap_content" />
</LinearLayout>
Cdigo-fonte 4: Layout principal [res/layout/main.xml]

Deste momento em diante tenha em mente que os arquivos xml aqui descritos so
apenas para voc poder comparar e ver se no esqueceu de nada. Todos os layouts devem
ser criados usando a ferramenta ADT. Voc ir notar que ao abrir o xml uma janela de
layout aparecer. Para visualizar o xml ou o layout grfico basta utilizar a aba inferior
esquerda.
Por fim, temos o menu. Clique com o boto direito do mouse em seu projeto e New
Other... ou Ctrl + N. Procure por Android XML File. Em Resource Type escolha a
opo Menu. Chame-o de main menu.xml.

1
2
3
4
5
6
7

<?xml version="1.0" encoding="UTF-8"?>


<menu xmlns:android= "http://schemas.android.com/apk/res/android" >
<item
android:id= "@+id/menu_add"
android:title= "Novo"
android:icon= "@android:drawable/ic_menu_add" />
</menu>
Cdigo-fonte 5: Menu principal [res/menu/main menu.xml]

Pronto, j temos nosso layout. Compile o projeto e vamos a prxima iterao.

2.1. PRIMEIRA APLICAO - CONTATOS

11

Conveno de nomes para cones


Observe que o cone utilizado no menu vem junto com o SDK do Android. Voc pode
visualizar os cones em SDK INSTALL/plataforms/android-8/data/res/drawable-hdpi

(substitua SDK INSTALL pelo diretrio de instalao do SDK do Android, no nosso caso

usr/local/lib/android-sdk, 1.2.2). Note que h namespaces ou prefixos em cada um


dos cones. O Android recomenda a seguinte conveno:

Tipo de Recurso

Prefixo

Exemplo

cones

ic

ic adicionar.png

ic launcher calendario.png

ic menu ajuda.png

ic stat notify msg.png

ic tab recente.png

ic dialog info.png

Launcher icons
Menu e Action Bar
Status bar icons
Tab icons
Dialog icons

ic launcher

ic menu

ic stat notify

ic tab

ic dialog

Tabela 2.1: Conveno para nome dos cones

Note que voc no obrigado a utilizar os prefixos citados acima, isto apenas uma
conveno. Veja mais detalhes em http://developer.android.com/guide/practices/
ui_guidelines/icon_design.html.
Abra o arquivo MainActivity.java e v ao mtodo onCreate. Defina o layout como
sendo nosso main.xml. Para isso adicione o layout main ao final do mtodo:
1
2
3
4
5

@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
}
Cdigo-fonte 6: Definir layout [MainActivity.java]

Cuidado: no ambiente Android temos uma classe chamada R. Ela existe tanto na biblioteca do Android como em cada projeto. Nesse caso faa o import da classe contatos.app.R.
A classe android.R utilizada em outras situaes, onde cdigos pr-prontos foram disponibilizados pela equipe do Android.
Agora precisamos sobrescrever os mtodos onCreateOptionsMenu e onOptionsItemSelected.
Eles iro criar o menu a partir de nosso layout e notificar quando os itens do menu forem
pressionados, respectivamente. Vamos ao cdigo:

12
1
2
3
4
5

CAPTULO 2. EXEMPLO PRTICO

@Override
public boolean onCreateOptionsMenu(Menu menu) {
new MenuInflater(this).inflate(R.menu.main_menu, menu);
return super.onCreateOptionsMenu(menu);
}

6
7
8
9
10
11
12
13
14

@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.menu_add) {
irParaSalvar();
return true;
}
return super.onOptionsItemSelected(item);
}

15
16
17
18

private void irParaSalvar() {


// no implementado ainda ...
}
Cdigo-fonte 7: Criando o menu [MainActivity.java]

2.1.3

Formulrios

Agora vamos criar nosso formulrio para criao e edio de contatos. Comearemos pelo
layout. Crie um arquivo xml em res/layout chamado salvar.xml.
Existem alguns pontos importantes para este trecho de cdigo. Comeando pelo layout
inicial, onde usaremos TableLayout. Esse layout ideal para telas com estilo tabela.
Um detalhe importante para observarmos neste layout que ele possui o atributo
stretchColumns com valor 1. Isso quer dizer que a coluna 1 da tabela ter o maior
tamanho possvel, respeitando o tamanho mnimo das outras clulas. Para visualizar as
mudanas voc pode tentar usar outros valores como 0 tornando a primeira coluna maior
que as demais, ou ainda * que far com que todas as clulas tenham o mesmo tamanho.

2.1. PRIMEIRA APLICAO - CONTATOS


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

13

<?xml version="1.0" encoding="UTF-8"?>


<RelativeLayout
android:id= "@+id/widget31"
android:layout_width= "fill_parent"
android:layout_height= "fill_parent"
xmlns:android= "http://schemas.android.com/apk/res/android" >
<TableLayout
android:id= "@+id/widget32"
android:layout_width= "fill_parent"
android:layout_height= "wrap_content"
android:orientation= "vertical"
android:stretchColumns= "1" >
<TableRow
android:id= "@+id/widget33"
android:layout_width= "fill_parent"
android:layout_height= "wrap_content"
android:orientation= "horizontal" >
<TextView
android:id= "@+id/textView1"
android:layout_width= "wrap_content"
android:layout_height= "wrap_content"
android:text= "Nome" ></TextView>
<EditText
android:id= "@+id/et_nome"
android:layout_width= "wrap_content"
android:layout_height= "wrap_content" ></EditText>
</TableRow>
<!-- faa mais duas TableRows contendo o Telefone e E-mail -->
<Button
android:id= "@+id/bt_salvar"
android:text= "Salvar"
android:layout_height= "wrap_content"
android:layout_width= "fill_parent" ></Button>
</TableLayout>
</RelativeLayout>
Cdigo-fonte 8: Formulrio principal [res/layout/salvar.xml]

Crie uma nova Activity chamada SalvarActivity dentro de contatos.app.view.


Para irmos de uma Activity para outra precisamos de um Intent. Um de seus construtores recebe como parmetros a instncia da classe em que estamos, sendo que ela deve
implementar a interface Context e o nome da classe a qual deve ser mostrada. Veja como
implementar o mtodo irParaSalvar da classe MainActivity:

14
1
2
3
4

CAPTULO 2. EXEMPLO PRTICO

private void irParaSalvar() {


Intent intent = new Intent(MainActivity.this, SaveActivity.class);
startActivity(intent);
}
Cdigo-fonte 9: Mudando de Activity [MainActivity.java]
Veremos agora como manipular EditTexts, que representam os campos de entrada
de dados. Abra o SalvarActivity e adicione o mtodo carregar e crie atributos para
guardar os EditTexts:

1
2

private EditText etNome, etFone, etEmail;


/* ... */

3
4
5
6
7
8
9

@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.salvar);
carregar();
}

10
11
12
13
14
15

private void carregar() {


etNome = (EditText) findViewById(R.id.et_nome);
etTefone = (EditText) findViewById(R.id.et_telefone);
etEmail = (EditText) findViewById(R.id.et_email);
}
Cdigo-fonte 10: Utilizando EditTexts [SalvarActivity.java]
Para que a Activity funcione precisamos mape-la no arquivo AndroidManifest.xml.
Adicione o contedo abaixo entre as tags application:

<activity android:name= ".view.SalvarActivity" ></activity>

Cdigo-fonte 11: Mapear SalvarActivity [AndroidManifest.xml]


Utilize sempre o ADT e apenas confira se o arquivo est da maneira correta.

2.1.4

Construindo o Model da aplicao

Precisamos de um helper para fazer acesso ao banco de dados. O Android prov suporte a
bancos de dados Sqlite por padro. Qualquer banco de dados que voc criar ser acessvel
pelo nome por qualquer classe na sua aplicao, mas no fora dela.
Crie uma classe chamada ContatoHelper em contatos.app.model que extende de
SQLiteOpenHelper. Essa classe ser capaz de ler e escrever no banco de dados graas aos
mtodos getReadableDatabase() e getWritableDatabase(), respectivamente.

2.1. PRIMEIRA APLICAO - CONTATOS

15

A princpio temos que criar um construtor passando como parmetros o nome do banco
de dados e a verso da DDL (Data Definition Language). Logo em seguida precisamos
implementar os mtodos onCreate, no qual iremos criar as tabelas e onUpdate, caso
tenhamos que alterar alguma tabela.
1

package contatos.app.model;

2
3
4
5

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

6
7

public class ContatoHelper extends SQLiteOpenHelper {

private static final String DATABASE_NAME = "contatos.db" ;


private static final int VERSION = 1;

9
10
11

public ContatoHelper(Context context) {


super(context, DATABASE_NAME, null, VERSION);
}

12
13
14
15

@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL( "CREATE TABLE contato (_id INTEGER PRIMARY KEY AUTOINCREMENT,"

16
17
18

+ " nome TEXT, fone TEXT, email TEXT);" );

19

20
21

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// nada a fazer por enquanto ...
}

22
23
24
25
26

}
Cdigo-fonte 12: Helper da aplicao [ContatoHelper.java]
Para a iterao de criao de um novo contato, ainda em ContatoHelper vamos adicionar um mtodo criar. Faa:

1
2
3

public void criar(ContentValues values) {


getWritableDatabase().insert( "contato" , "telefone" , values);
}
Cdigo-fonte 13: Criar novo contato [ContatoHelper.java]
Agora temos que fazer a chamada do mtodo criar da classe ContatoHelper em
SalvarActivity. Para isso temos que criar uma instncia de ContatoHelper, adicionar
o boto salvar e adicionar um Listener de click (faa o import da classe
android.view.View.OnClickListener). Vamos ao cdigo:

16
1
2
3

CAPTULO 2. EXEMPLO PRTICO

/* ... */
private ContatoHelper helper;
private Button btSalvar;

4
5
6
7
8
9
10
11
12

@Override
public void onCreate(Bundle icicle) {
/* ... */
helper = new ContatoHelper(this);
carregar();
ir();
/* ... */
}

13
14
15
16
17

private void carregar() {


/* ... */
btSalvar = (Button) findViewById(R.id.bt_salvar);
}

18
19
20

private void ir() {


btSalvar.setOnClickListener(new OnClickListener() {

21

public void onClick(View view) {


ContentValues values = new ContentValues();
values.put( "nome" , etNome.getText().toString());
values.put( "telefone" , etTefone.getText().toString());
values.put( "email" , etEmail.getText().toString());
helper.criar(values);
finish();
}

22
23
24
25
26
27
28
29

});

30
31

32
33
34
35
36
37

@Override
protected void onDestroy() {
super.onDestroy();
helper.close();
}
Cdigo-fonte 14: Fim da iterao criar contato [SalvarActivity.java]
Com essa implementao j possvel salvar contatos na base de dados.

2.1.5

Mostrando os dados na View

Aps salvar os dados no banco, devemos ser capazes de obter tais informaes e coloclas em forma de Lista. Para isso criaremos um novo layout que ser responsvel por
representar uma linha de nossa Lista. Essa linha deve ser semelhante a figura abaixo:

2.1. PRIMEIRA APLICAO - CONTATOS

17

Figura 2.1: Layout linha da Lista


Para isso crie um arquivo chamado linha.xml em res/layout com o seguinte contedo.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

<?xml version="1.0" encoding="UTF-8"?>


<LinearLayout xmlns:android= "http://schemas.android.com/apk/res/android"
android:layout_width= "fill_parent" android:layout_height= "wrap_content"
android:orientation= "horizontal" >
<ImageView
android:id= "@+id/linha_icone" android:layout_width= "wrap_content"
android:layout_height= "fill_parent" android:src= "@drawable/ic_launcher" >
</ImageView>
<LinearLayout
android:layout_width= "fill_parent" android:layout_height= "wrap_content"
android:orientation= "vertical" >
<TextView
android:id= "@+id/linha_nome" android:layout_width= "fill_parent"
android:layout_height= "wrap_content" android:textStyle= "bold"
android:ellipsize= "end" ></TextView>
<TextView
android:id= "@+id/linha_fone" android:layout_width= "fill_parent"
android:layout_height= "wrap_content" ></TextView>
<TextView
android:id= "@+id/linha_email" android:layout_width= "fill_parent"
android:layout_height= "wrap_content" ></TextView>
</LinearLayout>
</LinearLayout>
Cdigo-fonte 15: Layout para cada linha da lista [res/layout/linha.xml]
Note a possibilidade de aninhar o LinearLayout. Fazendo isso possvel criar o
layout desejado fazendo com que alguns elementos sejam inseridos na horizontal, outros
na vertical.
Outro ponto interessante o uso de negrito no TextView correspondente ao nome, na linha 14 , e o uso de reticncias caso o nome seja maior que a tela usando android:ellipsize="end"
na linha 15 .

18

CAPTULO 2. EXEMPLO PRTICO

Agora vamos at ContatoHelper e adicionar o mtodo listar. E tambm adicionaremos mtodos para facilitar a obteno dos valores de cada atributo.
1
2
3
4
5

public Cursor listar() {


return getReadableDatabase()
.rawQuery( "SELECT _id, nome, fone, email FROM contato ORDER BY nome" ,
null);
}

6
7
8
9

public String getNome(Cursor c) {


return c.getString(1);
}

10
11
12
13

public String getFone(Cursor c) {


return c.getString(2);
}

14
15
16
17

public String getEmail(Cursor c) {


return c.getString(3);
}
Cdigo-fonte 16: Listar contatos existentes [ContatoHelper.java]
Os elementos de um Cursor so numerados iniciando de 0 (zero). Neste caso o 0 a
coluna id. Note que ela no ser usada pelo programador e sim pelo Android. Isto ser

visto com mais detalhes em 2.1.6 Editando dados existentes.


Para popular cada linha de nossa Lista vamos criar uma classe interna (inner class)
em MainActivity. Assim podemos fazer cache dos objetos aumentando a performance.
Use o sufixo Holder para esse tipo de classe.

1
2

private static class ContatoHolder {


private TextView nome, fone, email = null;

public ContatoHolder(View linha) {


nome = (TextView) linha.findViewById(R.id.linha_nome);
fone = (TextView) linha.findViewById(R.id.linha_fone);
email = (TextView) linha.findViewById(R.id.linha_email);
}

4
5
6
7
8
9

public void popularForm(Cursor c, ContatoHelper helper) {


nome.setText(helper.getNome(c));
fone.setText(helper.getFone(c));
email.setText(helper.getEmail(c));
}

10
11
12
13
14
15

}
Cdigo-fonte 17: Classe Holder [MainActivity.java]

2.1. PRIMEIRA APLICAO - CONTATOS

19

Levando em conta que estamos usando a interface Cursor em nosso Helper temos
que criar uma classe que extenda de CursorAdapter que ser responsvel por definir o
layout de cada linha da Lista. Crie uma classe interna chamada ContatoAdapter. Iremos
sobrescrever dois mtodos, newView() e bindView(), que so responsveis por inflar
(inflate) uma nova linha e reciclar uma linha existente, respectivamente.

1
2

private ContatoHelper helper;


/* ... */

3
4

private class ContatoAdapter extends CursorAdapter {

public ContatoAdapter(Cursor c) {
super(MainActivity.this, c);
}

6
7
8
9

@Override
public View newView(Context cntxt, Cursor cursor, ViewGroup vg) {
LayoutInflater inflater = getLayoutInflater();
View linha = inflater.inflate(R.layout.linha, vg, false);
ContatoHolder holder = new ContatoHolder(linha);
linha.setTag(holder);
return linha;
}

10
11
12
13
14
15
16
17
18

@Override
public void bindView(View view, Context cntxt, Cursor cursor) {
ContatoHolder holder = (ContatoHolder) view.getTag();
holder.popularForm(cursor, helper);
}

19
20
21
22
23
24

}
Cdigo-fonte 18: Classe Adapter [MainActivity.java]

Com a introduo do Helper teremos que criar uma instncia da classe Cursor para
popular nossa ListView. Vamos ao cdigo-fonte:

20
1
2
3
4

CAPTULO 2. EXEMPLO PRTICO

/* ... */
private Cursor model = null;
private ContatoAdapter adapter = null;
private ListView listView = null;

5
6
7
8
9
10
11

@Override
public void onCreate(Bundle icicle) {
/* ... */
helper = new ContatoHelper(this);
carregar();
}

12
13
14
15
16
17
18
19

private void carregar() {


listView = (ListView) findViewById(R.id.lv_contatos);
model = helper.listar();
startManagingCursor(model);
adapter = new ContatoAdapter(model);
listView.setAdapter(adapter);
}

20
21
22
23
24
25
26

@Override
protected void onDestroy() {
super.onDestroy();
model.close();
helper.close();
}
Cdigo-fonte 19: Popular ListView [MainActivity.java]

Nunca esquecendo de fechar o helper ao sair, pois assim garantimos que a conexo
com o banco ser fechada.

2.1.6

Editando dados existentes

Para a edio de informaes usaremos o mesmo Activity do criar, ou seja, SalvarActivity.


Para isso precisamos passar um parmetro para o Activity. Usaremos ento um mtodo
do Intent que responsvel por isso, putExtra(chave, valor).
Para uma passagem de parmetros segura devemos usar um namespace para que no
colida com nenhum nome j utilizado pelo Android. Assim, vamos criar uma varivel
esttica do tipo String. Isso acontecer quando o usurio pressionar a linha que ele
deseja editar. Podemos fazer isso utilizando a interface OnItemClickListener.
Vamos incrementar tambm o mtodo irParaSalvar passando o parmetro caso haja
um. Vamos ao cdigo:

2.1. PRIMEIRA APLICAO - CONTATOS


1
2

21

/* ... */
public static final String _ID = "contatos.app._ID" ;

3
4
5
6
7
8

@Override
public void onCreate(Bundle icicle) {
/* ... */
configurar();
}

9
10
11
12

private void irParaSalvar() {


irParaSalvar(null);
}

13
14
15
16
17
18
19
20

private void irParaSalvar(String id) {


Intent intent = new Intent(MainActivity.this, SalvarActivity.class);
if (id != null) {
intent.putExtra(_ID, id);
}
startActivity(intent);
}

21
22
23
24
25
26
27
28
29

private void configurar() {


listView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
irParaSalvar(String.valueOf(id));
}
});
}
Cdigo-fonte 20: Passagem de parmetros [MainActivity.java]
Agora hora de tratar nosso parmetro no SalvarActivity. Caso haja um parmetro
precisamos obter os dados existentes no banco de dados para ento edit-lo. Neste caso
precisaremos de mais dois mtodos em ContatoHelper, que so ler e atualizar.

1
2
3
4

public Cursor ler(String id) {


return getReadableDatabase().rawQuery( "SELECT _id, nome, telefone, " +
"email FROM contato WHERE _id = ?" , new String[]{id});
}

5
6
7
8

public void atualizar(String id, ContentValues values) {


getWritableDatabase().update( "contato" , values, "_id = ?" , new String[]{id});
}
Cdigo-fonte 21: Ler e atualizar dados existentes [ContatoHelper.java]

22

CAPTULO 2. EXEMPLO PRTICO

O prximo passo tratar no SalvarActivity caso o parmetro tenha sido enviado


ou no. Caso positivo devemos carregar os dados existentes no banco de dados e depois
atualiz-los.
1
2

/* ... */
private String contatoId = null;

3
4
5
6
7
8
9
10

private void carregar() {


/* ... */
contatoId = getIntent().getStringExtra(MainActivity._ID);
if (contatoId != null) {
carregarContato();
}
}

11
12
13
14
15
16
17
18
19

private void carregarContato() {


Cursor cursor = helper.ler(contatoId);
cursor.moveToFirst();
etNome.setText(helper.getNome(cursor));
etFone.setText(helper.getFone(cursor));
etEmail.setText(helper.getEmail(cursor));
cursor.close();
}

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

private void ir() {


btSalvar.setOnClickListener(new OnClickListener() {
public void onClick(View view) {
ContentValues values = new ContentValues();
values.put( "nome" , etNome.getText().toString());
values.put( "telefone" , etTefone.getText().toString());
values.put( "email" , etEmail.getText().toString());
if (contatoId == null) {
helper.criar(values);
} else {
helper.atualizar(contatoId, values);
}
finish();
}
});
}
Cdigo-fonte 22: Usando Activity para criar ou atualizar [SalvarActivity.java]
Com isso encerramos um CRUD bsico, mas completo. A seguir temos implementaes mais especficas que iro tornar nossa aplicao mais profissional.

Captulo 3

Livro de Receitas
3.1

Mostrando Dilogos

No Android, podemos criar dilogos no Activity mostrando opes ao usurio, como por
exemplo, escolher itens de uma lista, ou responder sim ou no a uma ao, etc.
Vamos incrementar algumas partes de nosso cdigo e tentar encaixar algumas funcionalidades relacionadas.

3.1.1

Editar/Excluir ao clicar e segurar na ListView

Vamos implementar uma ao comum no mundo Android, que a seguinte: ao clicar e


segurar num item da ListView, ele mostra opes editar e excluir, por exemplo. Isto pode
ser feito facilmente usando AlertDialog.Builder, uma classe com mtodos pr-prontos
para serem usados por voc.
Neste exemplo, precisaremos editar ContatoHelper e adicionar um mtodo para deletar um contato, editar nosso MainActivity no mtodo configurar e adicionar um
Listener que ao clicar e segurar num item da ListView um mtodo acionado. Vamos a
implementao:

1
2
3
4
5

public int deletar(String id) {


String whereClause = "_id = ?" ;
String[] whereArgs = {id};
return getWritableDatabase().delete( "contato" , whereClause, whereArgs);
}
Cdigo-fonte 23: Deletar dados existentes [ContatoHelper.java]
23

24
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

CAPTULO 3. LIVRO DE RECEITAS

/* ... */
private void configurar() {
/* ... */
listView.setOnItemLongClickListener(new OnItemLongClickListener() {
public boolean onItemLongClick(AdapterView<?> parent, View view,
int position, final long id) {
final String[] itens = { "Editar" , "Deletar" };
AlertDialog.Builder dialogo =
new AlertDialog.Builder(MainActivity.this);
dialogo.setTitle( "Opes" );
dialogo.setItems(itens, new OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case 0: // editar
irParaSalvar(String.valueOf(id));
break;
case 1: // deletar
int linhasAfetadas = helper.deletar(String.valueOf(id));
if (linhasAfetadas > 0) {
exibirMensagem( "Contatos deletado com sucesso." );
carregar();
} else {
exibirMensagem( "Falha ao deletar contato." );
}
break;
}
}
});
dialogo.show();
return true;
}
});
}

34
35
36
37

private void exibirMensagem(String mensagem) {


Toast.makeText(this, mensagem, Toast.LENGTH_LONG).show();
}
Cdigo-fonte 24: Adicionar Listener para click longo [MainActivity.java]

Note a necessidade de um novo mtodo em MainActivity, o exibirMensagem. Ele


bastante til quando se quer exibir uma mensagem rapidamente e depois ela suma. Para
isso usamos a classe Toast.

3.1. MOSTRANDO DILOGOS

25

Interface como parmetro de um mtodo

Voc j deve ter notado o uso de interfaces como parmetro dos mtodos, por exemplo
na linha 4 e 11 do cdigo acima. Essa prtica obriga ao programador implementar a
classe na passagem dos parmetros.
Essa ideia vem de algumas linguagens de programao que possuem funes como
parmetros para outras funes. Como o Java no suporta essa caracterstica, a soluo
veio em forma de uma interface, a qual o programador obrigado a implementar seus
mtodos. Com isso o mtodo que recebe a interface como parmetro sabe exatamente o
que ela tem disponvel.
A partir dessa observao, podemos justificar o uso da palavra reservada final em
alguns parmetros dos mtodos acima. Isso acontece porque alguns parmetros so utilizados dentro da implementao das interfaces.
Caso haja a necessidade de utilizar uma implementao em outra classe voc pode criar
uma classe que implementa uma interface, por exemplo a interface OnItemLongClickListener.
Da para a passagem do parmetro apenas crie uma instncia da classe. Por exemplo, suponha que voc tenha uma classe chamada OpcoesContato que implementa OnItemLongClickListener,
nesse caso a linha 4 se tornaria:
listView.setOnItemLongClickListener(new OpcoesContato());

3.1.2

Dilogo de confirmao

Deletar dados uma ao que deve ser feita com cuidado, ento sempre bom confirmar
com o usurio se ele deseja realmente deletar, no nosso caso, um contato. Para isso
usaremos o AlertDialog.Builder mais uma vez, agora apenas com uma mensagem e os
botes Sim ou No.
Ainda em MainActivity criaremos um outro AlertDialog.Builder no momento que
o usurio clicar em Deletar. Segue o trecho:

26
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

CAPTULO 3. LIVRO DE RECEITAS

/* ... */
private void configurar() {
/* ... */
listView.setOnItemLongClickListener(new OnItemLongClickListener() {
public boolean onItemLongClick(AdapterView<?> parent, View view,
int position, final long id) {
/* ... */
dialogo.setItems(itens, new OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case 0: // editar
irParaSalvar(String.valueOf(id));
break;
case 1: // deletar
AlertDialog.Builder confirmacao =
new AlertDialog.Builder(MainActivity.this);
confirmacao.setTitle( "Deletar" );
confirmacao.setMessage( "Deseja realmente deletar este contato?" );
confirmacao.setPositiveButton( "Sim" , new OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
int linhasAfetadas = helper.deletar(String.valueOf(id));
if (linhasAfetadas > 0) {
exibirMensagem( "Contatos deletado com sucesso." );
carregar();
} else {
exibirMensagem( "Falha ao deletar contato." );
}
}
});
confirmacao.setNegativeButton( "No" , null);
confirmacao.show();
break;
}
}
});
dialogo.show();
return true;
}
});
}
Cdigo-fonte 25: Dilogo de confirmao ao deletar contato [MainActivity.java]
Pronto, agora o trecho que deleta o contato foi movido para dentro do Listener do
boto Sim. No boto No passamos null no Listener, pois caso seja a opo escolhida
apenas fazemos nada. Voc pode se quiser criar um Listener e mostrar uma mensagem
do tipo, Cancelado pelo usurio, para isso usando o mtodo exibirMensagem.

3.1. MOSTRANDO DILOGOS

3.1.3

27

Entrada de diferentes tipos de dados

O Android foi desenvolvido com muitos recursos pr-prontos para facilitar o desenvolvimento de aplicaes. Um recurso bastante til a distino dos dados que iro ser inseridos
nos TextViews. Com isso o teclado virtual do cliente se adapta ao tipo de dado que ser
inserido. No nosso caso faremos distino do campo telefone, onde apenas nmeros e
hfens (-) podem ser inseridos, e o campo e-mail onde a presena do arroba (@) e pontos
(.) so elementos essenciais.
Vejamos alguns valores aceitos pelo inputType:

I Para textos:
. text
. textCapCharacters
. textMultiLine
. textUri
. textEmailAddress
. textPersonName
. textPassword
. textVisiblePassword
I Para nmeros:
. number
. numberSigned
. numberDecimal
. phone
. datetime
. date
. time

Precisaremos alterar apenas o salvar.xml localizado em res/layout. Localize o


atributo inputType dos campos telefone e e-mail e altere os valores da seguinte maneira:

28
1
2
3
4

<!-- ... -->


<TableRow android:id= "@+id/tableRow2"
android:layout_width= "wrap_content"
android:layout_height= "wrap_content" >
<TextView android:id= "@+id/textView2"
android:layout_width= "wrap_content"
android:layout_height= "wrap_content"
android:text= "Telefone:" ></TextView>
<EditText android:layout_width= "wrap_content"
android:layout_height= "wrap_content"

5
6
7
8
9
10
11
12
13
14
15
16

android:id= "@+id/et_telefone"
android:inputType= "phone" ></EditText>
</TableRow>
<TableRow android:id= "@+id/tableRow3"
android:layout_width= "wrap_content"
android:layout_height= "wrap_content" >
<TextView android:id= "@+id/textView3"
android:layout_width= "wrap_content"
android:layout_height= "wrap_content"
android:text= "E-mail:" ></TextView>
<EditText android:layout_width= "wrap_content"
android:layout_height= "wrap_content"

17
18
19
20
21
22
23
24
25
26

CAPTULO 3. LIVRO DE RECEITAS

android:id= "@+id/et_email"
android:inputType= "textEmailAddress" ></EditText>
</TableRow>
<!-- ... -->
Cdigo-fonte 26: Distino de dados [res/layout/salvar.xml]

3.1.4

Validao de dados

Mesmo configurando um inputType para seu TextView pode no ser o bastante para
que os dados inseridos estejam corretos. Para isso usaremos a classe Patterns do pacote
android.util. Nela podemos encontrar alguns objetos bastante teis na hora de validar
dados. Entre eles esto os objetos Patterns.EMAIL ADDRESS e Patterns.PHONE. Com

eles podemos validar de forma simples os dados inseridos em nosso formulrio.


Em nosso SalvarActivity adicionaremos um mtodo validar passando como parmetro um ContentValues. Copie o mtodo exibirMensagem da classe MainActivity
para mostrar uma mensagem caso alguma validao seja falsa.
OBS: Para um melhor reuso crie uma classe abstrata que implementa o mtodo exibirMensagem
e que extenda de Activity e faa com que seus Activitys herdem dela. uma boa prtica.
Vamos ao trecho de cdigo:

3.1. MOSTRANDO DILOGOS


1
2
3

29

/* ... */
private void ir() {
btSalvar.setOnClickListener(new OnClickListener() {

public void onClick(View view) {


ContentValues values = new ContentValues();
values.put( "nome" , etNome.getText().toString());
values.put( "telefone" , etTefone.getText().toString());
values.put( "email" , etEmail.getText().toString());
if (validar(values)) {
if (contatoId == null) {
helper.criar(values);
} else {
helper.atualizar(contatoId, values);
}
finish();
}
}

5
6
7
8
9
10
11
12
13
14
15
16
17
18

});

19
20

21
22
23
24
25
26

private boolean validar(ContentValues values) {


if (!Patterns.PHONE.matcher(values.getAsString( "telefone" )).matches()) {
exibirMensagem( "Telefone no vlido." );
return false;
}

27

if (!Patterns.EMAIL_ADDRESS.matcher(values.getAsString( "email" )).matches()) {


exibirMensagem( "E-mail no vlido." );
return false;
}
return true;

28
29
30
31
32
33

34
35
36
37
38

private void exibirMensagem(String mensagem) {


Toast.makeText(this, mensagem, Toast.LENGTH_LONG).show();
}
/* ... */
Cdigo-fonte 27: Validao dos dados [SalvarActivity.java]

3.1.5

Fazendo uma ligao

J que estamos fazendo uma lista de contatos nada melhor que usar o nmero do telefone
dos contatos inseridos para realizar chamadas. Para isso vamos aprender um pouco sobre
Permisses.
Permisses no Android so definidas no AndroidManifest.xml. Ao instalar seu aplica-

30

CAPTULO 3. LIVRO DE RECEITAS

tivo, o usurio saber quais as permisses que o seu aplicativo necessita para ser executado.
Por padro, o Android traz uma srie de permisses que auxiliam seu aplicativo a se
comunicar com o aparelho. Abaixo alguns exemplos:

I Verificao
. ACCESS NETWORK STATE

. ACCESS WIFI STATE

. BATTERY STATS

I Comunicao
. BLUETOOTH
. CALL PHONE

. INTERNET
. SEND SMS

A lista completa pode ser vista em http://developer.android.com/reference/


android/Manifest.permission.html.
Edite o AndroidManifest.xml e adicione a permissao CALL PHONE.

1
2
3
4
5
6
7
8
9

<?xml version="1.0" encoding="UTF-8"?>


<manifest xmlns:android= "http://schemas.android.com/apk/res/android"
package= "contatos.app"
android:versionCode= "1"
android:versionName= "1.0" >
<uses-permission android:name= "android.permission.CALL_PHONE" >
</uses-permission>
<!-- ... -->
</manifest>
Cdigo-fonte 28: Permisso de realizar chamadas [AndroidManifest.xml]

Agora vamos adicionar um item ao dilogo que aparece ao clicar e segurar um item
da ListView. Ele servir para implementarmos o trecho que realiza a chamada. Vamos a
ele:

3.1. MOSTRANDO DILOGOS


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

31

/* ... */
private void configurar() {
listView.setOnItemLongClickListener(new OnItemLongClickListener() {
public boolean onItemLongClick(AdapterView<?> parent, View view,
final int position, final long id) {
final String[] itens = { "Editar" , "Deletar" , "Chamar" };
/* ... */
dialogo.setItems(itens, new OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
switch (which) {
/* ... */
case 2: // chamar
model.moveToPosition(position);
startActivity(new Intent(Intent.ACTION_CALL,
Uri.parse( "tel:" + helper.getTelefone(model))
)
);
break;
}
}
});
dialogo.show();
return true;
}
});
}
Cdigo-fonte 29: Item chamar no dilogo [MainActivity.java]
Nesse trecho de cdigo podemos ver o uso de Intents do prrpio Android, nesse
caso o Intent.ACTION CALL (veja linha 14 ). Ele serve para chamar uma Activity

que realize ligaes. Atente apenas para um detalhe - esse Intent faz a chamada sem
confirmao. Caso voc queira que o usurio possa visualizar o nmero no discador use o
Intent Intent.ACTION DIAL. Faa esse teste e veja a diferena entre os Intents.

Veja mais detalhes em http://developer.android.com/reference/android/content/


Intent.html.

32

3.1.6

CAPTULO 3. LIVRO DE RECEITAS

Enviando e-mail

Para envio de e-mail voc pode simplesmente usar a aplicao de e-mail padro do aparelho. Seguindo o mesmo princpio do exemplo anterior vamos apenas inserir um trecho de
cdigo no mtodo configurar da classe MainActivity:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

/* ... */
private void configurar() {
listView.setOnItemLongClickListener(new OnItemLongClickListener() {
public boolean onItemLongClick(AdapterView<?> parent, View view,
final int position, final long id) {
final String[] itens = { "Editar" , "Deletar" , "Chamar" ,
"Enviar e-mail" };
/* ... */
dialogo.setItems(itens, new OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
switch (which) {
/* ... */
case 3: // enviar e-mail
model.moveToPosition(position);
Intent email = new Intent(Intent.ACTION_SEND);
email.setType( "plain/text" );
email.putExtra(Intent.EXTRA_EMAIL,
new String[]{ helper.getEmail(model) });
startActivity(Intent.createChooser(email,
"Enviar e-mail..." ));
break;
}
}
});
dialogo.show();
return true;
}
});
}
Cdigo-fonte 30: Item enviar e-mail no dilogo [MainActivity.java]
Ao testar no emulador voc receber a mensagem: No applications can perform
this action. Traduzindo quer dizer que: Nenhuma aplicao pode executar esta ao.
Em outras palavras, nenhum cliente de e-mail foi encontrado.

3.2
3.2.1

Internacionalizao (i18n)
Forando regio para teste

Para podermos testar as strings de i18n podemos forar o Activity a utilizar uma
determinada linguagem. Isso se d por meio da classe Locale. Faamos um teste com o

3.3. UTILIZANDO AS PREFERNCIAS DO ANDROID

33

SalvarActivity inserindo o trecho de cdigo abaixo no mtodo onCreate. Vamos a ele:


1
2
3
4
5
6
7
8

/* ... */
@Override
protected void onCreate(Bundle savedInstanceState) {
/* ... */
forceLocale( "pt" , "BR" );
carregar();
ir();
}

9
10
11
12
13
14
15
16
17
18

private void forceLocale(String language, String country) {


Locale locale = new Locale(language, country);
Locale.setDefault(locale);
Configuration configuration = new Configuration();
configuration.locale = locale;
getBaseContext().getResources()
.updateConfiguration(configuration,
getBaseContext().getResources().getDisplayMetrics());
}
Cdigo-fonte 31: Forando regio [SalvarActivity.java]
Para visualizar a mudana crie strings no seu arquivo strings.xml. Substitua as
strings Nome, Telefone, E-mail e Salvar pelos respectivos valores em ingls Name, Phone,
E-mail e Save. Agora crie outro arquivo strings.xml dentro do diretrio /res/values-pt-rBR
e insira as mesmas strings citadas anteriormente, traduzindo cada valor.
Faa testes comentando a chamada para a funo forceLocale e veja as mudanas.

3.2.2

Forando regio pelo emulador

A maneira mais rpida e prtica de forar a regio pelo prprio emulador. V at a


lista de aplicativos e procure por Custom Locale. Depois pesquise por pt BR e caso no

encontre clique em Add New Locale. Digite pt BR e clique em Add and Select.

3.3

Utilizando as Preferncias do Android

O Android j disponibiliza uma maneira de criar preferncias de forma fcil. Para demonstrar implementaremos um exemplo bem amplo, que ir nos ajudar a entender ainda mais
de Android. Para comear adicionaremos um nova coluna a nossa tabela contato chamada grupo. Depois adicionaremos um array de strings ao nosso arquivo strings.xml
e ainda vamos aprender a utilizar um Spinner, tambm conhecido como combo box. Por
ltimo, e no menos importante, usaremos as preferncias para tornar padro um valor
de nosso Spinner.

34

CAPTULO 3. LIVRO DE RECEITAS

3.3.1

Atualizando colunas de uma tabela

Como visto em 2.1.4, a classe SQLiteOpenHelper obriga-nos a implementar os mtodos


onCreate e onUpgrade. Neste ponto ser necessrio o uso do mtodo onUpgrade. Ele
serve, como o nome sugere, para atualizar a DDL do banco de dados. Isso til quando
seu cliente j possui uma verso do seu aplicativo instalada e ele quer apenas atualizar
para uma nova verso. Tambm ser necessrio adicionar a coluna grupo nas queries.
Abra a classe ContatoHelper em contatos.app.model e faa as modificaes:
1
2
3
4

public class ContatoHelper extends SQLiteOpenHelper {


/* ... */
private static final int VERSION = 2;
private static final String TAG = "ContatoHelper" ;

@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL( "CREATE TABLE contato ( _id INTEGER PRIMARY KEY AUTOINCREMENT," +
"nome TEXT, telefone TEXT, email TEXT," +
// versao 2
"grupo INTEGER NOT NULL DEFAULT 0 );" );
}

6
7
8
9
10
11
12
13

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.w(TAG, "Atualizando banco de dados da verso "
+ oldVersion + " para " + newVersion + "." );
if (newVersion > oldVersion) {
switch (oldVersion) {
case 2:
try {
db.execSQL( "ALTER TABLE contato " +
"ADD COLUMN grupo INTEGER NOT NULL DEFAULT 0" );
} catch (SQLException e) {
Log.e(TAG, "Erro ao executar SQL: " , e);
}
default:
Log.w(TAG, "Verso desconhecida: " + oldVersion +
". Criando novo banco de dados." );
db.execSQL( "DROP TABLE IF EXISTS contato" );
onCreate(db);
}
}
}

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

}
Cdigo-fonte 32: Nova coluna grupo na base de dados [ContatoHelper.java]

3.3. UTILIZANDO AS PREFERNCIAS DO ANDROID

35

Vemos neste exemplo o uso da classe Log do pacote android.util. Ela possui apenas
mtodos estticos, assim no precisamos instanciar, apenas faa a chamada dos mtodos.
Temos:
Log.w() para mostrar warnings, ou seja, avisos.
Log.e() para mensagens de erro.
Log.d() para mensagens debug.
Log.i() para mensagens informativas.
Log.v() para outras mensagens.

1
2
3
4
5
6
7

public class ContatoHelper extends SQLiteOpenHelper {


/* ... */
public Cursor listar() {
return getReadableDatabase()
.rawQuery( "SELECT _id, nome, telefone, email, grupo " +
"FROM contato ORDER BY nome" , null);
}

public int getGrupo(Cursor c) {


return c.getInt(4);
}

9
10
11
12

public Cursor ler(String id) {


String[] params = {id};
return getReadableDatabase()
.rawQuery( "SELECT _id, nome, telefone, email, grupo " +
"FROM contato WHERE _id = ?" , params);
}

13
14
15
16
17
18
19

}
Cdigo-fonte 33: Modificao nas queries [ContatoHelper.java]

3.3.2

Array de Strings

No arquivo de strings do Android possvel criar vrios recursos. Dentre eles temos
Cor, Dimenso, Estilo/Tema. Usando a ferramenta ADT, crie um String Array em
strings.xml dentro de res/values e adicione alguns itens para representar os valores da
coluna grupo, e outro String Array para representar os ndices:
Dica: voc pode tentar implementar o trecho usando uma tabela do banco de dados. A
ideia a mesma, neste caso no seria necessrio o uso de String Arrays.

36
1
2
3
4
5
6
7
8
9
10
11
12
13
14

CAPTULO 3. LIVRO DE RECEITAS

<?xml version="1.0" encoding="utf-8"?>


<resources>
<!-- ... -->
<string-array name= "array_grupos" >
<item>amigos</item>
<item>trabalho</item>
<item>conhecidos</item>
<item>famlia</item>
</string-array>
<string-array name= "index_array_grupos" >
<item>0</item><item>1</item>
<item>2</item><item>3</item>
</string-array>
</resources>
Cdigo-fonte 34: Array de Strings [strings.xml]

3.3.3

Spinner, dilogo de seleo

O Spinner ideal quando temos que escolher entre valores fixos, sejam eles estticos
ou dinmicos. Nosso exemplo ir utilizar valores estticos para popular o mesmo. Para
isso utilizaremos o array grupos que criamos em res/values/strings.xml. Tambm

veremos um exemplo de uso da classe android.R como visto em 2.1.2 em que explicado
a diferena entre as classes de recursos. Mas antes temos que atualizar nosso layout
salvar.xml. Adicione o Spinner logo abaixo do e-mail, como mostra o trecho abaixo:
1
2
3
4
5

<!-- ... -->


<TableRow
android:id= "@+id/tableRow4"
android:layout_width= "wrap_content"
android:layout_height= "wrap_content" >

6
7
8
9
10
11

<TextView
android:id= "@+id/textView4"
android:layout_width= "wrap_content"
android:layout_height= "wrap_content"
android:text= "Grupo:" />

12
13
14
15
16
17
18

<Spinner
android:id= "@+id/sp_grupo"
android:layout_width= "wrap_content"
android:layout_height= "wrap_content" />
</TableRow>
<!-- ... -->
Cdigo-fonte 35: Adicionando elemento Spinner [res/layout/salvar.xml]

3.3. UTILIZANDO AS PREFERNCIAS DO ANDROID

37

Agora j podemos carregar e popular o Spinner na classe SalvarActivity.


1
2
3

public class SalvarActivity extends Activity {


/* ... */
private Spinner spGrupo = null;

private void carregar() {


/* ... */
spGrupo = (Spinner) findViewById(R.id.sp_grupo);
ArrayAdapter<CharSequence> adapter =
ArrayAdapter.createFromResource(this,
R.array.array_grupos, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spGrupo.setAdapter(adapter);
/* antes de verificar o parmetro contatoId */
}

5
6
7
8
9
10
11
12
13
14
15

private void carregarContato() {


spGrupo.setSelection(helper.getGrupo(c));
c.close();
}

16
17
18
19
20

private void ir() {


btSalvar.setOnClickListener(new View.OnClickListener() {
/* ... */
contato.setGrupo(spGrupo.getSelectedItemPosition());
/* antes de validar e salvar */
}
}

21
22
23
24
25
26
27
28

}
Cdigo-fonte 36: Utilizao de Spinner [SalvarActivity.java]
Note a utilizao da classe android.R nas linhas 10 e 11 . Eles servem para definir
o layout do Spinner. Isso quer dizer que voc pode implementar como seu Spinner ir
aparecer na tela da mesma maneira que implementamos a linha da ListView em 2.1.5.

3.3.4

A classe PreferenceActivity

Afinal vamos utilizar as preferncias do Android. Neste exemplo a usaremos para decidir
qual grupo do array grupos aparecer selecionado por padro. A princpio um exemplo

bem simples, mas que pode ser ajustado para outras finalidades, o que importa realmente
a ideia.
Para comear criaremos um layout em res/layout chamado preferencias.xml. No
projeto clique com boto direito do mouse e selecione New Other..., pesquise por
Android XML File e Next. Em Resource Type escolha Preference e escreva preferencias
em File. Logo abaixo em Root Element escolha a opo PreferenceScreen, ento

38

CAPTULO 3. LIVRO DE RECEITAS

Finish.
Utilizando a ferramenta ADT adicione um elemento ListPreference a PreferenceScreen.
Defina os parmetros necessrios como mostra o cdigo abaixo:
1
2
3
4
5

<?xml version="1.0" encoding="utf-8"?>


<PreferenceScreen xmlns:android= "http://schemas.android.com/apk/res/android" >
<ListPreference
android:summary= "Selecione o grupo padro"
android:dialogTitle= "Escolha um Grupo"
android:entries= "@array/array_grupos"

6
7
8
9
10

android:entryValues= "@array/index_array_grupos"
android:key= "lista_grupos"
android:title= "Grupos" />
</PreferenceScreen>
Cdigo-fonte 37: XML descrevendo layout de preferncias [res/xml/preferencias.xml]
Crie uma nova classe chamada EditarPreferencias em contatos.app.view herdando de PreferenceActivity. Agora de uma maneira bem simples implementaremos
essa classe. Veja:

package app.contatos.view;

2
3
4
5

import android.os.Bundle;
import android.preference.PreferenceActivity;
import app.contatos.R;

6
7

public class EditarPreferencias extends PreferenceActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferencias);
}

9
10
11
12
13
14

}
Cdigo-fonte 38: Activity para mostrar preferncias [EditarPreferencias.java]
Para chamar a nova Activity temos ainda que mape-la no AndroidManifest e criar
um item no menu.

<activity android:name= ".view.EditarPreferencias" ></activity>

Cdigo-fonte 39: Mapeando Activity EditarPreferencias [AndroidManifest.xml]

3.3. UTILIZANDO AS PREFERNCIAS DO ANDROID


1
2
3
4
5
6
7
8
9

39

<?xml version="1.0" encoding="utf-8"?>


<menu xmlns:android= "http://schemas.android.com/apk/res/android" >
<!-- ... -->
<item
android:id= "@+id/menu_pref"
android:icon= "@android:drawable/ic_menu_preferences"
android:title= "Preferncias" >
</item>
</menu>
Cdigo-fonte
40:
Adicionar
[res/menu/main menu.xml]

item

Preferncias

ao

menu

principal

Agora que adicionamos um item ao menu, temos que capturar o evento quando o
usurio o selecionar e direcion-lo s Preferncias. Isso deve ser feito em MainActivity.
1
2
3
4
5
6
7
8
9
10
11
12

/* ... */
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.menu_add) {
irPara(SalvarActivity.class);
return true;
} else if (item.getItemId() == R.id.menu_pref) {
irPara(EditarPreferencias.class);
return true;
}
return super.onOptionsItemSelected(item);
}

13
14
15
16

private void irPara(Class<?> clazz) {


irPara(clazz, null);
}

17
18
19
20
21
22
23
24

private void irPara(Class<?> clazz, String id) {


Intent intent = new Intent(MainActivity.this, clazz);
if (id != null) {
intent.putExtra(_ID, id);
}
startActivity(intent);
}
Cdigo-fonte 41: Ir para Preferncias pelo menu principal [MainActivity.java]
Note que para ter um cdigo mais eficiente e otimizado tivemos que mudar o mtodo
irParaSalvar para irPara passando como parmetro a classe que desejamos ir. Essa
mudana boa mais causa um impacto em outros trechos do cdigo. Conserte-os da

40

CAPTULO 3. LIVRO DE RECEITAS

seguinte maneira:
1
2
3
4
5
6
7
8

/* ... */
private void configurar() {
listView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
irPara(SalvarActivity.class, String.valueOf(id));
}
});

listView.setOnItemLongClickListener(new OnItemLongClickListener() {
public boolean onItemLongClick(AdapterView<?> parent, View view,
final int position, final long id) {
/* ... */
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case 0: // editar
irPara(SalvarActivity.class, String.valueOf(id));
break;
/* ... */

10
11
12
13
14
15
16
17
18
19
20

21

22

23

24
25

}
Cdigo-fonte 42: Mudana em mtodo irParaSalvar [MainActivity.java]
Por fim temos que selecionar o item que o usurio quer que esteja selecionado por
padro ao inserir um novo contato. Assim, em SalvarActivity adicione o trecho:

1
2
3
4
5
6
7
8
9
10
11
12

private void carregar() {


/* ... */
contatoId = getIntent().getStringExtra(MainActivity._ID);
if (contatoId != null) {
carregarContato();
} else {
SharedPreferences preferencias =
PreferenceManager.getDefaultSharedPreferences(this);
spGrupo.setSelection(
Integer.parseInt(preferencias.getString( "lista_grupos" , "0" )));
}
}
Cdigo-fonte 43: Obtem o valor padro definido nas Preferncias [SalvarActivity.java]

3.4. GRUPO DE CONTATOS USANDO GRID

3.4

41

Grupo de Contatos usando Grid

Uma das coisas mais legais quando falamos de aparelhos mveis a ideia da viso da lista
de aplicativos usada comumente com o cone e o texto logo abaixo. Essa ideia pode ser
facilmente implementada em um aplicativo Android usando GridView.
Nessa implementao vamos criar uma tela que mostra os grupos de contatos em forma
de Grid e ao clicar levaremos o usurio a lista de contatos mostrando apenas aqueles
contatos de um determinado grupo.

3.4.1

Layout usando GridView

Para comear criaremos um layout em res/layout chamado grupos item.xml. Ele ir

conter a imagem e o texto que sero exibidos no GridView. Faa como mostra o trecho
abaixo:
1
2
3
4
5
6

<?xml version="1.0" encoding="utf-8"?>


<LinearLayout xmlns:android= "http://schemas.android.com/apk/res/android"
android:layout_width= "fill_parent"
android:layout_height= "match_parent"
android:gravity= "center"
android:orientation= "vertical" >

7
8
9
10
11
12

<ImageView
android:id= "@+id/iv_icone"
android:layout_width= "wrap_content"
android:layout_height= "96.0dip"
android:scaleType= "fitCenter" />

13
14
15
16
17
18
19
20
21
22
23

<TextView
android:id= "@+id/tv_texto"
android:layout_width= "fill_parent"
android:layout_height= "wrap_content"
android:layout_marginBottom= "20.0dip"
android:layout_marginTop= "2.0dip"
android:gravity= "center"
android:text= "TextView"
android:textAppearance= "?android:textAppearanceMedium" />
</LinearLayout>
Cdigo-fonte 44: Item do Layout de Grupos [res/layout/grupos item.xml]

Hora de criar o GridView. Para isso crie um novo layout em res/layout chamado
grupos.xml. Adicione apenas um GridView como mostra o trecho de cdigo abaixo:

42
1
2
3
4
5

CAPTULO 3. LIVRO DE RECEITAS

<?xml version="1.0" encoding="utf-8"?>


<LinearLayout xmlns:android= "http://schemas.android.com/apk/res/android"
android:layout_width= "match_parent"
android:layout_height= "match_parent"
android:orientation= "vertical" >

<GridView
android:id= "@+id/gv_grupos"
android:layout_width= "match_parent"
android:layout_height= "wrap_content"
android:numColumns= "3" >
<!-- Preview: listitem=@layout/grupos_item -->
</GridView>

7
8
9
10
11
12
13
14
15

</LinearLayout>
Cdigo-fonte 45: Layout de Grupos [res/layout/grupos.xml]
Dica: a ferramenta ADT prov uma forma de pr-visualizar seu layout. Note que na
linha 12 temos um comentrio e nele temos a referncia ao layout grupos item. Para

isso apenas clique com boto direito do mouse na GridView e na opo Preview Grid
Content Choose Layout... selecione grupos item.

3.4.2

Activity para visualizar os Grupos

Como de se imaginar temos que criar uma Activity para visualizar os Grupos.
1

public class GruposActivity extends Activity {

private GridView grid = null;

3
4

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

5
6
7
8

setContentView(R.layout.grupos);
carregar();

9
10

11
12

private void carregar() {


grid = (GridView) findViewById(R.id.gv_grupos);
}

13
14
15
16

}
Cdigo-fonte 46: Activity para visualizar Grupos [GruposActivity.java]

3.4. GRUPO DE CONTATOS USANDO GRID

43

Temos que criar duas classes internas para nos ajudar a criar cada item do grupo de
contatos. Para isso usaremos a classe abstrata BaseAdapter.
1
2

/* ... */
static class IconeAdapter extends BaseAdapter {

private Context context;

4
5

public IconeAdapter(Context context) {


super();
this.context = context;
}

6
7
8
9
10

static class GruposHolder {


public ImageView icone;
public TextView texto;
}

11
12
13
14
15

public int getCount() {


return 0;
}

16
17
18
19

public Object getItem(int position) {


return null;
}

20
21
22
23

public long getItemId(int position) {


return 0;
}

24
25
26
27

public View getView(int position, View convertView, ViewGroup parent) {


return null;
}

28
29
30
31

}
Cdigo-fonte 47: Adapter responsvel por cada item do Grid [GruposActivity.java]
Nesse momento precisamos usar a ferramenta Inkscape e criar alguns cones. Para os
exemplos a seguir voc deve criar um cone para cada item do grupo, sendo eles:
I amigos
I trabalho
I conhecidos
I famlia

44

CAPTULO 3. LIVRO DE RECEITAS

Para ttulo de exemplo crie apenas cones simples e depois tente fazer itens mais sofisticados. Em http://developer.android.com/design/style/iconography.html voc
pode ver como devem ser criados os cones para seu aplicativo.
Criando cones com Inkscape
Use o Inkscape para criar um novo cone. No menu Arquivo Propriedades do Desenho...
ou apenas Shift + Ctrl + D e altere a largura e altura para 512px.
Aperte 5 para centralizar a folha e crie um quadrado (F4) um pouco menor que a
pgina. Utilize Ctrl para criar um quadrado perfeito. Altere a borda usando o crculo
branco no canto superior direito do quadrado. Selecione uma cor legal.
O Android possui uma paleta de cores que pode lhe ajudar inicialmente. Veja a tabela
abaixo:
Cor

Tom claro

Tom escuro

Azul

#33B5E5 TTT

#0099CC TTT

Roxo

#AA66CC TTT

#9933CC TTT

Verde

#99CC00 TTT

#669900 TTT

Laranja

#FFBB33 TTT

#FF8800 TTT

Vermelho

#FF4444 TTT

#CC0000 TTT

Tabela 3.1: Paleta de cores do Android


Mais detalhes em http://developer.android.com/design/style/color.html.
Para alterar a cor clique com boto direito do mouse no quadrado e selecione Preenchimento
e contorno. Observe a entrada de texto onde aparece RGBA. Altere com os valores acima
mantendo os dois ltimos, pois eles so referentes a transparncia.
Chegou a hora de exportar seu cone para os tamanhos sugeridos pelo Android. Basta
ir no menu Arquivo Exportar Bitmap... ou ainda Shift + Ctrl + E. Os tamanhos
esto definidos na tabela abaixo:
Local

Tamanho

res/drawable-xhdpi

96px

res/drawable-hdpi

72px

res/drawable-mdpi

48px

res/drawable-ldpi

36px
Tabela 3.2: Localizao e tamanho dos cones

Exporte o cone para cada um desses diretrios, crie-os caso no existam. Como temos
quatro grupos crie quatro cones usando cores diferentes. Siga a nomenclatura sugerida
em 2.1.2 Conveno de nomes para cones, exemplo: ic launcher grupo amigos.png.

3.4. GRUPO DE CONTATOS USANDO GRID

3.4.3

1
2
3
4
5
6
7
8

45

Implementando o Adapter

public class GruposActivity extends Activity {


/* ... */
static final int[] icones = {
R.drawable.ic_launcher_grupo_amigos,
R.drawable.ic_launcher_grupo_trabalho,
R.drawable.ic_launcher_grupo_conhecidos,
R.drawable.ic_launcher_grupo_familia
};

private void carregar() {


/* ... */
grid.setAdapter(new IconeAdapter(getBaseContext()));
}

10
11
12
13
14

static class IconeAdapter extends BaseAdapter {

15
16

public int getCount() {


return icones.length;
}

17
18
19
20

/* ... */
public View getView(int position, View convertView, ViewGroup parent) {
GruposHolder holder = null;
View v = convertView;
if (v == null) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.grupos_item, null);
holder = new GruposHolder();
holder.texto = (TextView) v.findViewById(R.id.tv_texto);
holder.icone = (ImageView) v.findViewById(R.id.iv_icone);
v.setTag(holder);
} else {
holder = (GruposHolder) v.getTag();
}
holder.icone.setImageResource(icones[position]);
holder.texto.setText(context.getResources()
.getStringArray(R.array.array_grupos)[position]);
return v;
}

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

41
42

}
Cdigo-fonte 48: implementao do Adapter [GruposActivity.java]

46

CAPTULO 3. LIVRO DE RECEITAS

Como visto em 2.1.5 Mostrando os dados na View, no Adapter podemos fazer cache
dos objetos e otimizar o cdigo. Isso pode ser observado a partir da linha 25 at a linha
35 , onde um teste realizado para ver se a linha est em cache.

Observao: na linha 37 existe um trecho de cdigo que no est nada otimizado. No


entanto usando string-array a nica maneira de dar certo. Isso poderia ser evitado se
os grupos de contatos fossem retirados do banco de dados. Seguindo as instrues antes
abordadas tente voc mesmo implementar usando banco de dados. uma tima maneira
de aprender melhor como funciona um aplicativo Android.
Finalize adicionando o Activity no AndroidManifest.xml. Clique na aba inferior
em Application e em Application Nodes clique em Add. Escolha Activity na lista de
opes e no atributo Name clique em Browser e busque por GruposActivity.
Para visualizar a nova Activity preciso adicionar um novo item no menu principal.
Reveja 2.1.2 Activity, e implemente essa parte. No esquea de adicionar uma condio
no mtodo onOptionsItemSelected da classe MainActivity.

3.4.4

Selecionando contatos de um determinado grupo

Para no deixar dvidas quanto a implementao deste trecho vamos fazer com que ao
clicar em um determinado grupo, somente contatos daquele grupo apaream na lista que
fica em MainActivity.
Primeiro sobrescreva o mtodo listar da classe ContatoHelper para que ele receba
um parmetro, que ir representar o grupo.
1
2
3
4
5
6

public Cursor listar(String grupo) {


String[] params = {grupo};
return getReadableDatabase()
.rawQuery( "SELECT _id, nome, fone, email, grupo FROM contato " +
"WHERE grupo = ? ORDER BY nome" , params);
}
Cdigo-fonte 49: Mtodo listar com parmetro grupo [ContatoHelper.java]

A implementao do clique em um item do grid semelhante a vista em 2.1.6 Editando


dados existentes, onde criamos uma varivel contendo o namespace do nosso parmetro.
Copie o mtodo irPara da classe MainActivity, mudando apenas o primeiro parmetro de intent.putExtra para o novo namespace, na linha 17 .
Por fim, inclua o mtodo configurar em onCreate, o qual ser responsvel por
configurar para onde ir ao clicar em um item do grid.

3.4. GRUPO DE CONTATOS USANDO GRID


1

47

public static final String _GRUPO = "contatos.app._GRUPO" ;

2
3
4
5
6
7

@Override
public void onCreate(Bundle savedInstanceState) {
/* ... */
configurar();
}

8
9
10
11
12
13
14
15
16

private void configurar() {


grid.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
irPara(MainActivity.class, String.valueOf(position));
}
});
}

17
18
19
20
21
22
23
24

private void irPara(Class<?> clazz, String id) {


Intent intent = new Intent(GruposActivity.this, clazz);
if (id != null) {
intent.putExtra(_GRUPO, id);
}
startActivity(intent);
}
Cdigo-fonte 50: Evento de clique em um item do grid [GruposActivity.java]
Agora preciso capturar o parmetro em MainActivity. Para isso basta fazer como
descrito abaixo:

1
2

/* ... */
private String grupo = null;

3
4
5
6
7
8
9
10
11
12
13
14
15

private void carregar() {


listView = (ListView) findViewById(R.id.lv_contatos);
grupo = getIntent().getStringExtra(GruposActivity._GRUPO);
if (grupo == null) {
model = helper.listar();
} else {
model = helper.listar(grupo);
}
startManagingCursor(model);
adapter = new ContatoAdapter(model);
listView.setAdapter(adapter);
}
Cdigo-fonte 51: Captura de parmetro vindo de GruposActivity [MainActivity.java]

48

CAPTULO 3. LIVRO DE RECEITAS

Muito bem, eis que temos um aplicativo j bem completo. Se tudo deu certo voc deve
ter uma tela como vemos abaixo:

Figura 3.1: Tela de Grupos

Apndice A

Sobre o Autor
Estudante de Cincia da Computao no IFCE Campus Maracana, Cear, Brazil. Programador Java, PHP, Ruby. Trabalha na Fidias Software, empresa que ajudou a fundar
juntamente com Jos Alberto e Shara Shami.

Sugestes e Crticas
Para fazer sugestes e crticas envie e-mail para camurca.home@gmail.com. Para ficar
antenado no mundo do Software Livre me acompanhe no Twitter:
https://twitter.com/#!/atilacamurca.

Cdigo-fonte deste guia


Voc pode baixar o cdigo-fonte deste guia em
https://github.com/atilacamurca/guia-aberto-android.
Visite tambm a pgina do projeto
http://atilacamurca.github.com/guia-aberto-android/ e verifique se h atualizaes.

49

50

APNDICE A. SOBRE O AUTOR

Glossrio
ADT Android Development Tools (Ferramentas de Desenvolvimento Android), 1
API Application Programming Interface (Interface de Programao de Aplicativos), 1
AVD Android Virtual Device (Dispositivo Virtual Android), 4
DDL Data Definition Language (Linguagem de Definio de Dados), a parte do SQL
que permite que as tabelas do banco de dados sejam criadas, alteradas ou removidas.
Ela tambm define ndices (chaves), especifica ligaes entre tabelas, alm de impor
restries entre tabelas, 14, 33
debug termo utilizado para indicar quais as operaes que esto sendo executadas, verificando assim se esto funcionando como deveriam ou se existem defeitos, 35
IDE Integrated Development Environment (Ambiente de Desenvolvimento Integrado),
so softwares que auxiliam no desenvolvimento de outros softwares. Ex. NetBeans
IDE http://netbeans.org/, Eclipse IDE http://www.eclipse.org/, 1
JDK Java Development Kit (Kit de Desenvolvimento Java). Refere-se ao Java utilizado
para desenvolvimento, 2
LTS Long Term Support (Termo de Suporte a Longo Prazo), indica que uma verso do
Ubuntu ter atualizaes por um perodo de tempo maior, sendo assim voc ter
um ambiente estvel e sempre atualizado, 1
lucid Codinome utilizado para a verso 10.04 do Ubuntu (Lucid Lynx), 1
PPA Personal Package Archives (Pacote de Arquivos Pessoais), pacotes de terceiros, ou
seja, que no so oriundos do repositrio oficial do Ubuntu, 2
SDK Software Development Kit (Kit de Desenvolvimento de Software), 3
Synaptic um gerenciador de pacotes em modo grfico baseado em GTK+ e APT. Ele
permite que voc instale, atualize e remova pacotes de software de uma maneira amigvel. Para instalar, abra um terminal e digite como super usurio (root): apt-get
install synaptic, 2
xml eXtensible Markup Language, foi desenvolvida com o propsito de estruturar, armazenar e transportar informaes, 10

51

Potrebbero piacerti anche