SlideShare una empresa de Scribd logo
1 de 61
Descargar para leer sin conexión
por Átila Camurça



               2a Edição
       27 de outubro de 2012
ii
Sumário

1 Preparando o Ambiente de Desenvolvimento                                                                                       1
  1.1 Introdução . . . . . . . . . . . . . . . . . . . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   1
  1.2 Instalação . . . . . . . . . . . . . . . . . . . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   2
      1.2.1 Java JDK 6 . . . . . . . . . . . . . . .         .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   2
      1.2.2 Android SDK . . . . . . . . . . . . .            .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   3
      1.2.3 Android 2.2 API 8 . . . . . . . . . . .          .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   3
      1.2.4 Android Virtual Device (AVD) . . . .             .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   4
      1.2.5 Eclipse Juno . . . . . . . . . . . . . .         .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   4
      1.2.6 Plugin ADT . . . . . . . . . . . . . . .         .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   4
      1.2.7 Sqlite3 . . . . . . . . . . . . . . . . . .      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   6
      1.2.8 Sqliteman . . . . . . . . . . . . . . . .        .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   6
      1.2.9 Inkscape . . . . . . . . . . . . . . . . .       .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   7

2 Exemplo prático                                                                                                                 9
  2.1 Primeira aplicação - Contatos . . . . . . .    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .    9
      2.1.1 AndroidManifest.xml . . . . . . . .      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .    9
      2.1.2 Activity . . . . . . . . . . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   10
      2.1.3 Formulários . . . . . . . . . . . . .    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   12
      2.1.4 Construindo o Model da aplicação         .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   14
      2.1.5 Mostrando os dados na View . . .         .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   16
      2.1.6 Editando dados existentes . . . . .      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   20

3 Livro de Receitas                                                                                                              23
  3.1 Mostrando Diálogos . . . . . . . . . . . . .       . . . . . .             .   .   .   .   .   .   .   .   .   .   .   .   23
      3.1.1 Editar/Excluir ao clicar e segurar na        ListView                .   .   .   .   .   .   .   .   .   .   .   .   23
      3.1.2 Diálogo de confirmação . . . . . . .          . . . . . .             .   .   .   .   .   .   .   .   .   .   .   .   25
      3.1.3 Entrada de diferentes tipos de dados         . . . . . .             .   .   .   .   .   .   .   .   .   .   .   .   27
      3.1.4 Validação de dados . . . . . . . . . .       . . . . . .             .   .   .   .   .   .   .   .   .   .   .   .   28
      3.1.5 Fazendo uma ligação . . . . . . . . .        . . . . . .             .   .   .   .   .   .   .   .   .   .   .   .   29
      3.1.6 Enviando e-mail . . . . . . . . . . .        . . . . . .             .   .   .   .   .   .   .   .   .   .   .   .   32
  3.2 Internacionalização (i18n) . . . . . . . . . .     . . . . . .             .   .   .   .   .   .   .   .   .   .   .   .   32
      3.2.1 Forçando região para teste . . . . . .       . . . . . .             .   .   .   .   .   .   .   .   .   .   .   .   32
      3.2.2 Forçando região pelo emulador . . .          . . . . . .             .   .   .   .   .   .   .   .   .   .   .   .   33
  3.3 Utilizando as Preferências do Android . . .        . . . . . .             .   .   .   .   .   .   .   .   .   .   .   .   33
      3.3.1 Atualizando colunas de uma tabela .          . . . . . .             .   .   .   .   .   .   .   .   .   .   .   .   34
      3.3.2 Array de Strings . . . . . . . . . . .       . . . . . .             .   .   .   .   .   .   .   .   .   .   .   .   35
      3.3.3 Spinner, diálogo de seleção . . . . .        . . . . . .             .   .   .   .   .   .   .   .   .   .   .   .   36

                                            iii
iv                                                                                                     SUMÁRIO

           3.3.4   A classe PreferenceActivity . . . . . . . .   . . . .   .   .   .   .   .   .   .   .   .   .   .   37
     3.4   Grupo   de Contatos usando Grid . . . . . . . . .     . . . .   .   .   .   .   .   .   .   .   .   .   .   41
           3.4.1   Layout usando GridView . . . . . . . . .      . . . .   .   .   .   .   .   .   .   .   .   .   .   41
           3.4.2   Activity para visualizar os Grupos . . . .    . . . .   .   .   .   .   .   .   .   .   .   .   .   42
           3.4.3   Implementando o Adapter . . . . . . . . .     . . . .   .   .   .   .   .   .   .   .   .   .   .   45
           3.4.4   Selecionando contatos de um determinado       grupo     .   .   .   .   .   .   .   .   .   .   .   46

A Sobre o Autor                                                                                                        49

Glossário                                                                                                              51
Lista de Códigos-fonte

 1    Exemplo de banco de dados [exemplo-bd.sql] . . . . . . . . . . . .         .   .   .   .   .    7
 2    Exemplo de query com subquery [exemplo-bd.sql] . . . . . . . . . .         .   .   .   .   .    7
 3    Projeto inicial [AndroidManifest.xml] . . . . . . . . . . . . . . . . .    .   .   .   .   .    9
 4    Layout principal [res/layout/main.xml] . . . . . . . . . . . . . . . .     .   .   .   .   .   10
 5    Menu principal [res/menu/main menu.xml] . . . . . . . . . . . . .          .   .   .   .   .   10
                                      ¯
 6    Definir layout [MainActivity.java] . . . . . . . . . . . . . . . . . . .    .   .   .   .   .   11
 7    Criando o menu [MainActivity.java] . . . . . . . . . . . . . . . . . .     .   .   .   .   .   12
 8    Formulário principal [res/layout/salvar.xml] . . . . . . . . . . . . .     .   .   .   .   .   13
 9    Mudando de Activity [MainActivity.java] . . . . . . . . . . . . . . .      .   .   .   .   .   14
 10   Utilizando EditText’s [SalvarActivity.java] . . . . . . . . . . . . . .    .   .   .   .   .   14
 11   Mapear SalvarActivity [AndroidManifest.xml] . . . . . . . . . . . .        .   .   .   .   .   14
 12   Helper da aplicação [ContatoHelper.java] . . . . . . . . . . . . . . .     .   .   .   .   .   15
 13   Criar novo contato [ContatoHelper.java] . . . . . . . . . . . . . . .      .   .   .   .   .   15
 14   Fim da iteração criar contato [SalvarActivity.java] . . . . . . . . .      .   .   .   .   .   16
 15   Layout para cada linha da lista [res/layout/linha.xml] . . . . . . .       .   .   .   .   .   17
 16   Listar contatos existentes [ContatoHelper.java] . . . . . . . . . . .      .   .   .   .   .   18
 17   Classe Holder [MainActivity.java] . . . . . . . . . . . . . . . . . . .    .   .   .   .   .   18
 18   Classe Adapter [MainActivity.java] . . . . . . . . . . . . . . . . . .     .   .   .   .   .   19
 19   Popular ListView [MainActivity.java] . . . . . . . . . . . . . . . . .     .   .   .   .   .   20
 20   Passagem de parâmetros [MainActivity.java] . . . . . . . . . . . . .       .   .   .   .   .   21
 21   Ler e atualizar dados existentes [ContatoHelper.java] . . . . . . . .      .   .   .   .   .   21
 22   Usando Activity para criar ou atualizar [SalvarActivity.java] . . . .      .   .   .   .   .   22
 23   Deletar dados existentes [ContatoHelper.java] . . . . . . . . . . . .      .   .   .   .   .   23
 24   Adicionar Listener para click longo [MainActivity.java] . . . . . . .      .   .   .   .   .   24
 25   Diálogo de confirmação ao deletar contato [MainActivity.java] . . .         .   .   .   .   .   26
 26   Distinção de dados [res/layout/salvar.xml] . . . . . . . . . . . . . .     .   .   .   .   .   28
 27   Validação dos dados [SalvarActivity.java] . . . . . . . . . . . . . . .    .   .   .   .   .   29
 28   Permissão de realizar chamadas [AndroidManifest.xml] . . . . . . .         .   .   .   .   .   30
 29   Item chamar no diálogo [MainActivity.java] . . . . . . . . . . . . .       .   .   .   .   .   31
 30   Item enviar e-mail no diálogo [MainActivity.java] . . . . . . . . . .      .   .   .   .   .   32
 31   Forçando região [SalvarActivity.java] . . . . . . . . . . . . . . . . .    .   .   .   .   .   33
 32   Nova coluna grupo na base de dados [ContatoHelper.java] . . . . .          .   .   .   .   .   34
 33   Modificação nas queries [ContatoHelper.java] . . . . . . . . . . . .        .   .   .   .   .   35
 34   Array de Strings [strings.xml] . . . . . . . . . . . . . . . . . . . . .   .   .   .   .   .   36
 35   Adicionando elemento Spinner [res/layout/salvar.xml] . . . . . . .         .   .   .   .   .   36
 36   Utilização de Spinner [SalvarActivity.java] . . . . . . . . . . . . . .    .   .   .   .   .   37
 37   XML descrevendo layout de preferências [res/xml/preferencias.xml]          .   .   .   .   .   38

                                           v
vi                                                          LISTA DE CÓDIGOS-FONTE

     38   Activity para mostrar preferências [EditarPreferencias.java] . . . . . . . .    .   38
     39   Mapeando Activity EditarPreferencias [AndroidManifest.xml] . . . . . . .        .   38
     40   Adicionar item Preferências ao menu principal [res/menu/main menu.xml]          .   39
                                                                          ¯
     41   Ir para Preferências pelo menu principal [MainActivity.java] . . . . . . . .    .   39
     42   Mudança em método irParaSalvar [MainActivity.java] . . . . . . . . . . .        .   40
     43   Obtem o valor padrão definido nas Preferências [SalvarActivity.java] . . .       .   40
     44   Item do Layout de Grupos [res/layout/grupos item.xml] . . . . . . . . . .       .   41
                                                       ¯
     45   Layout de Grupos [res/layout/grupos.xml] . . . . . . . . . . . . . . . . . .    .   42
     46   Activity para visualizar Grupos [GruposActivity.java] . . . . . . . . . . . .   .   42
     47   Adapter responsável por cada item do Grid [GruposActivity.java] . . . . .       .   43
     48   implementação do Adapter [GruposActivity.java] . . . . . . . . . . . . . .      .   45
     49   Método listar com parâmetro grupo [ContatoHelper.java] . . . . . . . . .        .   46
     50   Evento de clique em um item do grid [GruposActivity.java] . . . . . . . .       .   47
     51   Captura de parâmetro vindo de GruposActivity [MainActivity.java] . . .          .   47
Lista de Tabelas

 1.1   Tipos de dados do Sqlite . . . . . . . . . . . . . . . . . . . . . . . . . . . . .   6

 2.1   Convenção para nome dos ícones . . . . . . . . . . . . . . . . . . . . . . . . 11

 3.1   Paleta de cores do Android . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
 3.2   Localização 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
x   LISTA DE FIGURAS
Capítulo 1

Preparando o Ambiente de
Desenvolvimento

1.1     Introdução
O desenvolvimento de aplicativos para a plataforma Android é feito na linguagem Java.
Para esta apostila serão utilizados os seguintes aplicativos e bibliotecas:

      Ubuntu 10.04 ou 12.04

      Java JDK 6 ou 7

      Android SDK

      Android 2.2 API 8

      Eclipse Juno

      ADT Plugin

      Sqlite3

      Sqliteman

      Inkscape

   Você pode estar se perguntando: ”Por que utilizar essa configuração?”. Bom, para
começar um ambiente de desenvolvimento precisa ser estável, 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, então podemos utilizar
a versão mais recente. O mesmo para o plugin ADT.
   Usaremos especificamente para os exemplos a seguir a versão 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 versões e compilar seus aplicativos
para tablets, etc.

                                            1
2          CAPÍTULO 1. PREPARANDO O AMBIENTE DE DESENVOLVIMENTO

1.2     Instalação
A instalação do Java JDK 6 no Ubuntu 10.04 não é a mesma que no Ubuntu 12.04. Isso
porque na época de lançamento do lucid, em 2010, a empresa que desenvolvia o Java
era a Sun Microsystems, que tinha um canal nos repositórios 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.
    Discussões a parte, vamos ver as duas maneiras de instalar o Java.

1.2.1    Java JDK 6
A instalação do Java no Ubuntu 10.04 é bastante simples. Você apenas irá precisar habili-
tar repositório de terceiros, ou Partner. Isso pode ser feito através do aplicativo Synaptic.
No menu principal do Ubuntu clique em Sistema → Administração → Gerenciador
de pacotes Synaptic.
    No menu do Synaptic clique em Configuração → Repositórios. Na aba Outro
Software temos vários itens que representam repositórios. Marque os dois repositórios que
terminam com partner. Feche e depois clique em Editar → Recarregar informações
dos pacotes ou simplesmente Ctrl + R.
    Após a atualização dos pacotes existentes nos repositórios já é possível encontrar o
Java JDK 6. No campo de Pesquisa rápida digite: sun-java6. Clique com botão
direito no pacote sun-java6-jdk e selecione a opção Marcar para instalação. Depois
basta Aplicar as mudanças. Para isso clique em Editar → Aplicar as alterações
marcadas ou Ctrl + P.

    Para a instalação no Ubuntu 12.04 temos que habilitar um repositório de terceiros,
também conhecido como PPA (Personal Package Archives). Abra um terminal e execute
os passos a seguir para adicionar um repositório 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 não está familiarizado com o ambiente Linux vamos a uma pequena explica-
ção. Nos comandos acima aparecem dois caracteres que não devem ser escritos mas que
representam algo importante no âmbito dos comandos, são eles $ e #. Estes caracteres
indicam qual o nível do usuário; $ significa usuário comum, # representa super usuário
(root). No comando sudo su é onde trocamos de usuário comum para super usuário.
Neste momento você terá que entrar com sua senha de login.

Java JDK 7
Segundo a página de Requerimentos do Sistema (http://developer.android.com/sdk/
requirements.html) do site oficial do Android, é necessário uso do Java 6. Caso você
queira utilizar o Java 7, você terá que configurar seu projeto Android para ser compilado
com suporte a versão 6.
1.2. INSTALAÇÃO                                                                         3

    A instalação 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

   Após criar o projeto clique com botão 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 nível de compilação 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 instalação é feita apenas colocando o SDK em um diretório do sistema. Existem 2
bons locais para abrigar bibliotecas no Linux, são 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 diretório 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ê atenção ao uso do comando ln. Ele é responsável por criar links simbólicos. Isso é
muito útil quando se instala um aplicativo ou biblioteca, pois proporciona atualização sem
que outros ajustes sejam feitos. Neste caso basta linkar outra vez e pronto.
   Note que no último comando temos um link simbólico para o diretório /usr/local/bin.
É nele que colocamos os executáveis globais, ou seja, que são vistos a partir de qualquer
outro diretório. Agora saindo do modo root e usando seu próprio usuário instalaremos a
API.

1.2.3    Android 2.2 API 8
Ainda no terminal, agora como usuário comum, vamos abrir o aplicativo que instala qual-
quer uma das API disponibilizadas pelo Android.

$ android
4          CAPÍTULO 1. PREPARANDO O AMBIENTE DE DESENVOLVIMENTO

   O aplicativo Android SDK and AVD Manager irá aparecer. Clique em Avaliable
packages e procure pela versão 2.2 API 8 do Android. Selecione e clique em Install
Selected. Após o download você pode verificar a versão 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 versões 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 versão. Assim, caso você tenha que testar seu código em outras versões
você poderá saber qual emulador utilizar. Por exemplo use android-2.2. Em Target
escolha a versão, neste caso Android 2.2 - API Level 8. Pronto, apenas clique em
Create AVD.

Dicas
A opção Skin indica qual a resolução da tela do aparelho. Como não é possível redimen-
sionar a janela, em alguns monitores a janela fica maior que a tela do seu monitor.
    A opção Snapshot quando habilitada, serve para salvar o estado do emulador. Isso faz
com que da segunda inicialização em diante se torne mais rápida.
    A opção SD Card é ideal caso sua aplicação necessite guardar dados como fotos, arqui-
vos. O AVD irá reservar um espaço 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 de-
senvolvimento de aplicativos para o Android a versão Eclipse IDE for Java Developers
é ideal. Mas se você tiver interesse em aplicativos Java para Web a opção é baixar a versão
Eclipse IDE for Java EE Developers.
    Em todo caso as duas vão servir para o desenvolvimento, pois ambas vem com suporte
a Java.
    O Eclipse não 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 botão direiro do mouse no menu principal e escolhendo a
opção 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 visível a todos os usuários.

1.2.6   Plugin ADT
Para a instalação 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 confirmação sobre os itens
1.2. INSTALAÇÃO                                                                        5

a serem instalados, clique em Next. Agora basta aceitar os termos de uso e clicar em
Finish. Após o download e a instalação, 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ê não conheça mas que sempre precisou.

Configurando o ADT
Agora que o plugin foi instalado temos que dizer ao Eclipse onde nós 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 diretório
do SDK, caso não lembre, ele está em /usr/local/lib/android-sdk. Clique em Apply
na parte inferior direita para atualizar a lista de API’s disponíveis.
   Caso você tenha mais dúvidas dê uma olhada na página oficial de instalação 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 diretório 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 versão mínima é a API 8. Clique em Next.
    Na versão do ADT para o Eclipse Juno, uma novidade apareceu. É possível criar o
ícone lançador logo ao criar o aplicativo. Selecione da maneira que achar melhor e clique
em Next. Depois clique em Finish.
    Após isso clique com botão direito do mouse no projeto recém criado, e Run As →
Android Application. Se tudo tiver dado certo é possível ver no emulador sua primeira
aplicação rodando.

Dicas
Uma vez que você abriu o emulador não o feche. Você irá notar que ao abrir pela primeira
vez ele leva um tempo para isso. Neste caso ao atualizar o código-fonte apenas rode
o aplicativo novamente. O plugin ADT fará com que o aplicativo seja reinstalado no
emulador.
   Faça o teste com alguns atalhos básicos:
Alt + Enter Maximiza o emulador. Ideal para demostrações.
Ctrl + F11 Muda a orientação do emulador, retrato ou paisagem.
F8 Liga/desliga a rede.
    Outro elemento essencial é o LogCat. Ele faz parte do ADT e é responsável por mostrar
as mensagens de log do emulador. Caso você encontre problemas com seu código o LogCat
será seu melhor aliado. Para acessá-lo no Eclipse clique no menu Window → Show View
→ Other..., clique em Android → LogCat.
6             CAPÍTULO 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 fácil configuração e, acima de tudo, livre. Para a
instalação, abra um terminal como root e:

$ sudo su
# apt-get install sqlite3

   Após a instalação é possível utilizar o Sqlite via linha de comando. Faça logoff do
usuário root e faça 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 página oficial do projeto: http://www.sqlite.org/.

Tipos de dados
Utilize a tabela abaixo para criar suas tabelas futuramente.

    Nome      Descrição
    INTEGER   valores inteiros, positivos ou negativos. Podem variar de 1 a 8 bytes.
    REAL      valores reais ou decimais.
    TEXT      usado para armazenar valores, não-limitado. Suporta várias codifica-
              ções, por exemplo UTF-8.
    BLOB      objetos binários tais como imagens, arquivos de texto, etc. Também
              possui tamanho não-limitado.
    NULL      representa falta de informação.

                            Tabela 1.1: Tipos de dados do Sqlite


1.2.8      Sqliteman
Para uma gerência mais produtiva usaremos o Sqliteman para acessar e modificar bancos
de dados. A instalação é feita via linha de comando. Abra um terminal e:

$ sudo su
# apt-get install sqliteman
1.2. INSTALAÇÃO                                                                       7

        Depois de instalado, acesse o aplicativo do menu principal do Ubuntu em Aplicativos
     → Escritório → Sqliteman. Faça alguns testes criando bancos de dados, depois crie
     algumas tabelas. Ele possui assistentes que irão auxiliar nos primeiros momentos.
        Por exemplo, crie uma base de dados e depois clique com o botão direito do mouse em
     Tables. Utilize o assistente e veja como é simples criar tabelas no sqlite.

 1   -- Distribuições Linux
 2

 3   CREATE TABLE distros (
 4      _id INTEGER PRIMARY KEY,
 5      nome TEXT NOT NULL,
 6      interface TEXT NOT NULL DEFAULT ’Gnome3’ ,
 7      deriva_de INTEGER REFERENCES distros(_id)
 8   );
 9

10   INSERT   INTO   distros   VALUES   (1,   ’Debian’ , ’Gnome3’ , NULL);
11   INSERT   INTO   distros   VALUES   (2,   ’Ubuntu’ , ’Unity’ , 1);
12   INSERT   INTO   distros   VALUES   (3,   ’Linux Mint’ , ’Mate’ , 2);
13   INSERT   INTO   distros   VALUES   (4,   ’Fedora’ , ’KDE’ , NULL);
14   INSERT   INTO   distros   VALUES   (5,   ’Slackware’ , ’KDE’ , NULL);
15   INSERT   INTO   distros   VALUES   (6,   ’Slax’ , ’KDE’ , 5);
16   INSERT   INTO   distros   VALUES   (7,   ’Ubuntu Studio’ , ’XFCE’ , 2);
17   INSERT   INTO   distros   VALUES   (8,   ’kUbuntu’ , ’KDE’ , 2);
18   INSERT   INTO   distros   VALUES   (9,   ’xUbuntu’ , ’XFCE’ , 2);


                     Código-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 número de distros que derivam de uma outra original.
     Veja:

 1   SELECT d._id, d.nome, d.interface,
 2   (
 3      SELECT SUM( CASE WHEN aux.deriva_de = d._id THEN 1 ELSE 0 END )
 4      FROM distros aux
 5   ) AS num_derivadas
 6   FROM distros d


                Código-fonte 2: Exemplo de query com subquery [exemplo-bd.sql]

        Mais informações 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
     navegação, identidade visual, entre outras coisas.
8          CAPÍTULO 1. PREPARANDO O AMBIENTE DE DESENVOLVIMENTO

    A instalação é 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 página
http://developer.android.com/design/style/iconography.html.
Capítulo 2

     Exemplo prático

     2.1     Primeira aplicação - 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 aplicação, mapeia as Activity’s, entre outras configura-
     ções. Ao finalizar a criação do projeto, inicialmente este arquivo deverá conter o seguinte
     conteúdo:

 1   <?xml version="1.0" encoding="UTF-8"?>
 2   <manifest xmlns:android= "http://schemas.android.com/apk/res/android"
 3        package= "contatos.app"
 4        android:versionCode= "1"
 5        android:versionName= "1.0" >
 6       <uses-sdk android:minSdkVersion= "8" android:targetSdkVersion= "8" />
 7       <application android:icon= "@drawable/icon" android:label= "@string/app_name" >
 8            <activity android:name= ".MainActivity" android:label= "@string/app_name" >
 9               <intent-filter>
10                   <action android:name= "android.intent.action.MAIN" />
11                   <category android:name= "android.intent.category.LAUNCHER" />
12               </intent-filter>
13           </activity>
14       </application>
15   </manifest>


                      Código-fonte 3: Projeto inicial [AndroidManifest.xml]

                                                 9
10                                                CAPÍTULO 2. EXEMPLO PRÁTICO

     2.1.2    Activity

     Não existe método main visível ao programador no Android. Ao invés disso temos
     Activity’s. Para que o Android saiba qual ele deve iniciar primeiro utilizamos um
     intent-filter como visto no trecho de código acima da linha 09 a 12 . Para nossa
     primeira Activity criaremos uma lista de contatos e um menu para criação de um novo
     contato.
         Para construir o layout inicial de nossa aplicação precisamos editar o arquivo main.xml
     localizado em res/layout.

 1   <?xml version="1.0" encoding="utf-8"?>
 2   <LinearLayout xmlns:android= "http://schemas.android.com/apk/res/android"
 3       android:orientation= "vertical"
 4       android:layout_width= "fill_parent"
 5       android:layout_height= "fill_parent" >
 6       <ListView
 7         android:id= "@+id/lv_contatos"
 8         android:layout_width= "fill_parent"
 9         android:layout_height= "wrap_content" />
10   </LinearLayout>


                      Código-fonte 4: Layout principal [res/layout/main.xml]


         Deste momento em diante tenha em mente que os arquivos xml aqui descritos são
     apenas para você poder comparar e ver se não esqueceu de nada. Todos os layout’s 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 gráfico basta utilizar a aba inferior
     esquerda.
        Por fim, temos o menu. Clique com o botão direito do mouse em seu projeto e New →
     Other... ou Ctrl + N. Procure por Android XML File. Em Resource Type escolha a
     opção Menu. Chame-o de main menu.xml.
                                 ¯
 1   <?xml version="1.0" encoding="UTF-8"?>
 2   <menu xmlns:android= "http://schemas.android.com/apk/res/android" >
 3       <item
 4           android:id= "@+id/menu_add"
 5           android:title= "Novo"
 6           android:icon= "@android:drawable/ic_menu_add" />
 7   </menu>


                    Código-fonte 5: Menu principal [res/menu/main menu.xml]
                                                                 ¯

          Pronto, já temos nosso layout. Compile o projeto e vamos a próxima iteração.
2.1. PRIMEIRA APLICAÇÃO - CONTATOS                                                   11

    Convenção 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 diretório de instalação 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 convenção:


     Tipo de Recurso       Prefixo                            Exemplo
     Ícones                ic                                ic adicionar.png
                             ¯                                 ¯
     Launcher icons        ic launcher                       ic launcher calendario.png
                             ¯         ¯                       ¯        ¯
     Menu e Action Bar     ic menu                           ic menu ajuda.png
                             ¯     ¯                           ¯    ¯
     Status bar icons      ic stat notify                    ic stat notify msg.png
                             ¯     ¯      ¯                    ¯    ¯      ¯
     Tab icons             ic tab                            ic tab recente.png
                             ¯    ¯                            ¯   ¯
     Dialog icons          ic dialog                         ic dialog info.png
                             ¯       ¯                         ¯      ¯

                          Tabela 2.1: Convenção para nome dos ícones


       Note que você não é obrigado a utilizar os prefixos citados acima, isto é apenas uma
    convenção. Veja mais detalhes em http://developer.android.com/guide/practices/
    ui_guidelines/icon_design.html.
       Abra o arquivo MainActivity.java e vá ao método onCreate. Defina o layout como
    sendo nosso main.xml. Para isso adicione o layout main ao final do método:

1   @Override
2   public void onCreate(Bundle icicle) {
3      super.onCreate(icicle);
4      setContentView(R.layout.main);
5   }


                        Código-fonte 6: Definir layout [MainActivity.java]




    Cuidado: no ambiente Android temos uma classe chamada R. Ela existe tanto na biblio-
    teca do Android como em cada projeto. Nesse caso faça o import da classe contatos.app.R.
    A classe android.R é utilizada em outras situações, onde códigos pré-prontos foram dis-
    ponibilizados pela equipe do Android.
       Agora precisamos sobrescrever os métodos onCreateOptionsMenu e onOptionsItemSelected.
    Eles irão criar o menu a partir de nosso layout e notificar quando os itens do menu forem
    pressionados, respectivamente. Vamos ao código:
12                                              CAPÍTULO 2. EXEMPLO PRÁTICO

 1   @Override
 2   public boolean onCreateOptionsMenu(Menu menu) {
 3      new MenuInflater(this).inflate(R.menu.main_menu, menu);
 4      return super.onCreateOptionsMenu(menu);
 5   }
 6

 7   @Override
 8   public boolean onOptionsItemSelected(MenuItem item) {
 9      if (item.getItemId() == R.id.menu_add) {
10         irParaSalvar();
11         return true;
12      }
13      return super.onOptionsItemSelected(item);
14   }
15

16   private void irParaSalvar() {
17      // não implementado ainda ...
18   }


                       Código-fonte 7: Criando o menu [MainActivity.java]




     2.1.3   Formulários




     Agora vamos criar nosso formulário para criação e edição de contatos. Começaremos pelo
     layout. Crie um arquivo xml em res/layout chamado salvar.xml.


         Existem alguns pontos importantes para este trecho de código. Começando 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 possível, respeitando o tamanho mínimo das outras células. Para visualizar as
     mudanças você pode tentar usar outros valores como 0 tornando a primeira coluna maior
     que as demais, ou ainda * que fará com que todas as células tenham o mesmo tamanho.
2.1. PRIMEIRA APLICAÇÃO - CONTATOS                                                 13

 1   <?xml version="1.0" encoding="UTF-8"?>
 2   <RelativeLayout
 3   android:id= "@+id/widget31"
 4   android:layout_width= "fill_parent"
 5   android:layout_height= "fill_parent"
 6   xmlns:android= "http://schemas.android.com/apk/res/android" >
 7      <TableLayout
 8         android:id= "@+id/widget32"
 9         android:layout_width= "fill_parent"
10         android:layout_height= "wrap_content"
11         android:orientation= "vertical"
12         android:stretchColumns= "1" >
13         <TableRow
14            android:id= "@+id/widget33"
15            android:layout_width= "fill_parent"
16            android:layout_height= "wrap_content"
17            android:orientation= "horizontal" >
18            <TextView
19               android:id= "@+id/textView1"
20               android:layout_width= "wrap_content"
21               android:layout_height= "wrap_content"
22               android:text= "Nome" ></TextView>
23            <EditText
24               android:id= "@+id/et_nome"
25               android:layout_width= "wrap_content"
26               android:layout_height= "wrap_content" ></EditText>
27         </TableRow>
28         <!-- faça mais duas TableRow’s contendo o Telefone e E-mail -->
29         <Button
30            android:id= "@+id/bt_salvar"
31            android:text= "Salvar"
32            android:layout_height= "wrap_content"
33            android:layout_width= "fill_parent" ></Button>
34      </TableLayout>
35   </RelativeLayout>


                  Código-fonte 8: Formulário 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 constru-
     tores recebe como parâmetros a instância 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 método irParaSalvar da classe MainActivity:
14                                               CAPÍTULO 2. EXEMPLO PRÁTICO

 1   private void irParaSalvar() {
 2      Intent intent = new Intent(MainActivity.this, SaveActivity.class);
 3      startActivity(intent);
 4   }


                     Código-fonte 9: Mudando de Activity [MainActivity.java]

        Veremos agora como manipular EditText’s, que representam os campos de entrada
     de dados. Abra o SalvarActivity e adicione o método carregar e crie atributos para
     guardar os EditText’s:

 1   private EditText etNome, etFone, etEmail;
 2   /* ... */
 3

 4   @Override
 5   public void onCreate(Bundle icicle) {
 6      super.onCreate(icicle);
 7      setContentView(R.layout.salvar);
 8      carregar();
 9   }
10

11   private void carregar() {
12      etNome = (EditText) findViewById(R.id.et_nome);
13      etTefone = (EditText) findViewById(R.id.et_telefone);
14      etEmail = (EditText) findViewById(R.id.et_email);
15   }


                    Código-fonte 10: Utilizando EditText’s [SalvarActivity.java]

        Para que a Activity funcione precisamos mapeá-la no arquivo AndroidManifest.xml.
     Adicione o conteúdo abaixo entre as tags application:

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


                  Código-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 aplicação
     Precisamos de um helper para fazer acesso ao banco de dados. O Android provê suporte a
     bancos de dados Sqlite por padrão. Qualquer banco de dados que você criar será acessível
     pelo nome por qualquer classe na sua aplicação, mas não 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 graças aos
     métodos getReadableDatabase() e getWritableDatabase(), respectivamente.
2.1. PRIMEIRA APLICAÇÃO - CONTATOS                                                15

        A princípio temos que criar um construtor passando como parâmetros o nome do banco
     de dados e a versão da DDL (Data Definition Language). Logo em seguida precisamos
     implementar os métodos onCreate, no qual iremos criar as tabelas e onUpdate, caso
     tenhamos que alterar alguma tabela.
 1   package contatos.app.model;
 2

 3   import android.content.Context;
 4   import android.database.sqlite.SQLiteDatabase;
 5   import android.database.sqlite.SQLiteOpenHelper;
 6

 7   public class ContatoHelper extends SQLiteOpenHelper {
 8

 9       private static final String DATABASE_NAME = "contatos.db" ;
10       private static final int VERSION = 1;
11

12       public ContatoHelper(Context context) {
13          super(context, DATABASE_NAME, null, VERSION);
14       }
15

16       @Override
17       public void onCreate(SQLiteDatabase db) {
18          db.execSQL( "CREATE TABLE contato (_id INTEGER PRIMARY KEY AUTOINCREMENT,"
19                   + " nome TEXT, fone TEXT, email TEXT);" );
20       }
21

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


                   Código-fonte 12: Helper da aplicação [ContatoHelper.java]

         Para a iteração de criação de um novo contato, ainda em ContatoHelper vamos adi-
     cionar um método criar. Faça:

 1   public void criar(ContentValues values) {
 2      getWritableDatabase().insert( "contato" , "telefone" , values);
 3   }


                    Código-fonte 13: Criar novo contato [ContatoHelper.java]

        Agora temos que fazer a chamada do método criar da classe ContatoHelper em
     SalvarActivity. Para isso temos que criar uma instância de ContatoHelper, adicionar
     o botão salvar e adicionar um Listener de click (faça o import da classe
     android.view.View.OnClickListener). Vamos ao código:
16                                                  CAPÍTULO 2. EXEMPLO PRÁTICO

 1   /* ... */
 2   private ContatoHelper helper;
 3   private Button btSalvar;
 4

 5   @Override
 6   public void onCreate(Bundle icicle) {
 7      /* ... */
 8      helper = new ContatoHelper(this);
 9      carregar();
10      ir();
11      /* ... */
12   }
13

14   private void carregar() {
15      /* ... */
16      btSalvar = (Button) findViewById(R.id.bt_salvar);
17   }
18

19   private void ir() {
20      btSalvar.setOnClickListener(new OnClickListener() {
21

22              public void onClick(View view) {
23                 ContentValues values = new ContentValues();
24                 values.put( "nome" , etNome.getText().toString());
25                 values.put( "telefone" , etTefone.getText().toString());
26                 values.put( "email" , etEmail.getText().toString());
27                 helper.criar(values);
28                 finish();
29              }
30        });
31   }
32

33   @Override
34   protected void onDestroy() {
35      super.onDestroy();
36      helper.close();
37   }


                   Código-fonte 14: Fim da iteração criar contato [SalvarActivity.java]

          Com essa implementação já é possível salvar contatos na base de dados.


     2.1.5       Mostrando os dados na View
     Após salvar os dados no banco, devemos ser capazes de obter tais informações e colocá-
     las em forma de Lista. Para isso criaremos um novo layout que será responsável por
     representar uma linha de nossa Lista. Essa linha deve ser semelhante a figura abaixo:
2.1. PRIMEIRA APLICAÇÃO - CONTATOS                                                   17




                                Figura 2.1: Layout linha da Lista


        Para isso crie um arquivo chamado linha.xml em res/layout com o seguinte con-
     teúdo.
 1   <?xml version="1.0" encoding="UTF-8"?>
 2   <LinearLayout xmlns:android= "http://schemas.android.com/apk/res/android"
 3      android:layout_width= "fill_parent" android:layout_height= "wrap_content"
 4      android:orientation= "horizontal" >
 5      <ImageView
 6         android:id= "@+id/linha_icone" android:layout_width= "wrap_content"
 7         android:layout_height= "fill_parent" android:src= "@drawable/ic_launcher" >
 8      </ImageView>
 9      <LinearLayout
10         android:layout_width= "fill_parent" android:layout_height= "wrap_content"
11         android:orientation= "vertical" >
12         <TextView
13            android:id= "@+id/linha_nome" android:layout_width= "fill_parent"
14            android:layout_height= "wrap_content" android:textStyle= "bold"
15            android:ellipsize= "end" ></TextView>
16         <TextView
17            android:id= "@+id/linha_fone" android:layout_width= "fill_parent"
18            android:layout_height= "wrap_content" ></TextView>
19         <TextView
20            android:id= "@+id/linha_email" android:layout_width= "fill_parent"
21            android:layout_height= "wrap_content" ></TextView>
22         </LinearLayout>
23   </LinearLayout>


             Código-fonte 15: Layout para cada linha da lista [res/layout/linha.xml]

         Note a possibilidade de aninhar o LinearLayout. Fazendo isso é possível 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 li-
     nha 14 , e o uso de reticências caso o nome seja maior que a tela usando android:ellipsize="end"
     na linha 15 .
18                                              CAPÍTULO 2. EXEMPLO PRÁTICO

        Agora vamos até ContatoHelper e adicionar o método listar. E também adiciona-
     remos métodos para facilitar a obtenção dos valores de cada atributo.

 1   public Cursor listar() {
 2      return getReadableDatabase()
 3         .rawQuery( "SELECT _id, nome, fone, email FROM contato ORDER BY nome" ,
 4           null);
 5   }
 6

 7   public String getNome(Cursor c) {
 8      return c.getString(1);
 9   }
10

11   public String getFone(Cursor c) {
12      return c.getString(2);
13   }
14

15   public String getEmail(Cursor c) {
16      return c.getString(3);
17   }


                 Código-fonte 16: Listar contatos existentes [ContatoHelper.java]

         Os elementos de um Cursor são numerados iniciando de 0 (zero). Neste caso o 0 é a
     coluna id. Note que ela não 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   private static class ContatoHolder {
 2      private TextView nome, fone, email = null;
 3

 4        public ContatoHolder(View linha) {
 5           nome = (TextView) linha.findViewById(R.id.linha_nome);
 6           fone = (TextView) linha.findViewById(R.id.linha_fone);
 7           email = (TextView) linha.findViewById(R.id.linha_email);
 8        }
 9

10        public void popularForm(Cursor c, ContatoHelper helper) {
11           nome.setText(helper.getNome(c));
12           fone.setText(helper.getFone(c));
13           email.setText(helper.getEmail(c));
14        }
15   }


                       Código-fonte 17: Classe Holder [MainActivity.java]
2.1. PRIMEIRA APLICAÇÃO - 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á responsável por definir o
     layout de cada linha da Lista. Crie uma classe interna chamada ContatoAdapter. Iremos
     sobrescrever dois métodos, newView() e bindView(), que são responsáveis por inflar
     (inflate) uma nova linha e reciclar uma linha existente, respectivamente.




 1   private ContatoHelper helper;
 2   /* ... */
 3

 4   private class ContatoAdapter extends CursorAdapter {
 5

 6       public ContatoAdapter(Cursor c) {
 7          super(MainActivity.this, c);
 8       }
 9

10       @Override
11       public View newView(Context cntxt, Cursor cursor, ViewGroup vg) {
12          LayoutInflater inflater = getLayoutInflater();
13          View linha = inflater.inflate(R.layout.linha, vg, false);
14          ContatoHolder holder = new ContatoHolder(linha);
15          linha.setTag(holder);
16          return linha;
17       }
18

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


                      Código-fonte 18: Classe Adapter [MainActivity.java]




        Com a introdução do Helper teremos que criar uma instância da classe Cursor para
     popular nossa ListView. Vamos ao código-fonte:
20                                             CAPÍTULO 2. EXEMPLO PRÁTICO

 1   /* ... */
 2   private Cursor model = null;
 3   private ContatoAdapter adapter = null;
 4   private ListView listView = null;
 5

 6   @Override
 7   public void onCreate(Bundle icicle) {
 8      /* ... */
 9      helper = new ContatoHelper(this);
10      carregar();
11   }
12

13   private void carregar() {
14      listView = (ListView) findViewById(R.id.lv_contatos);
15      model = helper.listar();
16      startManagingCursor(model);
17      adapter = new ContatoAdapter(model);
18      listView.setAdapter(adapter);
19   }
20

21   @Override
22   protected void onDestroy() {
23      super.onDestroy();
24      model.close();
25      helper.close();
26   }


                     Código-fonte 19: Popular ListView [MainActivity.java]


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




     2.1.6   Editando dados existentes

     Para a edição de informações usaremos o mesmo Activity do criar, ou seja, SalvarActivity.
     Para isso precisamos passar um parâmetro para o Activity. Usaremos então um método
     do Intent que é responsável por isso, putExtra(chave, valor).
         Para uma passagem de parâmetros segura devemos usar um namespace para que não
     colida com nenhum nome já utilizado pelo Android. Assim, vamos criar uma variável
     estática do tipo String. Isso acontecerá quando o usuário pressionar a linha que ele
     deseja editar. Podemos fazer isso utilizando a interface OnItemClickListener.
        Vamos incrementar também o método irParaSalvar passando o parâmetro caso haja
     um. Vamos ao código:
2.1. PRIMEIRA APLICAÇÃO - CONTATOS                                                 21

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

 4   @Override
 5   public void onCreate(Bundle icicle) {
 6      /* ... */
 7      configurar();
 8   }
 9

10   private void irParaSalvar() {
11      irParaSalvar(null);
12   }
13

14   private void irParaSalvar(String id) {
15      Intent intent = new Intent(MainActivity.this, SalvarActivity.class);
16      if (id != null) {
17         intent.putExtra(_ID, id);
18      }
19      startActivity(intent);
20   }
21

22   private void configurar() {
23      listView.setOnItemClickListener(new OnItemClickListener() {
24          public void onItemClick(AdapterView<?> parent, View view,
25                int position, long id) {
26             irParaSalvar(String.valueOf(id));
27          }
28      });
29   }


                  Código-fonte 20: Passagem de parâmetros [MainActivity.java]


        Agora é hora de tratar nosso parâmetro no SalvarActivity. Caso haja um parâmetro
     precisamos obter os dados existentes no banco de dados para então editá-lo. Neste caso
     precisaremos de mais dois métodos em ContatoHelper, que são ler e atualizar.

 1   public Cursor ler(String id) {
 2      return getReadableDatabase().rawQuery( "SELECT _id, nome, telefone, " +
 3          "email FROM contato WHERE _id = ?" , new String[]{id});
 4   }
 5

 6   public void atualizar(String id, ContentValues values) {
 7      getWritableDatabase().update( "contato" , values, "_id = ?" , new String[]{id});
 8   }


              Código-fonte 21: Ler e atualizar dados existentes [ContatoHelper.java]
22                                              CAPÍTULO 2. EXEMPLO PRÁTICO

        O próximo passo é tratar no SalvarActivity caso o parâmetro tenha sido enviado
     ou não. Caso positivo devemos carregar os dados existentes no banco de dados e depois
     atualizá-los.
 1   /* ... */
 2   private String contatoId = null;
 3

 4   private void carregar() {
 5      /* ... */
 6      contatoId = getIntent().getStringExtra(MainActivity._ID);
 7      if (contatoId != null) {
 8         carregarContato();
 9      }
10   }
11

12   private void carregarContato() {
13      Cursor cursor = helper.ler(contatoId);
14      cursor.moveToFirst();
15      etNome.setText(helper.getNome(cursor));
16      etFone.setText(helper.getFone(cursor));
17      etEmail.setText(helper.getEmail(cursor));
18      cursor.close();
19   }
20

21   private void ir() {
22      btSalvar.setOnClickListener(new OnClickListener() {
23          public void onClick(View view) {
24             ContentValues values = new ContentValues();
25             values.put( "nome" , etNome.getText().toString());
26             values.put( "telefone" , etTefone.getText().toString());
27             values.put( "email" , etEmail.getText().toString());
28             if (contatoId == null) {
29                helper.criar(values);
30             } else {
31                helper.atualizar(contatoId, values);
32             }
33             finish();
34          }
35      });
36   }


          Código-fonte 22: Usando Activity para criar ou atualizar [SalvarActivity.java]

        Com isso encerramos um CRUD básico, mas completo. A seguir temos implementa-
     ções mais específicas que irão tornar nossa aplicação mais profissional.
Capítulo 3

    Livro de Receitas

    3.1     Mostrando Diálogos

    No Android, podemos criar diálogos no Activity mostrando opções ao usuário, como por
    exemplo, escolher itens de uma lista, ou responder sim ou não a uma ação, etc.
        Vamos incrementar algumas partes de nosso código e tentar encaixar algumas funcio-
    nalidades relacionadas.




    3.1.1   Editar/Excluir ao clicar e segurar na ListView

    Vamos implementar uma ação comum no mundo Android, que é a seguinte: ao clicar e
    segurar num item da ListView, ele mostra opções editar e excluir, por exemplo. Isto pode
    ser feito facilmente usando AlertDialog.Builder, uma classe com métodos pré-prontos
    para serem usados por você.
        Neste exemplo, precisaremos editar ContatoHelper e adicionar um método para de-
    letar um contato, editar nosso MainActivity no método configurar e adicionar um
    Listener que ao clicar e segurar num item da ListView um método é acionado. Vamos a
    implementação:


1   public int deletar(String id) {
2      String whereClause = "_id = ?" ;
3      String[] whereArgs = {id};
4      return getWritableDatabase().delete( "contato" , whereClause, whereArgs);
5   }


                Código-fonte 23: Deletar dados existentes [ContatoHelper.java]

                                              23
24                                            CAPÍTULO 3. LIVRO DE RECEITAS

 1   /* ... */
 2   private void configurar() {
 3      /* ... */
 4      listView.setOnItemLongClickListener(new OnItemLongClickListener() {
 5          public boolean onItemLongClick(AdapterView<?> parent, View view,
 6                int position, final long id) {
 7             final String[] itens = { "Editar" , "Deletar" };
 8             AlertDialog.Builder dialogo =
 9                new AlertDialog.Builder(MainActivity.this);
10             dialogo.setTitle( "Opções" );
11             dialogo.setItems(itens, new OnClickListener() {
12                public void onClick(DialogInterface dialog, int which) {
13                   switch (which) {
14                   case 0: // editar
15                      irParaSalvar(String.valueOf(id));
16                      break;
17                   case 1: // deletar
18                      int linhasAfetadas = helper.deletar(String.valueOf(id));
19                      if (linhasAfetadas > 0) {
20                          exibirMensagem( "Contatos deletado com sucesso." );
21                          carregar();
22                      } else {
23                          exibirMensagem( "Falha ao deletar contato." );
24                      }
25                      break;
26                   }
27                }
28             });
29             dialogo.show();
30             return true;
31          }
32      });
33   }
34

35   private void exibirMensagem(String mensagem) {
36      Toast.makeText(this, mensagem, Toast.LENGTH_LONG).show();
37   }


            Código-fonte 24: Adicionar Listener para click longo [MainActivity.java]




         Note a necessidade de um novo método 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 DIÁLOGOS                                                            25

Interface como parâmetro de um método




Você já deve ter notado o uso de interface’s como parâmetro dos métodos, por exemplo
na linha 4 e 11 do código acima. Essa prática obriga ao programador implementar a
classe na passagem dos parâmetros.

    Essa ideia vem de algumas linguagens de programação que possuem funções como
parâmetros para outras funções. Como o Java não suporta essa característica, a solução
veio em forma de uma interface, a qual o programador é obrigado a implementar seus
métodos. Com isso o método que recebe a interface como parâmetro sabe exatamente o
que ela tem disponível.

   A partir dessa observação, podemos justificar o uso da palavra reservada final em
alguns parâmetros dos métodos acima. Isso acontece porque alguns parâmetros são utili-
zados dentro da implementação das interface’s.

   Caso haja a necessidade de utilizar uma implementação em outra classe você pode criar
uma classe que implementa uma interface, por exemplo a interface OnItemLongClickListener.
Daí para a passagem do parâmetro apenas crie uma instância da classe. Por exemplo, supo-
nha que você tenha uma classe chamada OpcoesContato que implementa OnItemLongClickListener,
nesse caso a linha 4 se tornaria:

   listView.setOnItemLongClickListener(new OpcoesContato());




3.1.2   Diálogo de confirmação



Deletar dados é uma ação que deve ser feita com cuidado, então sempre é bom confirmar
com o usuário 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
botões Sim ou Não.

   Ainda em MainActivity criaremos um outro AlertDialog.Builder no momento que
o usuário clicar em Deletar. Segue o trecho:
26                                             CAPÍTULO 3. LIVRO DE RECEITAS

 1   /* ... */
 2   private void configurar() {
 3      /* ... */
 4      listView.setOnItemLongClickListener(new OnItemLongClickListener() {
 5          public boolean onItemLongClick(AdapterView<?> parent, View view,
 6                int position, final long id) {
 7             /* ... */
 8             dialogo.setItems(itens, new OnClickListener() {
 9                public void onClick(DialogInterface dialog, int which) {
10                   switch (which) {
11                   case 0: // editar
12                      irParaSalvar(String.valueOf(id));
13                      break;
14                   case 1: // deletar
15                      AlertDialog.Builder confirmacao =
16                          new AlertDialog.Builder(MainActivity.this);
17                      confirmacao.setTitle( "Deletar" );
18                      confirmacao.setMessage( "Deseja realmente deletar este contato?" );
19                      confirmacao.setPositiveButton( "Sim" , new OnClickListener() {
20                          public void onClick(DialogInterface dialog, int which) {
21                             int linhasAfetadas = helper.deletar(String.valueOf(id));
22                             if (linhasAfetadas > 0) {
23                                exibirMensagem( "Contatos deletado com sucesso." );
24                                carregar();
25                             } else {
26                                exibirMensagem( "Falha ao deletar contato." );
27                             }
28                          }
29                      });
30                      confirmacao.setNegativeButton( "Não" , null);
31                      confirmacao.show();
32                      break;
33                   }
34                }
35             });
36             dialogo.show();
37             return true;
38          }
39      });
40   }


          Código-fonte 25: Diálogo de confirmação ao deletar contato [MainActivity.java]

        Pronto, agora o trecho que deleta o contato foi movido para dentro do Listener do
     botão Sim. No botão Não passamos null no Listener, pois caso seja a opção escolhida
     apenas fazemos nada. Você pode se quiser criar um Listener e mostrar uma mensagem
     do tipo, Cancelado pelo usuário, para isso usando o método exibirMensagem.
3.1. MOSTRANDO DIÁLOGOS                                                                  27

3.1.3   Entrada de diferentes tipos de dados

O Android foi desenvolvido com muitos recursos pré-prontos para facilitar o desenvolvi-
mento de aplicações. Um recurso bastante útil é a distinção dos dados que irão ser inseridos
nos TextView’s. Com isso o teclado virtual do cliente se adapta ao tipo de dado que será
inserido. No nosso caso faremos distinção do campo telefone, onde apenas números e
hífens (-) podem ser inseridos, e o campo e-mail onde a presença do arroba (@) e pontos
(.) são elementos essenciais.
   Vejamos alguns valores aceitos pelo inputType:


     Para textos:


           text

           textCapCharacters

           textMultiLine

           textUri

           textEmailAddress

           textPersonName

           textPassword

           textVisiblePassword


     Para números:


           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                                              CAPÍTULO 3. LIVRO DE RECEITAS

 1   <!-- ... -->
 2   <TableRow android:id= "@+id/tableRow2"
 3      android:layout_width= "wrap_content"
 4      android:layout_height= "wrap_content" >
 5           <TextView android:id= "@+id/textView2"
 6               android:layout_width= "wrap_content"
 7               android:layout_height= "wrap_content"
 8               android:text= "Telefone:" ></TextView>
 9           <EditText android:layout_width= "wrap_content"
10               android:layout_height= "wrap_content"
11            android:id= "@+id/et_telefone"
12            android:inputType= "phone" ></EditText>
13   </TableRow>
14   <TableRow android:id= "@+id/tableRow3"
15      android:layout_width= "wrap_content"
16      android:layout_height= "wrap_content" >
17           <TextView android:id= "@+id/textView3"
18               android:layout_width= "wrap_content"
19               android:layout_height= "wrap_content"
20               android:text= "E-mail:" ></TextView>
21           <EditText android:layout_width= "wrap_content"
22               android:layout_height= "wrap_content"
23            android:id= "@+id/et_email"
24            android:inputType= "textEmailAddress" ></EditText>
25    </TableRow>
26   <!-- ... -->


                    Código-fonte 26: Distinção de dados [res/layout/salvar.xml]


     3.1.4     Validação de dados
     Mesmo configurando um inputType para seu TextView pode não 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 estão os objetos Patterns.EMAIL ADDRESS e Patterns.PHONE. Com
                                                          ¯
     eles podemos validar de forma simples os dados inseridos em nosso formulário.
         Em nosso SalvarActivity adicionaremos um método validar passando como pa-
     râmetro um ContentValues. Copie o método exibirMensagem da classe MainActivity
     para mostrar uma mensagem caso alguma validação seja falsa.


     OBS: Para um melhor reuso crie uma classe abstrata que implementa o método exibirMensagem
     e que extenda de Activity e faça com que seus Activity’s herdem dela. É uma boa prá-
     tica.
         Vamos ao trecho de código:
3.1. MOSTRANDO DIÁLOGOS                                                            29

 1   /* ... */
 2   private void ir() {
 3      btSalvar.setOnClickListener(new OnClickListener() {
 4

 5             public void onClick(View view) {
 6                ContentValues values = new ContentValues();
 7                values.put( "nome" , etNome.getText().toString());
 8                values.put( "telefone" , etTefone.getText().toString());
 9                values.put( "email" , etEmail.getText().toString());
10                if (validar(values)) {
11                   if (contatoId == null) {
12                      helper.criar(values);
13                   } else {
14                      helper.atualizar(contatoId, values);
15                   }
16                   finish();
17                }
18             }
19       });
20   }
21

22   private boolean validar(ContentValues values) {
23      if (!Patterns.PHONE.matcher(values.getAsString( "telefone" )).matches()) {
24         exibirMensagem( "Telefone não é válido." );
25         return false;
26      }
27

28       if (!Patterns.EMAIL_ADDRESS.matcher(values.getAsString( "email" )).matches()) {
29          exibirMensagem( "E-mail não é válido." );
30          return false;
31       }
32       return true;
33   }
34

35   private void exibirMensagem(String mensagem) {
36       Toast.makeText(this, mensagem, Toast.LENGTH_LONG).show();
37   }
38   /* ... */


                     Código-fonte 27: Validação dos dados [SalvarActivity.java]


     3.1.5      Fazendo uma ligação
     Já que estamos fazendo uma lista de contatos nada melhor que usar o número do telefone
     dos contatos inseridos para realizar chamadas. Para isso vamos aprender um pouco sobre
     Permissões.
        Permissões no Android são definidas no AndroidManifest.xml. Ao instalar seu aplica-
30                                                CAPÍTULO 3. LIVRO DE RECEITAS

    tivo, o usuário saberá quais as permissões que o seu aplicativo necessita para ser executado.
       Por padrão, o Android traz uma série de permissões que auxiliam seu aplicativo a se
    comunicar com o aparelho. Abaixo alguns exemplos:


          Verificação


               ACCESS NETWORK STATE
                     ¯       ¯
               ACCESS WIFI STATE
                     ¯    ¯
               BATTERY STATS
                      ¯

          Comunicação


               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   <?xml version="1.0" encoding="UTF-8"?>
2   <manifest xmlns:android= "http://schemas.android.com/apk/res/android"
3        package= "contatos.app"
4        android:versionCode= "1"
5        android:versionName= "1.0" >
6        <uses-permission android:name= "android.permission.CALL_PHONE" >
7        </uses-permission>
8        <!-- ... -->
9   </manifest>


             Código-fonte 28: Permissão de realizar chamadas [AndroidManifest.xml]


         Agora vamos adicionar um item ao diálogo 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 DIÁLOGOS                                                          31

 1   /* ... */
 2   private void configurar() {
 3      listView.setOnItemLongClickListener(new OnItemLongClickListener() {
 4          public boolean onItemLongClick(AdapterView<?> parent, View view,
 5                final int position, final long id) {
 6             final String[] itens = { "Editar" , "Deletar" , "Chamar" };
 7             /* ... */
 8             dialogo.setItems(itens, new OnClickListener() {
 9                public void onClick(DialogInterface dialog, int which) {
10                   switch (which) {
11                      /* ... */
12                      case 2: // chamar
13                          model.moveToPosition(position);
14                          startActivity(new Intent(Intent.ACTION_CALL,
15                                      Uri.parse( "tel:" + helper.getTelefone(model))
16                                    )
17                          );
18                          break;
19                   }
20                }
21             });
22             dialogo.show();
23             return true;
24          }
25      });
26   }


                  Código-fonte 29: Item chamar no diálogo [MainActivity.java]

        Nesse trecho de código podemos ver o uso de Intent’s do prórpio Android, nesse
     caso o Intent.ACTION CALL (veja linha 14 ). Ele serve para chamar uma Activity
                             ¯
     que realize ligações. Atente apenas para um detalhe - esse Intent faz a chamada sem
     confirmação. Caso você queira que o usuário possa visualizar o número no discador use o
     Intent Intent.ACTION DIAL. Faça esse teste e veja a diferença entre os Intent’s.
                             ¯
        Veja mais detalhes em http://developer.android.com/reference/android/content/
     Intent.html.
32                                             CAPÍTULO 3. LIVRO DE RECEITAS

     3.1.6   Enviando e-mail
     Para envio de e-mail você pode simplesmente usar a aplicação de e-mail padrão do apare-
     lho. Seguindo o mesmo princípio do exemplo anterior vamos apenas inserir um trecho de
     código no método configurar da classe MainActivity:

 1   /* ... */
 2   private void configurar() {
 3      listView.setOnItemLongClickListener(new OnItemLongClickListener() {
 4          public boolean onItemLongClick(AdapterView<?> parent, View view,
 5                final int position, final long id) {
 6             final String[] itens = { "Editar" , "Deletar" , "Chamar" ,
 7                  "Enviar e-mail" };
 8             /* ... */
 9             dialogo.setItems(itens, new OnClickListener() {
10                public void onClick(DialogInterface dialog, int which) {
11                   switch (which) {
12                      /* ... */
13                      case 3: // enviar e-mail
14                          model.moveToPosition(position);
15                          Intent email = new Intent(Intent.ACTION_SEND);
16                          email.setType( "plain/text" );
17                          email.putExtra(Intent.EXTRA_EMAIL,
18                             new String[]{ helper.getEmail(model) });
19                          startActivity(Intent.createChooser(email,
20                              "Enviar e-mail..." ));
21                          break;
22                   }
23                }
24             });
25             dialogo.show();
26             return true;
27          }
28      });
29   }


                Código-fonte 30: Item enviar e-mail no diálogo [MainActivity.java]

        Ao testar no emulador você receberá a mensagem: No applications can perform
     this action. Traduzindo quer dizer que: Nenhuma aplicação pode executar esta ação.
     Em outras palavras, nenhum cliente de e-mail foi encontrado.


     3.2     Internacionalização (i18n)
     3.2.1   Forçando região para teste
     Para podermos testar as strings de i18n podemos forçar o Activity a utilizar uma
     determinada linguagem. Isso se dá por meio da classe Locale. Façamos um teste com o
3.3. UTILIZANDO AS PREFERÊNCIAS DO ANDROID                                            33

     SalvarActivity inserindo o trecho de código abaixo no método onCreate. Vamos a ele:

 1   /* ... */
 2   @Override
 3   protected void onCreate(Bundle savedInstanceState) {
 4      /* ... */
 5      forceLocale( "pt" , "BR" );
 6      carregar();
 7      ir();
 8   }
 9

10   private void forceLocale(String language, String country) {
11      Locale locale = new Locale(language, country);
12      Locale.setDefault(locale);
13      Configuration configuration = new Configuration();
14      configuration.locale = locale;
15      getBaseContext().getResources()
16         .updateConfiguration(configuration,
17            getBaseContext().getResources().getDisplayMetrics());
18   }


                      Código-fonte 31: Forçando região [SalvarActivity.java]


         Para visualizar a mudança crie strings no seu arquivo strings.xml. Substitua as
     strings Nome, Telefone, E-mail e Salvar pelos respectivos valores em inglês Name, Phone,
     E-mail e Save. Agora crie outro arquivo strings.xml dentro do diretório /res/values-pt-rBR
     e insira as mesmas strings citadas anteriormente, traduzindo cada valor.
         Faça testes comentando a chamada para a função forceLocale e veja as mudanças.


     3.2.2   Forçando região pelo emulador

     A maneira mais rápida e prática de forçar a região é pelo próprio emulador. Vá até a
     lista de aplicativos e procure por Custom Locale. Depois pesquise por pt BR e caso não
                                                                             ¯
     encontre clique em Add New Locale. Digite pt BR e clique em Add and Select.
                                                   ¯


     3.3     Utilizando as Preferências do Android
     O Android já disponibiliza uma maneira de criar preferências de forma fácil. Para demons-
     trar implementaremos um exemplo bem amplo, que irá nos ajudar a entender ainda mais
     de Android. Para começar adicionaremos um nova coluna a nossa tabela contato cha-
     mada grupo. Depois adicionaremos um array de string’s ao nosso arquivo strings.xml
     e ainda vamos aprender a utilizar um Spinner, também conhecido como combo box. Por
     último, e não menos importante, usaremos as preferências para tornar padrão um valor
     de nosso Spinner.
34                                             CAPÍTULO 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 métodos
     onCreate e onUpgrade. Neste ponto será necessário o uso do método onUpgrade. Ele
     serve, como o nome sugere, para atualizar a DDL do banco de dados. Isso é útil quando
     seu cliente já possui uma versão do seu aplicativo instalada e ele quer apenas atualizar
     para uma nova versão. Também será necessário adicionar a coluna grupo nas queries.
     Abra a classe ContatoHelper em contatos.app.model e faça as modificações:


 1   public class ContatoHelper extends SQLiteOpenHelper {
 2      /* ... */
 3      private static final int VERSION = 2;
 4      private static final String TAG = "ContatoHelper" ;
 5

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

14        @Override
15        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
16           Log.w(TAG, "Atualizando banco de dados da versão "
17                 + oldVersion + " para " + newVersion + "." );
18           if (newVersion > oldVersion) {
19              switch (oldVersion) {
20              case 2:
21                 try {
22                    db.execSQL( "ALTER TABLE contato " +
23                           "ADD COLUMN grupo INTEGER NOT NULL DEFAULT 0" );
24                 } catch (SQLException e) {
25                    Log.e(TAG, "Erro ao executar SQL: " , e);
26                 }
27              default:
28                 Log.w(TAG, "Versão desconhecida: " + oldVersion +
29                     ". Criando novo banco de dados." );
30                 db.execSQL( "DROP TABLE IF EXISTS contato" );
31                 onCreate(db);
32              }
33           }
34        }
35   }


             Código-fonte 32: Nova coluna grupo na base de dados [ContatoHelper.java]
3.3. UTILIZANDO AS PREFERÊNCIAS DO ANDROID                                          35

        Vemos neste exemplo o uso da classe Log do pacote android.util. Ela possui apenas
     métodos estáticos, assim não precisamos instanciar, apenas faça a chamada dos métodos.
     Temos:

     Log.w() para mostrar warning’s, 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   public class ContatoHelper extends SQLiteOpenHelper {
 2      /* ... */
 3      public Cursor listar() {
 4         return getReadableDatabase()
 5            .rawQuery( "SELECT _id, nome, telefone, email, grupo " +
 6                   "FROM contato ORDER BY nome" , null);
 7      }
 8

 9       public int getGrupo(Cursor c) {
10          return c.getInt(4);
11       }
12

13       public Cursor ler(String id) {
14          String[] params = {id};
15          return getReadableDatabase()
16             .rawQuery( "SELECT _id, nome, telefone, email, grupo " +
17                    "FROM contato WHERE _id = ?" , params);
18       }
19   }


                 Código-fonte 33: Modificação nas queries [ContatoHelper.java]


     3.3.2   Array de Strings
     No arquivo de string’s do Android é possível criar vários recursos. Dentre eles temos
     Cor, Dimensão, 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 não seria necessário o uso de String Array’s.
36                                              CAPÍTULO 3. LIVRO DE RECEITAS

 1   <?xml version="1.0" encoding="utf-8"?>
 2   <resources>
 3       <!-- ... -->
 4       <string-array name= "array_grupos" >
 5           <item>amigos</item>
 6           <item>trabalho</item>
 7           <item>conhecidos</item>
 8           <item>família</item>
 9       </string-array>
10       <string-array name= "index_array_grupos" >
11           <item>0</item><item>1</item>
12           <item>2</item><item>3</item>
13       </string-array>
14   </resources>


                          Código-fonte 34: Array de Strings [strings.xml]


     3.3.3     Spinner, diálogo de seleção
     O Spinner é ideal quando temos que escolher entre valores fixos, sejam eles estáticos
     ou dinâmicos. Nosso exemplo irá utilizar valores estáticos para popular o mesmo. Para
     isso utilizaremos o array grupos que criamos em res/values/strings.xml. Também
                              ¯
     veremos um exemplo de uso da classe android.R como visto em 2.1.2 em que é explicado
     a diferença 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   <TableRow
 3        android:id= "@+id/tableRow4"
 4        android:layout_width= "wrap_content"
 5        android:layout_height= "wrap_content" >
 6

 7           <TextView
 8               android:id= "@+id/textView4"
 9               android:layout_width= "wrap_content"
10               android:layout_height= "wrap_content"
11               android:text= "Grupo:" />
12

13        <Spinner
14            android:id= "@+id/sp_grupo"
15            android:layout_width= "wrap_content"
16            android:layout_height= "wrap_content" />
17    </TableRow>
18   <!-- ... -->


               Código-fonte 35: Adicionando elemento Spinner [res/layout/salvar.xml]
3.3. UTILIZANDO AS PREFERÊNCIAS DO ANDROID                                         37

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

 1   public class SalvarActivity extends Activity {
 2      /* ... */
 3      private Spinner spGrupo = null;
 4

 5       private void carregar() {
 6          /* ... */
 7          spGrupo = (Spinner) findViewById(R.id.sp_grupo);
 8          ArrayAdapter<CharSequence> adapter =
 9                ArrayAdapter.createFromResource(this,
10                      R.array.array_grupos, android.R.layout.simple_spinner_item);
11          adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
12          spGrupo.setAdapter(adapter);
13          /* antes de verificar o parâmetro contatoId */
14       }
15

16       private void carregarContato() {
17          spGrupo.setSelection(helper.getGrupo(c));
18          c.close();
19       }
20

21       private void ir() {
22          btSalvar.setOnClickListener(new View.OnClickListener() {
23             /* ... */
24             contato.setGrupo(spGrupo.getSelectedItemPosition());
25             /* antes de validar e salvar */
26          }
27       }
28   }


                   Código-fonte 36: Utilização de Spinner [SalvarActivity.java]

         Note a utilização 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 preferências do Android. Neste exemplo a usaremos para decidir
     qual grupo do array grupos aparecerá selecionado por padrão. A princípio é um exemplo
                         ¯
     bem simples, mas que pode ser ajustado para outras finalidades, o que importa realmente
     é a ideia.
         Para começar criaremos um layout em res/layout chamado preferencias.xml. No
     projeto clique com botão 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 opção PreferenceScreen, então
38                                               CAPÍTULO 3. LIVRO DE RECEITAS

     Finish.
        Utilizando a ferramenta ADT adicione um elemento ListPreference a PreferenceScreen.
     Defina os parâmetros necessários como mostra o código abaixo:

 1   <?xml version="1.0" encoding="utf-8"?>
 2   <PreferenceScreen xmlns:android= "http://schemas.android.com/apk/res/android" >
 3       <ListPreference
 4        android:summary= "Selecione o grupo padrão"
 5        android:dialogTitle= "Escolha um Grupo"
 6          android:entries= "@array/array_grupos"
 7        android:entryValues= "@array/index_array_grupos"
 8        android:key= "lista_grupos"
 9        android:title= "Grupos" />
10   </PreferenceScreen>


         Código-fonte 37: XML descrevendo layout de preferências [res/xml/preferencias.xml]


         Crie uma nova classe chamada EditarPreferencias em contatos.app.view her-
     dando de PreferenceActivity. Agora de uma maneira bem simples implementaremos
     essa classe. Veja:

 1   package app.contatos.view;
 2

 3   import android.os.Bundle;
 4   import android.preference.PreferenceActivity;
 5   import app.contatos.R;
 6

 7   public class EditarPreferencias extends PreferenceActivity {
 8

 9        @Override
10        protected void onCreate(Bundle savedInstanceState) {
11           super.onCreate(savedInstanceState);
12           addPreferencesFromResource(R.xml.preferencias);
13        }
14   }


            Código-fonte 38: Activity para mostrar preferências [EditarPreferencias.java]


       Para chamar a nova Activity temos ainda que mapeá-la no AndroidManifest e criar
     um item no menu.

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


           Código-fonte 39: Mapeando Activity EditarPreferencias [AndroidManifest.xml]
3.3. UTILIZANDO AS PREFERÊNCIAS DO ANDROID                                            39

 1   <?xml version="1.0" encoding="utf-8"?>
 2   <menu xmlns:android= "http://schemas.android.com/apk/res/android" >
 3       <!-- ... -->
 4       <item
 5           android:id= "@+id/menu_pref"
 6           android:icon= "@android:drawable/ic_menu_preferences"
 7           android:title= "Preferências" >
 8       </item>
 9   </menu>


     Código-fonte   40:     Adicionar        item    Preferências    ao    menu      principal
     [res/menu/main menu.xml]
                   ¯

        Agora que adicionamos um item ao menu, temos que capturar o evento quando o
     usuário o selecionar e direcioná-lo às Preferências. Isso deve ser feito em MainActivity.

 1   /* ... */
 2   @Override
 3   public boolean onOptionsItemSelected(MenuItem item) {
 4      if (item.getItemId() == R.id.menu_add) {
 5         irPara(SalvarActivity.class);
 6         return true;
 7      } else if (item.getItemId() == R.id.menu_pref) {
 8         irPara(EditarPreferencias.class);
 9         return true;
10      }
11      return super.onOptionsItemSelected(item);
12   }
13

14   private void irPara(Class<?> clazz) {
15      irPara(clazz, null);
16   }
17

18   private void irPara(Class<?> clazz, String id) {
19       Intent intent = new Intent(MainActivity.this, clazz);
20       if (id != null) {
21          intent.putExtra(_ID, id);
22       }
23      startActivity(intent);
24   }


          Código-fonte 41: Ir para Preferências pelo menu principal [MainActivity.java]

        Note que para ter um código mais eficiente e otimizado tivemos que mudar o método
     irParaSalvar para irPara passando como parâmetro a classe que desejamos ir. Essa
     mudança é boa mais causa um impacto em outros trechos do código. Conserte-os da
40                                                CAPÍTULO 3. LIVRO DE RECEITAS

     seguinte maneira:
 1   /* ... */
 2   private void configurar() {
 3      listView.setOnItemClickListener(new OnItemClickListener() {
 4          public void onItemClick(AdapterView<?> parent, View view,
 5                int position, long id) {
 6             irPara(SalvarActivity.class, String.valueOf(id));
 7          }
 8      });
 9

10        listView.setOnItemLongClickListener(new OnItemLongClickListener() {
11           public boolean onItemLongClick(AdapterView<?> parent, View view,
12                 final int position, final long id) {
13              /* ... */
14              public void onClick(DialogInterface dialog, int which) {
15                 switch (which) {
16                    case 0: // editar
17                       irPara(SalvarActivity.class, String.valueOf(id));
18                       break;
19                    /* ... */
20

21                     }
22                 }
23            }
24        }
25   }


                  Código-fonte 42: Mudança em método irParaSalvar [MainActivity.java]

        Por fim temos que selecionar o item que o usuário quer que esteja selecionado por
     padrão ao inserir um novo contato. Assim, em SalvarActivity adicione o trecho:

 1   private void carregar() {
 2      /* ... */
 3      contatoId = getIntent().getStringExtra(MainActivity._ID);
 4      if (contatoId != null) {
 5         carregarContato();
 6      } else {
 7         SharedPreferences preferencias =
 8               PreferenceManager.getDefaultSharedPreferences(this);
 9         spGrupo.setSelection(
10               Integer.parseInt(preferencias.getString( "lista_grupos" , "0" )));
11      }
12   }


         Código-fonte 43: Obtem o valor padrão definido nas Preferências [SalvarActivity.java]
3.4. GRUPO DE CONTATOS USANDO GRID                                                    41

     3.4     Grupo de Contatos usando Grid

     Uma das coisas mais legais quando falamos de aparelhos móveis é a ideia da visão 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 implementação vamos criar uma tela que mostra os grupos de contatos em forma
     de Grid e ao clicar levaremos o usuário a lista de contatos mostrando apenas aqueles
     contatos de um determinado grupo.



     3.4.1   Layout usando GridView

     Para começar criaremos um layout em res/layout chamado grupos item.xml. Ele irá
                                                                      ¯
     conter a imagem e o texto que serão exibidos no GridView. Faça como mostra o trecho
     abaixo:

 1   <?xml version="1.0" encoding="utf-8"?>
 2   <LinearLayout xmlns:android= "http://schemas.android.com/apk/res/android"
 3       android:layout_width= "fill_parent"
 4       android:layout_height= "match_parent"
 5       android:gravity= "center"
 6       android:orientation= "vertical" >
 7

 8      <ImageView
 9          android:id= "@+id/iv_icone"
10          android:layout_width= "wrap_content"
11          android:layout_height= "96.0dip"
12          android:scaleType= "fitCenter" />
13

14       <TextView
15           android:id= "@+id/tv_texto"
16           android:layout_width= "fill_parent"
17           android:layout_height= "wrap_content"
18           android:layout_marginBottom= "20.0dip"
19           android:layout_marginTop= "2.0dip"
20           android:gravity= "center"
21           android:text= "TextView"
22           android:textAppearance= "?android:textAppearanceMedium" />
23   </LinearLayout>


             Código-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 código abaixo:
42                                              CAPÍTULO 3. LIVRO DE RECEITAS

 1   <?xml version="1.0" encoding="utf-8"?>
 2   <LinearLayout xmlns:android= "http://schemas.android.com/apk/res/android"
 3       android:layout_width= "match_parent"
 4       android:layout_height= "match_parent"
 5       android:orientation= "vertical" >
 6

 7        <GridView
 8            android:id= "@+id/gv_grupos"
 9            android:layout_width= "match_parent"
10            android:layout_height= "wrap_content"
11            android:numColumns= "3" >
12            <!-- Preview: listitem=@layout/grupos_item -->
13        </GridView>
14

15   </LinearLayout>


                    Código-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 comentário e nele temos a referência ao layout grupos item. Para
                                                                            ¯
     isso apenas clique com botão direito do mouse na GridView e na opção 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 {
 2

 3        private GridView grid = null;
 4

 5        @Override
 6        protected void onCreate(Bundle savedInstanceState) {
 7           super.onCreate(savedInstanceState);
 8

 9            setContentView(R.layout.grupos);
10            carregar();
11        }
12

13        private void carregar() {
14           grid = (GridView) findViewById(R.id.gv_grupos);
15        }
16   }


               Código-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 {
 3

 4       private Context context;
 5

 6       public IconeAdapter(Context context) {
 7          super();
 8          this.context = context;
 9       }
10

11       static class GruposHolder {
12          public ImageView icone;
13          public TextView texto;
14       }
15

16       public int getCount() {
17          return 0;
18       }
19

20       public Object getItem(int position) {
21          return null;
22       }
23

24       public long getItemId(int position) {
25          return 0;
26       }
27

28       public View getView(int position, View convertView, ViewGroup parent) {
29          return null;
30       }
31   }


         Código-fonte 47: Adapter responsável 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:

           amigos

           trabalho

           conhecidos

           família
Desenvolvimento Android do zero
Desenvolvimento Android do zero
Desenvolvimento Android do zero
Desenvolvimento Android do zero
Desenvolvimento Android do zero
Desenvolvimento Android do zero
Desenvolvimento Android do zero
Desenvolvimento Android do zero

Más contenido relacionado

La actualidad más candente

Programando ooo b
Programando ooo bProgramando ooo b
Programando ooo bvangney
 
Hands on map 3d 2011
Hands on map 3d 2011Hands on map 3d 2011
Hands on map 3d 2011Peer Ter
 
Programacao cpp
Programacao cppProgramacao cpp
Programacao cppTiago
 
249371958 guia-seguranca-debian
249371958 guia-seguranca-debian249371958 guia-seguranca-debian
249371958 guia-seguranca-debianSergio Boudart
 
K19 k52-desenvolvimento-web-com-struts
K19 k52-desenvolvimento-web-com-strutsK19 k52-desenvolvimento-web-com-struts
K19 k52-desenvolvimento-web-com-strutsCaique Moretto
 
K19 k23-integracao-de-sistemas-com-webservices-jms-e-ejb
K19 k23-integracao-de-sistemas-com-webservices-jms-e-ejbK19 k23-integracao-de-sistemas-com-webservices-jms-e-ejb
K19 k23-integracao-de-sistemas-com-webservices-jms-e-ejbCaique Moretto
 
Introdução à programação em R
Introdução à programação em RIntrodução à programação em R
Introdução à programação em RMonica Barros
 
K19 k22-desenvolvimento-web-avancado-com-jsf2-ejb3.1-e-cdi
K19 k22-desenvolvimento-web-avancado-com-jsf2-ejb3.1-e-cdiK19 k22-desenvolvimento-web-avancado-com-jsf2-ejb3.1-e-cdi
K19 k22-desenvolvimento-web-avancado-com-jsf2-ejb3.1-e-cdiCaique Moretto
 
K19 k12-desenvolvimento-web-com-jsf2-e-jpa2
K19 k12-desenvolvimento-web-com-jsf2-e-jpa2K19 k12-desenvolvimento-web-com-jsf2-e-jpa2
K19 k12-desenvolvimento-web-com-jsf2-e-jpa2surdido
 
K19 k32-desenvolvimento-web-com-aspnet-mvc
K19 k32-desenvolvimento-web-com-aspnet-mvcK19 k32-desenvolvimento-web-com-aspnet-mvc
K19 k32-desenvolvimento-web-com-aspnet-mvcCaique Moretto
 
K19 k41-desenvolvimento-mobile-com-android
K19 k41-desenvolvimento-mobile-com-androidK19 k41-desenvolvimento-mobile-com-android
K19 k41-desenvolvimento-mobile-com-androidCaique Moretto
 
K19 k21-persistencia-com-jpa2-e-hibernate
K19 k21-persistencia-com-jpa2-e-hibernateK19 k21-persistencia-com-jpa2-e-hibernate
K19 k21-persistencia-com-jpa2-e-hibernateCaique Moretto
 
Caelum ruby-on-rails-rr71
Caelum ruby-on-rails-rr71Caelum ruby-on-rails-rr71
Caelum ruby-on-rails-rr71Caique Moretto
 
Publicado ruby on-rails-rr71
Publicado ruby on-rails-rr71Publicado ruby on-rails-rr71
Publicado ruby on-rails-rr71Fernando Palma
 
Relatório de Projecto de Licenciatura
Relatório de Projecto de LicenciaturaRelatório de Projecto de Licenciatura
Relatório de Projecto de LicenciaturaJoel Carvalho
 
My sql
My sqlMy sql
My sqlTiago
 

La actualidad más candente (19)

Programando ooo b
Programando ooo bProgramando ooo b
Programando ooo b
 
Hands on map 3d 2011
Hands on map 3d 2011Hands on map 3d 2011
Hands on map 3d 2011
 
Programacao cpp
Programacao cppProgramacao cpp
Programacao cpp
 
249371958 guia-seguranca-debian
249371958 guia-seguranca-debian249371958 guia-seguranca-debian
249371958 guia-seguranca-debian
 
K19 k52-desenvolvimento-web-com-struts
K19 k52-desenvolvimento-web-com-strutsK19 k52-desenvolvimento-web-com-struts
K19 k52-desenvolvimento-web-com-struts
 
K19 k23-integracao-de-sistemas-com-webservices-jms-e-ejb
K19 k23-integracao-de-sistemas-com-webservices-jms-e-ejbK19 k23-integracao-de-sistemas-com-webservices-jms-e-ejb
K19 k23-integracao-de-sistemas-com-webservices-jms-e-ejb
 
Introdução à programação em R
Introdução à programação em RIntrodução à programação em R
Introdução à programação em R
 
K19 k22-desenvolvimento-web-avancado-com-jsf2-ejb3.1-e-cdi
K19 k22-desenvolvimento-web-avancado-com-jsf2-ejb3.1-e-cdiK19 k22-desenvolvimento-web-avancado-com-jsf2-ejb3.1-e-cdi
K19 k22-desenvolvimento-web-avancado-com-jsf2-ejb3.1-e-cdi
 
K19 k12-desenvolvimento-web-com-jsf2-e-jpa2
K19 k12-desenvolvimento-web-com-jsf2-e-jpa2K19 k12-desenvolvimento-web-com-jsf2-e-jpa2
K19 k12-desenvolvimento-web-com-jsf2-e-jpa2
 
K19 k32-desenvolvimento-web-com-aspnet-mvc
K19 k32-desenvolvimento-web-com-aspnet-mvcK19 k32-desenvolvimento-web-com-aspnet-mvc
K19 k32-desenvolvimento-web-com-aspnet-mvc
 
Curso estatistica descritiva no r
Curso   estatistica descritiva no rCurso   estatistica descritiva no r
Curso estatistica descritiva no r
 
K19 k41-desenvolvimento-mobile-com-android
K19 k41-desenvolvimento-mobile-com-androidK19 k41-desenvolvimento-mobile-com-android
K19 k41-desenvolvimento-mobile-com-android
 
K19 k21-persistencia-com-jpa2-e-hibernate
K19 k21-persistencia-com-jpa2-e-hibernateK19 k21-persistencia-com-jpa2-e-hibernate
K19 k21-persistencia-com-jpa2-e-hibernate
 
Apostila JSF 2.0 - K19
Apostila JSF 2.0 - K19Apostila JSF 2.0 - K19
Apostila JSF 2.0 - K19
 
Caelum ruby-on-rails-rr71
Caelum ruby-on-rails-rr71Caelum ruby-on-rails-rr71
Caelum ruby-on-rails-rr71
 
Publicado ruby on-rails-rr71
Publicado ruby on-rails-rr71Publicado ruby on-rails-rr71
Publicado ruby on-rails-rr71
 
Relatório de Projecto de Licenciatura
Relatório de Projecto de LicenciaturaRelatório de Projecto de Licenciatura
Relatório de Projecto de Licenciatura
 
My sql
My sqlMy sql
My sql
 
Estrutura de dados
Estrutura de dadosEstrutura de dados
Estrutura de dados
 

Destacado

Linux - Instalação de Programas
Linux - Instalação de ProgramasLinux - Instalação de Programas
Linux - Instalação de ProgramasÁtila Camurça
 
Aplicativos - Ubuntu COMSOLiD
Aplicativos - Ubuntu COMSOLiDAplicativos - Ubuntu COMSOLiD
Aplicativos - Ubuntu COMSOLiDÁtila Camurça
 
Tradução de Aplicativos Livres
Tradução de Aplicativos LivresTradução de Aplicativos Livres
Tradução de Aplicativos LivresÁtila Camurça
 
Linux - Customização e Repositórios Off-line
Linux - Customização e Repositórios Off-lineLinux - Customização e Repositórios Off-line
Linux - Customização e Repositórios Off-lineÁtila Camurça
 
Onde o Software Livre pode te levar
Onde o Software Livre pode te levarOnde o Software Livre pode te levar
Onde o Software Livre pode te levarDarlildo Lima
 

Destacado (7)

Software livre
Software livreSoftware livre
Software livre
 
Linux - Instalação de Programas
Linux - Instalação de ProgramasLinux - Instalação de Programas
Linux - Instalação de Programas
 
Aplicativos - Ubuntu COMSOLiD
Aplicativos - Ubuntu COMSOLiDAplicativos - Ubuntu COMSOLiD
Aplicativos - Ubuntu COMSOLiD
 
Tradução de Aplicativos Livres
Tradução de Aplicativos LivresTradução de Aplicativos Livres
Tradução de Aplicativos Livres
 
Linux - Customização e Repositórios Off-line
Linux - Customização e Repositórios Off-lineLinux - Customização e Repositórios Off-line
Linux - Customização e Repositórios Off-line
 
Ubuntu COMSOLiD 5
Ubuntu COMSOLiD 5Ubuntu COMSOLiD 5
Ubuntu COMSOLiD 5
 
Onde o Software Livre pode te levar
Onde o Software Livre pode te levarOnde o Software Livre pode te levar
Onde o Software Livre pode te levar
 

Similar a Desenvolvimento Android do zero (20)

Poojava
PoojavaPoojava
Poojava
 
Poojava
PoojavaPoojava
Poojava
 
Manualipdoc4 pt
Manualipdoc4 ptManualipdoc4 pt
Manualipdoc4 pt
 
Poojava
PoojavaPoojava
Poojava
 
Programação Orientada a Objetos com Java
Programação Orientada a Objetos com JavaProgramação Orientada a Objetos com Java
Programação Orientada a Objetos com Java
 
Manual do Kile
Manual do KileManual do Kile
Manual do Kile
 
Apostila geo gebra
Apostila geo gebraApostila geo gebra
Apostila geo gebra
 
Apostilando mysql
Apostilando mysqlApostilando mysql
Apostilando mysql
 
Sql
SqlSql
Sql
 
Php
PhpPhp
Php
 
Arquitetura computadores
Arquitetura computadoresArquitetura computadores
Arquitetura computadores
 
Introdução às redes
Introdução às redesIntrodução às redes
Introdução às redes
 
Manual sobre a ferramenta Kate - Linux
Manual sobre a ferramenta Kate - LinuxManual sobre a ferramenta Kate - Linux
Manual sobre a ferramenta Kate - Linux
 
Dissertação Mestrado
Dissertação MestradoDissertação Mestrado
Dissertação Mestrado
 
Programming Languages Paradigms
Programming Languages ParadigmsProgramming Languages Paradigms
Programming Languages Paradigms
 
Ncl e Lua - desenvolvendo aplicações interativas para tv digital
Ncl e Lua - desenvolvendo aplicações interativas para tv digitalNcl e Lua - desenvolvendo aplicações interativas para tv digital
Ncl e Lua - desenvolvendo aplicações interativas para tv digital
 
Apostila aspnet mvc
Apostila aspnet mvcApostila aspnet mvc
Apostila aspnet mvc
 
android
androidandroid
android
 
Lpi 101
Lpi 101Lpi 101
Lpi 101
 
Algoritmos jabour
Algoritmos jabourAlgoritmos jabour
Algoritmos jabour
 

Más de Átila Camurça

Software Livre: Além da filosofia
Software Livre: Além da filosofiaSoftware Livre: Além da filosofia
Software Livre: Além da filosofiaÁtila Camurça
 
Espionagem e Software Livre
Espionagem e Software LivreEspionagem e Software Livre
Espionagem e Software LivreÁtila Camurça
 
NodeJS - E/S não-bloqueante - Dirigido a Eventos
NodeJS - E/S não-bloqueante - Dirigido a EventosNodeJS - E/S não-bloqueante - Dirigido a Eventos
NodeJS - E/S não-bloqueante - Dirigido a EventosÁtila Camurça
 
Onde o Software Livre pode te levar - Uma viagem ao mundo livre
Onde o Software Livre pode te levar - Uma viagem ao mundo livreOnde o Software Livre pode te levar - Uma viagem ao mundo livre
Onde o Software Livre pode te levar - Uma viagem ao mundo livreÁtila Camurça
 

Más de Átila Camurça (7)

Ciência e Informática
Ciência e InformáticaCiência e Informática
Ciência e Informática
 
Software Livre: Além da filosofia
Software Livre: Além da filosofiaSoftware Livre: Além da filosofia
Software Livre: Além da filosofia
 
Espionagem e Software Livre
Espionagem e Software LivreEspionagem e Software Livre
Espionagem e Software Livre
 
Ubuntu COMSOLiD 6
Ubuntu COMSOLiD 6Ubuntu COMSOLiD 6
Ubuntu COMSOLiD 6
 
Árvores B
Árvores BÁrvores B
Árvores B
 
NodeJS - E/S não-bloqueante - Dirigido a Eventos
NodeJS - E/S não-bloqueante - Dirigido a EventosNodeJS - E/S não-bloqueante - Dirigido a Eventos
NodeJS - E/S não-bloqueante - Dirigido a Eventos
 
Onde o Software Livre pode te levar - Uma viagem ao mundo livre
Onde o Software Livre pode te levar - Uma viagem ao mundo livreOnde o Software Livre pode te levar - Uma viagem ao mundo livre
Onde o Software Livre pode te levar - Uma viagem ao mundo livre
 

Desenvolvimento Android do zero

  • 1. por Átila Camurça 2a Edição 27 de outubro de 2012
  • 2. ii
  • 3. Sumário 1 Preparando o Ambiente de Desenvolvimento 1 1.1 Introdução . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.2 Instalação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.2.1 Java JDK 6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.2.2 Android SDK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 1.2.3 Android 2.2 API 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 1.2.4 Android Virtual Device (AVD) . . . . . . . . . . . . . . . . . . . . . 4 1.2.5 Eclipse Juno . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 1.2.6 Plugin ADT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 1.2.7 Sqlite3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 1.2.8 Sqliteman . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 1.2.9 Inkscape . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 2 Exemplo prático 9 2.1 Primeira aplicação - Contatos . . . . . . . . . . . . . . . . . . . . . . . . . . 9 2.1.1 AndroidManifest.xml . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 2.1.2 Activity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 2.1.3 Formulários . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 2.1.4 Construindo o Model da aplicação . . . . . . . . . . . . . . . . . . . 14 2.1.5 Mostrando os dados na View . . . . . . . . . . . . . . . . . . . . . . 16 2.1.6 Editando dados existentes . . . . . . . . . . . . . . . . . . . . . . . . 20 3 Livro de Receitas 23 3.1 Mostrando Diálogos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 3.1.1 Editar/Excluir ao clicar e segurar na ListView . . . . . . . . . . . . 23 3.1.2 Diálogo de confirmação . . . . . . . . . . . . . . . . . . . . . . . . . 25 3.1.3 Entrada de diferentes tipos de dados . . . . . . . . . . . . . . . . . . 27 3.1.4 Validação de dados . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 3.1.5 Fazendo uma ligação . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 3.1.6 Enviando e-mail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 3.2 Internacionalização (i18n) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 3.2.1 Forçando região para teste . . . . . . . . . . . . . . . . . . . . . . . . 32 3.2.2 Forçando região pelo emulador . . . . . . . . . . . . . . . . . . . . . 33 3.3 Utilizando as Preferências do Android . . . . . . . . . . . . . . . . . . . . . 33 3.3.1 Atualizando colunas de uma tabela . . . . . . . . . . . . . . . . . . . 34 3.3.2 Array de Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 3.3.3 Spinner, diálogo de seleção . . . . . . . . . . . . . . . . . . . . . . . 36 iii
  • 4. iv SUMÁRIO 3.3.4 A classe PreferenceActivity . . . . . . . . . . . . . . . . . . . . . . . 37 3.4 Grupo de Contatos usando Grid . . . . . . . . . . . . . . . . . . . . . . . . 41 3.4.1 Layout usando GridView . . . . . . . . . . . . . . . . . . . . . . . . 41 3.4.2 Activity para visualizar os Grupos . . . . . . . . . . . . . . . . . . . 42 3.4.3 Implementando o Adapter . . . . . . . . . . . . . . . . . . . . . . . . 45 3.4.4 Selecionando contatos de um determinado grupo . . . . . . . . . . . 46 A Sobre o Autor 49 Glossário 51
  • 5. Lista de Códigos-fonte 1 Exemplo de banco de dados [exemplo-bd.sql] . . . . . . . . . . . . . . . . . 7 2 Exemplo de query com subquery [exemplo-bd.sql] . . . . . . . . . . . . . . . 7 3 Projeto inicial [AndroidManifest.xml] . . . . . . . . . . . . . . . . . . . . . . 9 4 Layout principal [res/layout/main.xml] . . . . . . . . . . . . . . . . . . . . . 10 5 Menu principal [res/menu/main menu.xml] . . . . . . . . . . . . . . . . . . 10 ¯ 6 Definir layout [MainActivity.java] . . . . . . . . . . . . . . . . . . . . . . . . 11 7 Criando o menu [MainActivity.java] . . . . . . . . . . . . . . . . . . . . . . . 12 8 Formulário principal [res/layout/salvar.xml] . . . . . . . . . . . . . . . . . . 13 9 Mudando de Activity [MainActivity.java] . . . . . . . . . . . . . . . . . . . . 14 10 Utilizando EditText’s [SalvarActivity.java] . . . . . . . . . . . . . . . . . . . 14 11 Mapear SalvarActivity [AndroidManifest.xml] . . . . . . . . . . . . . . . . . 14 12 Helper da aplicação [ContatoHelper.java] . . . . . . . . . . . . . . . . . . . . 15 13 Criar novo contato [ContatoHelper.java] . . . . . . . . . . . . . . . . . . . . 15 14 Fim da iteração criar contato [SalvarActivity.java] . . . . . . . . . . . . . . 16 15 Layout para cada linha da lista [res/layout/linha.xml] . . . . . . . . . . . . 17 16 Listar contatos existentes [ContatoHelper.java] . . . . . . . . . . . . . . . . 18 17 Classe Holder [MainActivity.java] . . . . . . . . . . . . . . . . . . . . . . . . 18 18 Classe Adapter [MainActivity.java] . . . . . . . . . . . . . . . . . . . . . . . 19 19 Popular ListView [MainActivity.java] . . . . . . . . . . . . . . . . . . . . . . 20 20 Passagem de parâmetros [MainActivity.java] . . . . . . . . . . . . . . . . . . 21 21 Ler e atualizar dados existentes [ContatoHelper.java] . . . . . . . . . . . . . 21 22 Usando Activity para criar ou atualizar [SalvarActivity.java] . . . . . . . . . 22 23 Deletar dados existentes [ContatoHelper.java] . . . . . . . . . . . . . . . . . 23 24 Adicionar Listener para click longo [MainActivity.java] . . . . . . . . . . . . 24 25 Diálogo de confirmação ao deletar contato [MainActivity.java] . . . . . . . . 26 26 Distinção de dados [res/layout/salvar.xml] . . . . . . . . . . . . . . . . . . . 28 27 Validação dos dados [SalvarActivity.java] . . . . . . . . . . . . . . . . . . . . 29 28 Permissão de realizar chamadas [AndroidManifest.xml] . . . . . . . . . . . . 30 29 Item chamar no diálogo [MainActivity.java] . . . . . . . . . . . . . . . . . . 31 30 Item enviar e-mail no diálogo [MainActivity.java] . . . . . . . . . . . . . . . 32 31 Forçando região [SalvarActivity.java] . . . . . . . . . . . . . . . . . . . . . . 33 32 Nova coluna grupo na base de dados [ContatoHelper.java] . . . . . . . . . . 34 33 Modificação nas queries [ContatoHelper.java] . . . . . . . . . . . . . . . . . 35 34 Array de Strings [strings.xml] . . . . . . . . . . . . . . . . . . . . . . . . . . 36 35 Adicionando elemento Spinner [res/layout/salvar.xml] . . . . . . . . . . . . 36 36 Utilização de Spinner [SalvarActivity.java] . . . . . . . . . . . . . . . . . . . 37 37 XML descrevendo layout de preferências [res/xml/preferencias.xml] . . . . . 38 v
  • 6. vi LISTA DE CÓDIGOS-FONTE 38 Activity para mostrar preferências [EditarPreferencias.java] . . . . . . . . . 38 39 Mapeando Activity EditarPreferencias [AndroidManifest.xml] . . . . . . . . 38 40 Adicionar item Preferências ao menu principal [res/menu/main menu.xml] . 39 ¯ 41 Ir para Preferências pelo menu principal [MainActivity.java] . . . . . . . . . 39 42 Mudança em método irParaSalvar [MainActivity.java] . . . . . . . . . . . . 40 43 Obtem o valor padrão definido nas Preferências [SalvarActivity.java] . . . . 40 44 Item do Layout de Grupos [res/layout/grupos item.xml] . . . . . . . . . . . 41 ¯ 45 Layout de Grupos [res/layout/grupos.xml] . . . . . . . . . . . . . . . . . . . 42 46 Activity para visualizar Grupos [GruposActivity.java] . . . . . . . . . . . . . 42 47 Adapter responsável por cada item do Grid [GruposActivity.java] . . . . . . 43 48 implementação do Adapter [GruposActivity.java] . . . . . . . . . . . . . . . 45 49 Método listar com parâmetro grupo [ContatoHelper.java] . . . . . . . . . . 46 50 Evento de clique em um item do grid [GruposActivity.java] . . . . . . . . . 47 51 Captura de parâmetro vindo de GruposActivity [MainActivity.java] . . . . 47
  • 7. Lista de Tabelas 1.1 Tipos de dados do Sqlite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 2.1 Convenção para nome dos ícones . . . . . . . . . . . . . . . . . . . . . . . . 11 3.1 Paleta de cores do Android . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 3.2 Localização e tamanho dos ícones . . . . . . . . . . . . . . . . . . . . . . . . 44 vii
  • 8. viii LISTA DE TABELAS
  • 9. Lista de Figuras 2.1 Layout linha da Lista . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 3.1 Tela de Grupos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 ix
  • 10. x LISTA DE FIGURAS
  • 11. Capítulo 1 Preparando o Ambiente de Desenvolvimento 1.1 Introdução O desenvolvimento de aplicativos para a plataforma Android é feito na linguagem Java. Para esta apostila serão utilizados os seguintes aplicativos e bibliotecas: Ubuntu 10.04 ou 12.04 Java JDK 6 ou 7 Android SDK Android 2.2 API 8 Eclipse Juno ADT Plugin Sqlite3 Sqliteman Inkscape Você pode estar se perguntando: ”Por que utilizar essa configuração?”. Bom, para começar um ambiente de desenvolvimento precisa ser estável, 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, então podemos utilizar a versão mais recente. O mesmo para o plugin ADT. Usaremos especificamente para os exemplos a seguir a versão 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 versões e compilar seus aplicativos para tablets, etc. 1
  • 12. 2 CAPÍTULO 1. PREPARANDO O AMBIENTE DE DESENVOLVIMENTO 1.2 Instalação A instalação do Java JDK 6 no Ubuntu 10.04 não é a mesma que no Ubuntu 12.04. Isso porque na época de lançamento do lucid, em 2010, a empresa que desenvolvia o Java era a Sun Microsystems, que tinha um canal nos repositórios 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. Discussões a parte, vamos ver as duas maneiras de instalar o Java. 1.2.1 Java JDK 6 A instalação do Java no Ubuntu 10.04 é bastante simples. Você apenas irá precisar habili- tar repositório de terceiros, ou Partner. Isso pode ser feito através do aplicativo Synaptic. No menu principal do Ubuntu clique em Sistema → Administração → Gerenciador de pacotes Synaptic. No menu do Synaptic clique em Configuração → Repositórios. Na aba Outro Software temos vários itens que representam repositórios. Marque os dois repositórios que terminam com partner. Feche e depois clique em Editar → Recarregar informações dos pacotes ou simplesmente Ctrl + R. Após a atualização dos pacotes existentes nos repositórios já é possível encontrar o Java JDK 6. No campo de Pesquisa rápida digite: sun-java6. Clique com botão direito no pacote sun-java6-jdk e selecione a opção Marcar para instalação. Depois basta Aplicar as mudanças. Para isso clique em Editar → Aplicar as alterações marcadas ou Ctrl + P. Para a instalação no Ubuntu 12.04 temos que habilitar um repositório de terceiros, também conhecido como PPA (Personal Package Archives). Abra um terminal e execute os passos a seguir para adicionar um repositório 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 não está familiarizado com o ambiente Linux vamos a uma pequena explica- ção. Nos comandos acima aparecem dois caracteres que não devem ser escritos mas que representam algo importante no âmbito dos comandos, são eles $ e #. Estes caracteres indicam qual o nível do usuário; $ significa usuário comum, # representa super usuário (root). No comando sudo su é onde trocamos de usuário comum para super usuário. Neste momento você terá que entrar com sua senha de login. Java JDK 7 Segundo a página de Requerimentos do Sistema (http://developer.android.com/sdk/ requirements.html) do site oficial do Android, é necessário uso do Java 6. Caso você queira utilizar o Java 7, você terá que configurar seu projeto Android para ser compilado com suporte a versão 6.
  • 13. 1.2. INSTALAÇÃO 3 A instalação 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 Após criar o projeto clique com botão 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 nível de compilação 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 instalação é feita apenas colocando o SDK em um diretório do sistema. Existem 2 bons locais para abrigar bibliotecas no Linux, são 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 diretório 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ê atenção ao uso do comando ln. Ele é responsável por criar links simbólicos. Isso é muito útil quando se instala um aplicativo ou biblioteca, pois proporciona atualização sem que outros ajustes sejam feitos. Neste caso basta linkar outra vez e pronto. Note que no último comando temos um link simbólico para o diretório /usr/local/bin. É nele que colocamos os executáveis globais, ou seja, que são vistos a partir de qualquer outro diretório. Agora saindo do modo root e usando seu próprio usuário instalaremos a API. 1.2.3 Android 2.2 API 8 Ainda no terminal, agora como usuário comum, vamos abrir o aplicativo que instala qual- quer uma das API disponibilizadas pelo Android. $ android
  • 14. 4 CAPÍTULO 1. PREPARANDO O AMBIENTE DE DESENVOLVIMENTO O aplicativo Android SDK and AVD Manager irá aparecer. Clique em Avaliable packages e procure pela versão 2.2 API 8 do Android. Selecione e clique em Install Selected. Após o download você pode verificar a versão 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 versões 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 versão. Assim, caso você tenha que testar seu código em outras versões você poderá saber qual emulador utilizar. Por exemplo use android-2.2. Em Target escolha a versão, neste caso Android 2.2 - API Level 8. Pronto, apenas clique em Create AVD. Dicas A opção Skin indica qual a resolução da tela do aparelho. Como não é possível redimen- sionar a janela, em alguns monitores a janela fica maior que a tela do seu monitor. A opção Snapshot quando habilitada, serve para salvar o estado do emulador. Isso faz com que da segunda inicialização em diante se torne mais rápida. A opção SD Card é ideal caso sua aplicação necessite guardar dados como fotos, arqui- vos. O AVD irá reservar um espaço 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 de- senvolvimento de aplicativos para o Android a versão Eclipse IDE for Java Developers é ideal. Mas se você tiver interesse em aplicativos Java para Web a opção é baixar a versão Eclipse IDE for Java EE Developers. Em todo caso as duas vão servir para o desenvolvimento, pois ambas vem com suporte a Java. O Eclipse não 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 botão direiro do mouse no menu principal e escolhendo a opção 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 visível a todos os usuários. 1.2.6 Plugin ADT Para a instalação 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 confirmação sobre os itens
  • 15. 1.2. INSTALAÇÃO 5 a serem instalados, clique em Next. Agora basta aceitar os termos de uso e clicar em Finish. Após o download e a instalação, 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ê não conheça mas que sempre precisou. Configurando o ADT Agora que o plugin foi instalado temos que dizer ao Eclipse onde nós 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 diretório do SDK, caso não lembre, ele está em /usr/local/lib/android-sdk. Clique em Apply na parte inferior direita para atualizar a lista de API’s disponíveis. Caso você tenha mais dúvidas dê uma olhada na página oficial de instalação 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 diretório 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 versão mínima é a API 8. Clique em Next. Na versão do ADT para o Eclipse Juno, uma novidade apareceu. É possível criar o ícone lançador logo ao criar o aplicativo. Selecione da maneira que achar melhor e clique em Next. Depois clique em Finish. Após isso clique com botão direito do mouse no projeto recém criado, e Run As → Android Application. Se tudo tiver dado certo é possível ver no emulador sua primeira aplicação rodando. Dicas Uma vez que você abriu o emulador não o feche. Você irá notar que ao abrir pela primeira vez ele leva um tempo para isso. Neste caso ao atualizar o código-fonte apenas rode o aplicativo novamente. O plugin ADT fará com que o aplicativo seja reinstalado no emulador. Faça o teste com alguns atalhos básicos: Alt + Enter Maximiza o emulador. Ideal para demostrações. Ctrl + F11 Muda a orientação do emulador, retrato ou paisagem. F8 Liga/desliga a rede. Outro elemento essencial é o LogCat. Ele faz parte do ADT e é responsável por mostrar as mensagens de log do emulador. Caso você encontre problemas com seu código o LogCat será seu melhor aliado. Para acessá-lo no Eclipse clique no menu Window → Show View → Other..., clique em Android → LogCat.
  • 16. 6 CAPÍTULO 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 fácil configuração e, acima de tudo, livre. Para a instalação, abra um terminal como root e: $ sudo su # apt-get install sqlite3 Após a instalação é possível utilizar o Sqlite via linha de comando. Faça logoff do usuário root e faça 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 página oficial do projeto: http://www.sqlite.org/. Tipos de dados Utilize a tabela abaixo para criar suas tabelas futuramente. Nome Descrição INTEGER valores inteiros, positivos ou negativos. Podem variar de 1 a 8 bytes. REAL valores reais ou decimais. TEXT usado para armazenar valores, não-limitado. Suporta várias codifica- ções, por exemplo UTF-8. BLOB objetos binários tais como imagens, arquivos de texto, etc. Também possui tamanho não-limitado. NULL representa falta de informação. Tabela 1.1: Tipos de dados do Sqlite 1.2.8 Sqliteman Para uma gerência mais produtiva usaremos o Sqliteman para acessar e modificar bancos de dados. A instalação é feita via linha de comando. Abra um terminal e: $ sudo su # apt-get install sqliteman
  • 17. 1.2. INSTALAÇÃO 7 Depois de instalado, acesse o aplicativo do menu principal do Ubuntu em Aplicativos → Escritório → Sqliteman. Faça alguns testes criando bancos de dados, depois crie algumas tabelas. Ele possui assistentes que irão auxiliar nos primeiros momentos. Por exemplo, crie uma base de dados e depois clique com o botão direito do mouse em Tables. Utilize o assistente e veja como é simples criar tabelas no sqlite. 1 -- Distribuições Linux 2 3 CREATE TABLE distros ( 4 _id INTEGER PRIMARY KEY, 5 nome TEXT NOT NULL, 6 interface TEXT NOT NULL DEFAULT ’Gnome3’ , 7 deriva_de INTEGER REFERENCES distros(_id) 8 ); 9 10 INSERT INTO distros VALUES (1, ’Debian’ , ’Gnome3’ , NULL); 11 INSERT INTO distros VALUES (2, ’Ubuntu’ , ’Unity’ , 1); 12 INSERT INTO distros VALUES (3, ’Linux Mint’ , ’Mate’ , 2); 13 INSERT INTO distros VALUES (4, ’Fedora’ , ’KDE’ , NULL); 14 INSERT INTO distros VALUES (5, ’Slackware’ , ’KDE’ , NULL); 15 INSERT INTO distros VALUES (6, ’Slax’ , ’KDE’ , 5); 16 INSERT INTO distros VALUES (7, ’Ubuntu Studio’ , ’XFCE’ , 2); 17 INSERT INTO distros VALUES (8, ’kUbuntu’ , ’KDE’ , 2); 18 INSERT INTO distros VALUES (9, ’xUbuntu’ , ’XFCE’ , 2); Código-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 número de distros que derivam de uma outra original. Veja: 1 SELECT d._id, d.nome, d.interface, 2 ( 3 SELECT SUM( CASE WHEN aux.deriva_de = d._id THEN 1 ELSE 0 END ) 4 FROM distros aux 5 ) AS num_derivadas 6 FROM distros d Código-fonte 2: Exemplo de query com subquery [exemplo-bd.sql] Mais informações 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 navegação, identidade visual, entre outras coisas.
  • 18. 8 CAPÍTULO 1. PREPARANDO O AMBIENTE DE DESENVOLVIMENTO A instalação é 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 página http://developer.android.com/design/style/iconography.html.
  • 19. Capítulo 2 Exemplo prático 2.1 Primeira aplicação - 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 aplicação, mapeia as Activity’s, entre outras configura- ções. Ao finalizar a criação do projeto, inicialmente este arquivo deverá conter o seguinte conteúdo: 1 <?xml version="1.0" encoding="UTF-8"?> 2 <manifest xmlns:android= "http://schemas.android.com/apk/res/android" 3 package= "contatos.app" 4 android:versionCode= "1" 5 android:versionName= "1.0" > 6 <uses-sdk android:minSdkVersion= "8" android:targetSdkVersion= "8" /> 7 <application android:icon= "@drawable/icon" android:label= "@string/app_name" > 8 <activity android:name= ".MainActivity" android:label= "@string/app_name" > 9 <intent-filter> 10 <action android:name= "android.intent.action.MAIN" /> 11 <category android:name= "android.intent.category.LAUNCHER" /> 12 </intent-filter> 13 </activity> 14 </application> 15 </manifest> Código-fonte 3: Projeto inicial [AndroidManifest.xml] 9
  • 20. 10 CAPÍTULO 2. EXEMPLO PRÁTICO 2.1.2 Activity Não existe método main visível ao programador no Android. Ao invés disso temos Activity’s. Para que o Android saiba qual ele deve iniciar primeiro utilizamos um intent-filter como visto no trecho de código acima da linha 09 a 12 . Para nossa primeira Activity criaremos uma lista de contatos e um menu para criação de um novo contato. Para construir o layout inicial de nossa aplicação precisamos editar o arquivo main.xml localizado em res/layout. 1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android= "http://schemas.android.com/apk/res/android" 3 android:orientation= "vertical" 4 android:layout_width= "fill_parent" 5 android:layout_height= "fill_parent" > 6 <ListView 7 android:id= "@+id/lv_contatos" 8 android:layout_width= "fill_parent" 9 android:layout_height= "wrap_content" /> 10 </LinearLayout> Código-fonte 4: Layout principal [res/layout/main.xml] Deste momento em diante tenha em mente que os arquivos xml aqui descritos são apenas para você poder comparar e ver se não esqueceu de nada. Todos os layout’s 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 gráfico basta utilizar a aba inferior esquerda. Por fim, temos o menu. Clique com o botão direito do mouse em seu projeto e New → Other... ou Ctrl + N. Procure por Android XML File. Em Resource Type escolha a opção Menu. Chame-o de main menu.xml. ¯ 1 <?xml version="1.0" encoding="UTF-8"?> 2 <menu xmlns:android= "http://schemas.android.com/apk/res/android" > 3 <item 4 android:id= "@+id/menu_add" 5 android:title= "Novo" 6 android:icon= "@android:drawable/ic_menu_add" /> 7 </menu> Código-fonte 5: Menu principal [res/menu/main menu.xml] ¯ Pronto, já temos nosso layout. Compile o projeto e vamos a próxima iteração.
  • 21. 2.1. PRIMEIRA APLICAÇÃO - CONTATOS 11 Convenção 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 diretório de instalação 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 convenção: Tipo de Recurso Prefixo Exemplo Ícones ic ic adicionar.png ¯ ¯ Launcher icons ic launcher ic launcher calendario.png ¯ ¯ ¯ ¯ Menu e Action Bar ic menu ic menu ajuda.png ¯ ¯ ¯ ¯ Status bar icons ic stat notify ic stat notify msg.png ¯ ¯ ¯ ¯ ¯ ¯ Tab icons ic tab ic tab recente.png ¯ ¯ ¯ ¯ Dialog icons ic dialog ic dialog info.png ¯ ¯ ¯ ¯ Tabela 2.1: Convenção para nome dos ícones Note que você não é obrigado a utilizar os prefixos citados acima, isto é apenas uma convenção. Veja mais detalhes em http://developer.android.com/guide/practices/ ui_guidelines/icon_design.html. Abra o arquivo MainActivity.java e vá ao método onCreate. Defina o layout como sendo nosso main.xml. Para isso adicione o layout main ao final do método: 1 @Override 2 public void onCreate(Bundle icicle) { 3 super.onCreate(icicle); 4 setContentView(R.layout.main); 5 } Código-fonte 6: Definir layout [MainActivity.java] Cuidado: no ambiente Android temos uma classe chamada R. Ela existe tanto na biblio- teca do Android como em cada projeto. Nesse caso faça o import da classe contatos.app.R. A classe android.R é utilizada em outras situações, onde códigos pré-prontos foram dis- ponibilizados pela equipe do Android. Agora precisamos sobrescrever os métodos onCreateOptionsMenu e onOptionsItemSelected. Eles irão criar o menu a partir de nosso layout e notificar quando os itens do menu forem pressionados, respectivamente. Vamos ao código:
  • 22. 12 CAPÍTULO 2. EXEMPLO PRÁTICO 1 @Override 2 public boolean onCreateOptionsMenu(Menu menu) { 3 new MenuInflater(this).inflate(R.menu.main_menu, menu); 4 return super.onCreateOptionsMenu(menu); 5 } 6 7 @Override 8 public boolean onOptionsItemSelected(MenuItem item) { 9 if (item.getItemId() == R.id.menu_add) { 10 irParaSalvar(); 11 return true; 12 } 13 return super.onOptionsItemSelected(item); 14 } 15 16 private void irParaSalvar() { 17 // não implementado ainda ... 18 } Código-fonte 7: Criando o menu [MainActivity.java] 2.1.3 Formulários Agora vamos criar nosso formulário para criação e edição de contatos. Começaremos pelo layout. Crie um arquivo xml em res/layout chamado salvar.xml. Existem alguns pontos importantes para este trecho de código. Começando 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 possível, respeitando o tamanho mínimo das outras células. Para visualizar as mudanças você pode tentar usar outros valores como 0 tornando a primeira coluna maior que as demais, ou ainda * que fará com que todas as células tenham o mesmo tamanho.
  • 23. 2.1. PRIMEIRA APLICAÇÃO - CONTATOS 13 1 <?xml version="1.0" encoding="UTF-8"?> 2 <RelativeLayout 3 android:id= "@+id/widget31" 4 android:layout_width= "fill_parent" 5 android:layout_height= "fill_parent" 6 xmlns:android= "http://schemas.android.com/apk/res/android" > 7 <TableLayout 8 android:id= "@+id/widget32" 9 android:layout_width= "fill_parent" 10 android:layout_height= "wrap_content" 11 android:orientation= "vertical" 12 android:stretchColumns= "1" > 13 <TableRow 14 android:id= "@+id/widget33" 15 android:layout_width= "fill_parent" 16 android:layout_height= "wrap_content" 17 android:orientation= "horizontal" > 18 <TextView 19 android:id= "@+id/textView1" 20 android:layout_width= "wrap_content" 21 android:layout_height= "wrap_content" 22 android:text= "Nome" ></TextView> 23 <EditText 24 android:id= "@+id/et_nome" 25 android:layout_width= "wrap_content" 26 android:layout_height= "wrap_content" ></EditText> 27 </TableRow> 28 <!-- faça mais duas TableRow’s contendo o Telefone e E-mail --> 29 <Button 30 android:id= "@+id/bt_salvar" 31 android:text= "Salvar" 32 android:layout_height= "wrap_content" 33 android:layout_width= "fill_parent" ></Button> 34 </TableLayout> 35 </RelativeLayout> Código-fonte 8: Formulário 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 constru- tores recebe como parâmetros a instância 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 método irParaSalvar da classe MainActivity:
  • 24. 14 CAPÍTULO 2. EXEMPLO PRÁTICO 1 private void irParaSalvar() { 2 Intent intent = new Intent(MainActivity.this, SaveActivity.class); 3 startActivity(intent); 4 } Código-fonte 9: Mudando de Activity [MainActivity.java] Veremos agora como manipular EditText’s, que representam os campos de entrada de dados. Abra o SalvarActivity e adicione o método carregar e crie atributos para guardar os EditText’s: 1 private EditText etNome, etFone, etEmail; 2 /* ... */ 3 4 @Override 5 public void onCreate(Bundle icicle) { 6 super.onCreate(icicle); 7 setContentView(R.layout.salvar); 8 carregar(); 9 } 10 11 private void carregar() { 12 etNome = (EditText) findViewById(R.id.et_nome); 13 etTefone = (EditText) findViewById(R.id.et_telefone); 14 etEmail = (EditText) findViewById(R.id.et_email); 15 } Código-fonte 10: Utilizando EditText’s [SalvarActivity.java] Para que a Activity funcione precisamos mapeá-la no arquivo AndroidManifest.xml. Adicione o conteúdo abaixo entre as tags application: 1 <activity android:name= ".view.SalvarActivity" ></activity> Código-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 aplicação Precisamos de um helper para fazer acesso ao banco de dados. O Android provê suporte a bancos de dados Sqlite por padrão. Qualquer banco de dados que você criar será acessível pelo nome por qualquer classe na sua aplicação, mas não 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 graças aos métodos getReadableDatabase() e getWritableDatabase(), respectivamente.
  • 25. 2.1. PRIMEIRA APLICAÇÃO - CONTATOS 15 A princípio temos que criar um construtor passando como parâmetros o nome do banco de dados e a versão da DDL (Data Definition Language). Logo em seguida precisamos implementar os métodos onCreate, no qual iremos criar as tabelas e onUpdate, caso tenhamos que alterar alguma tabela. 1 package contatos.app.model; 2 3 import android.content.Context; 4 import android.database.sqlite.SQLiteDatabase; 5 import android.database.sqlite.SQLiteOpenHelper; 6 7 public class ContatoHelper extends SQLiteOpenHelper { 8 9 private static final String DATABASE_NAME = "contatos.db" ; 10 private static final int VERSION = 1; 11 12 public ContatoHelper(Context context) { 13 super(context, DATABASE_NAME, null, VERSION); 14 } 15 16 @Override 17 public void onCreate(SQLiteDatabase db) { 18 db.execSQL( "CREATE TABLE contato (_id INTEGER PRIMARY KEY AUTOINCREMENT," 19 + " nome TEXT, fone TEXT, email TEXT);" ); 20 } 21 22 @Override 23 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 24 // nada a fazer por enquanto ... 25 } 26 } Código-fonte 12: Helper da aplicação [ContatoHelper.java] Para a iteração de criação de um novo contato, ainda em ContatoHelper vamos adi- cionar um método criar. Faça: 1 public void criar(ContentValues values) { 2 getWritableDatabase().insert( "contato" , "telefone" , values); 3 } Código-fonte 13: Criar novo contato [ContatoHelper.java] Agora temos que fazer a chamada do método criar da classe ContatoHelper em SalvarActivity. Para isso temos que criar uma instância de ContatoHelper, adicionar o botão salvar e adicionar um Listener de click (faça o import da classe android.view.View.OnClickListener). Vamos ao código:
  • 26. 16 CAPÍTULO 2. EXEMPLO PRÁTICO 1 /* ... */ 2 private ContatoHelper helper; 3 private Button btSalvar; 4 5 @Override 6 public void onCreate(Bundle icicle) { 7 /* ... */ 8 helper = new ContatoHelper(this); 9 carregar(); 10 ir(); 11 /* ... */ 12 } 13 14 private void carregar() { 15 /* ... */ 16 btSalvar = (Button) findViewById(R.id.bt_salvar); 17 } 18 19 private void ir() { 20 btSalvar.setOnClickListener(new OnClickListener() { 21 22 public void onClick(View view) { 23 ContentValues values = new ContentValues(); 24 values.put( "nome" , etNome.getText().toString()); 25 values.put( "telefone" , etTefone.getText().toString()); 26 values.put( "email" , etEmail.getText().toString()); 27 helper.criar(values); 28 finish(); 29 } 30 }); 31 } 32 33 @Override 34 protected void onDestroy() { 35 super.onDestroy(); 36 helper.close(); 37 } Código-fonte 14: Fim da iteração criar contato [SalvarActivity.java] Com essa implementação já é possível salvar contatos na base de dados. 2.1.5 Mostrando os dados na View Após salvar os dados no banco, devemos ser capazes de obter tais informações e colocá- las em forma de Lista. Para isso criaremos um novo layout que será responsável por representar uma linha de nossa Lista. Essa linha deve ser semelhante a figura abaixo:
  • 27. 2.1. PRIMEIRA APLICAÇÃO - CONTATOS 17 Figura 2.1: Layout linha da Lista Para isso crie um arquivo chamado linha.xml em res/layout com o seguinte con- teúdo. 1 <?xml version="1.0" encoding="UTF-8"?> 2 <LinearLayout xmlns:android= "http://schemas.android.com/apk/res/android" 3 android:layout_width= "fill_parent" android:layout_height= "wrap_content" 4 android:orientation= "horizontal" > 5 <ImageView 6 android:id= "@+id/linha_icone" android:layout_width= "wrap_content" 7 android:layout_height= "fill_parent" android:src= "@drawable/ic_launcher" > 8 </ImageView> 9 <LinearLayout 10 android:layout_width= "fill_parent" android:layout_height= "wrap_content" 11 android:orientation= "vertical" > 12 <TextView 13 android:id= "@+id/linha_nome" android:layout_width= "fill_parent" 14 android:layout_height= "wrap_content" android:textStyle= "bold" 15 android:ellipsize= "end" ></TextView> 16 <TextView 17 android:id= "@+id/linha_fone" android:layout_width= "fill_parent" 18 android:layout_height= "wrap_content" ></TextView> 19 <TextView 20 android:id= "@+id/linha_email" android:layout_width= "fill_parent" 21 android:layout_height= "wrap_content" ></TextView> 22 </LinearLayout> 23 </LinearLayout> Código-fonte 15: Layout para cada linha da lista [res/layout/linha.xml] Note a possibilidade de aninhar o LinearLayout. Fazendo isso é possível 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 li- nha 14 , e o uso de reticências caso o nome seja maior que a tela usando android:ellipsize="end" na linha 15 .
  • 28. 18 CAPÍTULO 2. EXEMPLO PRÁTICO Agora vamos até ContatoHelper e adicionar o método listar. E também adiciona- remos métodos para facilitar a obtenção dos valores de cada atributo. 1 public Cursor listar() { 2 return getReadableDatabase() 3 .rawQuery( "SELECT _id, nome, fone, email FROM contato ORDER BY nome" , 4 null); 5 } 6 7 public String getNome(Cursor c) { 8 return c.getString(1); 9 } 10 11 public String getFone(Cursor c) { 12 return c.getString(2); 13 } 14 15 public String getEmail(Cursor c) { 16 return c.getString(3); 17 } Código-fonte 16: Listar contatos existentes [ContatoHelper.java] Os elementos de um Cursor são numerados iniciando de 0 (zero). Neste caso o 0 é a coluna id. Note que ela não 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 private static class ContatoHolder { 2 private TextView nome, fone, email = null; 3 4 public ContatoHolder(View linha) { 5 nome = (TextView) linha.findViewById(R.id.linha_nome); 6 fone = (TextView) linha.findViewById(R.id.linha_fone); 7 email = (TextView) linha.findViewById(R.id.linha_email); 8 } 9 10 public void popularForm(Cursor c, ContatoHelper helper) { 11 nome.setText(helper.getNome(c)); 12 fone.setText(helper.getFone(c)); 13 email.setText(helper.getEmail(c)); 14 } 15 } Código-fonte 17: Classe Holder [MainActivity.java]
  • 29. 2.1. PRIMEIRA APLICAÇÃO - 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á responsável por definir o layout de cada linha da Lista. Crie uma classe interna chamada ContatoAdapter. Iremos sobrescrever dois métodos, newView() e bindView(), que são responsáveis por inflar (inflate) uma nova linha e reciclar uma linha existente, respectivamente. 1 private ContatoHelper helper; 2 /* ... */ 3 4 private class ContatoAdapter extends CursorAdapter { 5 6 public ContatoAdapter(Cursor c) { 7 super(MainActivity.this, c); 8 } 9 10 @Override 11 public View newView(Context cntxt, Cursor cursor, ViewGroup vg) { 12 LayoutInflater inflater = getLayoutInflater(); 13 View linha = inflater.inflate(R.layout.linha, vg, false); 14 ContatoHolder holder = new ContatoHolder(linha); 15 linha.setTag(holder); 16 return linha; 17 } 18 19 @Override 20 public void bindView(View view, Context cntxt, Cursor cursor) { 21 ContatoHolder holder = (ContatoHolder) view.getTag(); 22 holder.popularForm(cursor, helper); 23 } 24 } Código-fonte 18: Classe Adapter [MainActivity.java] Com a introdução do Helper teremos que criar uma instância da classe Cursor para popular nossa ListView. Vamos ao código-fonte:
  • 30. 20 CAPÍTULO 2. EXEMPLO PRÁTICO 1 /* ... */ 2 private Cursor model = null; 3 private ContatoAdapter adapter = null; 4 private ListView listView = null; 5 6 @Override 7 public void onCreate(Bundle icicle) { 8 /* ... */ 9 helper = new ContatoHelper(this); 10 carregar(); 11 } 12 13 private void carregar() { 14 listView = (ListView) findViewById(R.id.lv_contatos); 15 model = helper.listar(); 16 startManagingCursor(model); 17 adapter = new ContatoAdapter(model); 18 listView.setAdapter(adapter); 19 } 20 21 @Override 22 protected void onDestroy() { 23 super.onDestroy(); 24 model.close(); 25 helper.close(); 26 } Código-fonte 19: Popular ListView [MainActivity.java] Nunca esquecendo de fechar o helper ao sair, pois assim garantimos que a conexão com o banco será fechada. 2.1.6 Editando dados existentes Para a edição de informações usaremos o mesmo Activity do criar, ou seja, SalvarActivity. Para isso precisamos passar um parâmetro para o Activity. Usaremos então um método do Intent que é responsável por isso, putExtra(chave, valor). Para uma passagem de parâmetros segura devemos usar um namespace para que não colida com nenhum nome já utilizado pelo Android. Assim, vamos criar uma variável estática do tipo String. Isso acontecerá quando o usuário pressionar a linha que ele deseja editar. Podemos fazer isso utilizando a interface OnItemClickListener. Vamos incrementar também o método irParaSalvar passando o parâmetro caso haja um. Vamos ao código:
  • 31. 2.1. PRIMEIRA APLICAÇÃO - CONTATOS 21 1 /* ... */ 2 public static final String _ID = "contatos.app._ID" ; 3 4 @Override 5 public void onCreate(Bundle icicle) { 6 /* ... */ 7 configurar(); 8 } 9 10 private void irParaSalvar() { 11 irParaSalvar(null); 12 } 13 14 private void irParaSalvar(String id) { 15 Intent intent = new Intent(MainActivity.this, SalvarActivity.class); 16 if (id != null) { 17 intent.putExtra(_ID, id); 18 } 19 startActivity(intent); 20 } 21 22 private void configurar() { 23 listView.setOnItemClickListener(new OnItemClickListener() { 24 public void onItemClick(AdapterView<?> parent, View view, 25 int position, long id) { 26 irParaSalvar(String.valueOf(id)); 27 } 28 }); 29 } Código-fonte 20: Passagem de parâmetros [MainActivity.java] Agora é hora de tratar nosso parâmetro no SalvarActivity. Caso haja um parâmetro precisamos obter os dados existentes no banco de dados para então editá-lo. Neste caso precisaremos de mais dois métodos em ContatoHelper, que são ler e atualizar. 1 public Cursor ler(String id) { 2 return getReadableDatabase().rawQuery( "SELECT _id, nome, telefone, " + 3 "email FROM contato WHERE _id = ?" , new String[]{id}); 4 } 5 6 public void atualizar(String id, ContentValues values) { 7 getWritableDatabase().update( "contato" , values, "_id = ?" , new String[]{id}); 8 } Código-fonte 21: Ler e atualizar dados existentes [ContatoHelper.java]
  • 32. 22 CAPÍTULO 2. EXEMPLO PRÁTICO O próximo passo é tratar no SalvarActivity caso o parâmetro tenha sido enviado ou não. Caso positivo devemos carregar os dados existentes no banco de dados e depois atualizá-los. 1 /* ... */ 2 private String contatoId = null; 3 4 private void carregar() { 5 /* ... */ 6 contatoId = getIntent().getStringExtra(MainActivity._ID); 7 if (contatoId != null) { 8 carregarContato(); 9 } 10 } 11 12 private void carregarContato() { 13 Cursor cursor = helper.ler(contatoId); 14 cursor.moveToFirst(); 15 etNome.setText(helper.getNome(cursor)); 16 etFone.setText(helper.getFone(cursor)); 17 etEmail.setText(helper.getEmail(cursor)); 18 cursor.close(); 19 } 20 21 private void ir() { 22 btSalvar.setOnClickListener(new OnClickListener() { 23 public void onClick(View view) { 24 ContentValues values = new ContentValues(); 25 values.put( "nome" , etNome.getText().toString()); 26 values.put( "telefone" , etTefone.getText().toString()); 27 values.put( "email" , etEmail.getText().toString()); 28 if (contatoId == null) { 29 helper.criar(values); 30 } else { 31 helper.atualizar(contatoId, values); 32 } 33 finish(); 34 } 35 }); 36 } Código-fonte 22: Usando Activity para criar ou atualizar [SalvarActivity.java] Com isso encerramos um CRUD básico, mas completo. A seguir temos implementa- ções mais específicas que irão tornar nossa aplicação mais profissional.
  • 33. Capítulo 3 Livro de Receitas 3.1 Mostrando Diálogos No Android, podemos criar diálogos no Activity mostrando opções ao usuário, como por exemplo, escolher itens de uma lista, ou responder sim ou não a uma ação, etc. Vamos incrementar algumas partes de nosso código e tentar encaixar algumas funcio- nalidades relacionadas. 3.1.1 Editar/Excluir ao clicar e segurar na ListView Vamos implementar uma ação comum no mundo Android, que é a seguinte: ao clicar e segurar num item da ListView, ele mostra opções editar e excluir, por exemplo. Isto pode ser feito facilmente usando AlertDialog.Builder, uma classe com métodos pré-prontos para serem usados por você. Neste exemplo, precisaremos editar ContatoHelper e adicionar um método para de- letar um contato, editar nosso MainActivity no método configurar e adicionar um Listener que ao clicar e segurar num item da ListView um método é acionado. Vamos a implementação: 1 public int deletar(String id) { 2 String whereClause = "_id = ?" ; 3 String[] whereArgs = {id}; 4 return getWritableDatabase().delete( "contato" , whereClause, whereArgs); 5 } Código-fonte 23: Deletar dados existentes [ContatoHelper.java] 23
  • 34. 24 CAPÍTULO 3. LIVRO DE RECEITAS 1 /* ... */ 2 private void configurar() { 3 /* ... */ 4 listView.setOnItemLongClickListener(new OnItemLongClickListener() { 5 public boolean onItemLongClick(AdapterView<?> parent, View view, 6 int position, final long id) { 7 final String[] itens = { "Editar" , "Deletar" }; 8 AlertDialog.Builder dialogo = 9 new AlertDialog.Builder(MainActivity.this); 10 dialogo.setTitle( "Opções" ); 11 dialogo.setItems(itens, new OnClickListener() { 12 public void onClick(DialogInterface dialog, int which) { 13 switch (which) { 14 case 0: // editar 15 irParaSalvar(String.valueOf(id)); 16 break; 17 case 1: // deletar 18 int linhasAfetadas = helper.deletar(String.valueOf(id)); 19 if (linhasAfetadas > 0) { 20 exibirMensagem( "Contatos deletado com sucesso." ); 21 carregar(); 22 } else { 23 exibirMensagem( "Falha ao deletar contato." ); 24 } 25 break; 26 } 27 } 28 }); 29 dialogo.show(); 30 return true; 31 } 32 }); 33 } 34 35 private void exibirMensagem(String mensagem) { 36 Toast.makeText(this, mensagem, Toast.LENGTH_LONG).show(); 37 } Código-fonte 24: Adicionar Listener para click longo [MainActivity.java] Note a necessidade de um novo método em MainActivity, o exibirMensagem. Ele é bastante útil quando se quer exibir uma mensagem rapidamente e depois ela suma. Para isso usamos a classe Toast.
  • 35. 3.1. MOSTRANDO DIÁLOGOS 25 Interface como parâmetro de um método Você já deve ter notado o uso de interface’s como parâmetro dos métodos, por exemplo na linha 4 e 11 do código acima. Essa prática obriga ao programador implementar a classe na passagem dos parâmetros. Essa ideia vem de algumas linguagens de programação que possuem funções como parâmetros para outras funções. Como o Java não suporta essa característica, a solução veio em forma de uma interface, a qual o programador é obrigado a implementar seus métodos. Com isso o método que recebe a interface como parâmetro sabe exatamente o que ela tem disponível. A partir dessa observação, podemos justificar o uso da palavra reservada final em alguns parâmetros dos métodos acima. Isso acontece porque alguns parâmetros são utili- zados dentro da implementação das interface’s. Caso haja a necessidade de utilizar uma implementação em outra classe você pode criar uma classe que implementa uma interface, por exemplo a interface OnItemLongClickListener. Daí para a passagem do parâmetro apenas crie uma instância da classe. Por exemplo, supo- nha que você tenha uma classe chamada OpcoesContato que implementa OnItemLongClickListener, nesse caso a linha 4 se tornaria: listView.setOnItemLongClickListener(new OpcoesContato()); 3.1.2 Diálogo de confirmação Deletar dados é uma ação que deve ser feita com cuidado, então sempre é bom confirmar com o usuário 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 botões Sim ou Não. Ainda em MainActivity criaremos um outro AlertDialog.Builder no momento que o usuário clicar em Deletar. Segue o trecho:
  • 36. 26 CAPÍTULO 3. LIVRO DE RECEITAS 1 /* ... */ 2 private void configurar() { 3 /* ... */ 4 listView.setOnItemLongClickListener(new OnItemLongClickListener() { 5 public boolean onItemLongClick(AdapterView<?> parent, View view, 6 int position, final long id) { 7 /* ... */ 8 dialogo.setItems(itens, new OnClickListener() { 9 public void onClick(DialogInterface dialog, int which) { 10 switch (which) { 11 case 0: // editar 12 irParaSalvar(String.valueOf(id)); 13 break; 14 case 1: // deletar 15 AlertDialog.Builder confirmacao = 16 new AlertDialog.Builder(MainActivity.this); 17 confirmacao.setTitle( "Deletar" ); 18 confirmacao.setMessage( "Deseja realmente deletar este contato?" ); 19 confirmacao.setPositiveButton( "Sim" , new OnClickListener() { 20 public void onClick(DialogInterface dialog, int which) { 21 int linhasAfetadas = helper.deletar(String.valueOf(id)); 22 if (linhasAfetadas > 0) { 23 exibirMensagem( "Contatos deletado com sucesso." ); 24 carregar(); 25 } else { 26 exibirMensagem( "Falha ao deletar contato." ); 27 } 28 } 29 }); 30 confirmacao.setNegativeButton( "Não" , null); 31 confirmacao.show(); 32 break; 33 } 34 } 35 }); 36 dialogo.show(); 37 return true; 38 } 39 }); 40 } Código-fonte 25: Diálogo de confirmação ao deletar contato [MainActivity.java] Pronto, agora o trecho que deleta o contato foi movido para dentro do Listener do botão Sim. No botão Não passamos null no Listener, pois caso seja a opção escolhida apenas fazemos nada. Você pode se quiser criar um Listener e mostrar uma mensagem do tipo, Cancelado pelo usuário, para isso usando o método exibirMensagem.
  • 37. 3.1. MOSTRANDO DIÁLOGOS 27 3.1.3 Entrada de diferentes tipos de dados O Android foi desenvolvido com muitos recursos pré-prontos para facilitar o desenvolvi- mento de aplicações. Um recurso bastante útil é a distinção dos dados que irão ser inseridos nos TextView’s. Com isso o teclado virtual do cliente se adapta ao tipo de dado que será inserido. No nosso caso faremos distinção do campo telefone, onde apenas números e hífens (-) podem ser inseridos, e o campo e-mail onde a presença do arroba (@) e pontos (.) são elementos essenciais. Vejamos alguns valores aceitos pelo inputType: Para textos: text textCapCharacters textMultiLine textUri textEmailAddress textPersonName textPassword textVisiblePassword Para números: 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:
  • 38. 28 CAPÍTULO 3. LIVRO DE RECEITAS 1 <!-- ... --> 2 <TableRow android:id= "@+id/tableRow2" 3 android:layout_width= "wrap_content" 4 android:layout_height= "wrap_content" > 5 <TextView android:id= "@+id/textView2" 6 android:layout_width= "wrap_content" 7 android:layout_height= "wrap_content" 8 android:text= "Telefone:" ></TextView> 9 <EditText android:layout_width= "wrap_content" 10 android:layout_height= "wrap_content" 11 android:id= "@+id/et_telefone" 12 android:inputType= "phone" ></EditText> 13 </TableRow> 14 <TableRow android:id= "@+id/tableRow3" 15 android:layout_width= "wrap_content" 16 android:layout_height= "wrap_content" > 17 <TextView android:id= "@+id/textView3" 18 android:layout_width= "wrap_content" 19 android:layout_height= "wrap_content" 20 android:text= "E-mail:" ></TextView> 21 <EditText android:layout_width= "wrap_content" 22 android:layout_height= "wrap_content" 23 android:id= "@+id/et_email" 24 android:inputType= "textEmailAddress" ></EditText> 25 </TableRow> 26 <!-- ... --> Código-fonte 26: Distinção de dados [res/layout/salvar.xml] 3.1.4 Validação de dados Mesmo configurando um inputType para seu TextView pode não 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 estão os objetos Patterns.EMAIL ADDRESS e Patterns.PHONE. Com ¯ eles podemos validar de forma simples os dados inseridos em nosso formulário. Em nosso SalvarActivity adicionaremos um método validar passando como pa- râmetro um ContentValues. Copie o método exibirMensagem da classe MainActivity para mostrar uma mensagem caso alguma validação seja falsa. OBS: Para um melhor reuso crie uma classe abstrata que implementa o método exibirMensagem e que extenda de Activity e faça com que seus Activity’s herdem dela. É uma boa prá- tica. Vamos ao trecho de código:
  • 39. 3.1. MOSTRANDO DIÁLOGOS 29 1 /* ... */ 2 private void ir() { 3 btSalvar.setOnClickListener(new OnClickListener() { 4 5 public void onClick(View view) { 6 ContentValues values = new ContentValues(); 7 values.put( "nome" , etNome.getText().toString()); 8 values.put( "telefone" , etTefone.getText().toString()); 9 values.put( "email" , etEmail.getText().toString()); 10 if (validar(values)) { 11 if (contatoId == null) { 12 helper.criar(values); 13 } else { 14 helper.atualizar(contatoId, values); 15 } 16 finish(); 17 } 18 } 19 }); 20 } 21 22 private boolean validar(ContentValues values) { 23 if (!Patterns.PHONE.matcher(values.getAsString( "telefone" )).matches()) { 24 exibirMensagem( "Telefone não é válido." ); 25 return false; 26 } 27 28 if (!Patterns.EMAIL_ADDRESS.matcher(values.getAsString( "email" )).matches()) { 29 exibirMensagem( "E-mail não é válido." ); 30 return false; 31 } 32 return true; 33 } 34 35 private void exibirMensagem(String mensagem) { 36 Toast.makeText(this, mensagem, Toast.LENGTH_LONG).show(); 37 } 38 /* ... */ Código-fonte 27: Validação dos dados [SalvarActivity.java] 3.1.5 Fazendo uma ligação Já que estamos fazendo uma lista de contatos nada melhor que usar o número do telefone dos contatos inseridos para realizar chamadas. Para isso vamos aprender um pouco sobre Permissões. Permissões no Android são definidas no AndroidManifest.xml. Ao instalar seu aplica-
  • 40. 30 CAPÍTULO 3. LIVRO DE RECEITAS tivo, o usuário saberá quais as permissões que o seu aplicativo necessita para ser executado. Por padrão, o Android traz uma série de permissões que auxiliam seu aplicativo a se comunicar com o aparelho. Abaixo alguns exemplos: Verificação ACCESS NETWORK STATE ¯ ¯ ACCESS WIFI STATE ¯ ¯ BATTERY STATS ¯ Comunicação 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 <?xml version="1.0" encoding="UTF-8"?> 2 <manifest xmlns:android= "http://schemas.android.com/apk/res/android" 3 package= "contatos.app" 4 android:versionCode= "1" 5 android:versionName= "1.0" > 6 <uses-permission android:name= "android.permission.CALL_PHONE" > 7 </uses-permission> 8 <!-- ... --> 9 </manifest> Código-fonte 28: Permissão de realizar chamadas [AndroidManifest.xml] Agora vamos adicionar um item ao diálogo que aparece ao clicar e segurar um item da ListView. Ele servirá para implementarmos o trecho que realiza a chamada. Vamos a ele:
  • 41. 3.1. MOSTRANDO DIÁLOGOS 31 1 /* ... */ 2 private void configurar() { 3 listView.setOnItemLongClickListener(new OnItemLongClickListener() { 4 public boolean onItemLongClick(AdapterView<?> parent, View view, 5 final int position, final long id) { 6 final String[] itens = { "Editar" , "Deletar" , "Chamar" }; 7 /* ... */ 8 dialogo.setItems(itens, new OnClickListener() { 9 public void onClick(DialogInterface dialog, int which) { 10 switch (which) { 11 /* ... */ 12 case 2: // chamar 13 model.moveToPosition(position); 14 startActivity(new Intent(Intent.ACTION_CALL, 15 Uri.parse( "tel:" + helper.getTelefone(model)) 16 ) 17 ); 18 break; 19 } 20 } 21 }); 22 dialogo.show(); 23 return true; 24 } 25 }); 26 } Código-fonte 29: Item chamar no diálogo [MainActivity.java] Nesse trecho de código podemos ver o uso de Intent’s do prórpio Android, nesse caso o Intent.ACTION CALL (veja linha 14 ). Ele serve para chamar uma Activity ¯ que realize ligações. Atente apenas para um detalhe - esse Intent faz a chamada sem confirmação. Caso você queira que o usuário possa visualizar o número no discador use o Intent Intent.ACTION DIAL. Faça esse teste e veja a diferença entre os Intent’s. ¯ Veja mais detalhes em http://developer.android.com/reference/android/content/ Intent.html.
  • 42. 32 CAPÍTULO 3. LIVRO DE RECEITAS 3.1.6 Enviando e-mail Para envio de e-mail você pode simplesmente usar a aplicação de e-mail padrão do apare- lho. Seguindo o mesmo princípio do exemplo anterior vamos apenas inserir um trecho de código no método configurar da classe MainActivity: 1 /* ... */ 2 private void configurar() { 3 listView.setOnItemLongClickListener(new OnItemLongClickListener() { 4 public boolean onItemLongClick(AdapterView<?> parent, View view, 5 final int position, final long id) { 6 final String[] itens = { "Editar" , "Deletar" , "Chamar" , 7 "Enviar e-mail" }; 8 /* ... */ 9 dialogo.setItems(itens, new OnClickListener() { 10 public void onClick(DialogInterface dialog, int which) { 11 switch (which) { 12 /* ... */ 13 case 3: // enviar e-mail 14 model.moveToPosition(position); 15 Intent email = new Intent(Intent.ACTION_SEND); 16 email.setType( "plain/text" ); 17 email.putExtra(Intent.EXTRA_EMAIL, 18 new String[]{ helper.getEmail(model) }); 19 startActivity(Intent.createChooser(email, 20 "Enviar e-mail..." )); 21 break; 22 } 23 } 24 }); 25 dialogo.show(); 26 return true; 27 } 28 }); 29 } Código-fonte 30: Item enviar e-mail no diálogo [MainActivity.java] Ao testar no emulador você receberá a mensagem: No applications can perform this action. Traduzindo quer dizer que: Nenhuma aplicação pode executar esta ação. Em outras palavras, nenhum cliente de e-mail foi encontrado. 3.2 Internacionalização (i18n) 3.2.1 Forçando região para teste Para podermos testar as strings de i18n podemos forçar o Activity a utilizar uma determinada linguagem. Isso se dá por meio da classe Locale. Façamos um teste com o
  • 43. 3.3. UTILIZANDO AS PREFERÊNCIAS DO ANDROID 33 SalvarActivity inserindo o trecho de código abaixo no método onCreate. Vamos a ele: 1 /* ... */ 2 @Override 3 protected void onCreate(Bundle savedInstanceState) { 4 /* ... */ 5 forceLocale( "pt" , "BR" ); 6 carregar(); 7 ir(); 8 } 9 10 private void forceLocale(String language, String country) { 11 Locale locale = new Locale(language, country); 12 Locale.setDefault(locale); 13 Configuration configuration = new Configuration(); 14 configuration.locale = locale; 15 getBaseContext().getResources() 16 .updateConfiguration(configuration, 17 getBaseContext().getResources().getDisplayMetrics()); 18 } Código-fonte 31: Forçando região [SalvarActivity.java] Para visualizar a mudança crie strings no seu arquivo strings.xml. Substitua as strings Nome, Telefone, E-mail e Salvar pelos respectivos valores em inglês Name, Phone, E-mail e Save. Agora crie outro arquivo strings.xml dentro do diretório /res/values-pt-rBR e insira as mesmas strings citadas anteriormente, traduzindo cada valor. Faça testes comentando a chamada para a função forceLocale e veja as mudanças. 3.2.2 Forçando região pelo emulador A maneira mais rápida e prática de forçar a região é pelo próprio emulador. Vá até a lista de aplicativos e procure por Custom Locale. Depois pesquise por pt BR e caso não ¯ encontre clique em Add New Locale. Digite pt BR e clique em Add and Select. ¯ 3.3 Utilizando as Preferências do Android O Android já disponibiliza uma maneira de criar preferências de forma fácil. Para demons- trar implementaremos um exemplo bem amplo, que irá nos ajudar a entender ainda mais de Android. Para começar adicionaremos um nova coluna a nossa tabela contato cha- mada grupo. Depois adicionaremos um array de string’s ao nosso arquivo strings.xml e ainda vamos aprender a utilizar um Spinner, também conhecido como combo box. Por último, e não menos importante, usaremos as preferências para tornar padrão um valor de nosso Spinner.
  • 44. 34 CAPÍTULO 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 métodos onCreate e onUpgrade. Neste ponto será necessário o uso do método onUpgrade. Ele serve, como o nome sugere, para atualizar a DDL do banco de dados. Isso é útil quando seu cliente já possui uma versão do seu aplicativo instalada e ele quer apenas atualizar para uma nova versão. Também será necessário adicionar a coluna grupo nas queries. Abra a classe ContatoHelper em contatos.app.model e faça as modificações: 1 public class ContatoHelper extends SQLiteOpenHelper { 2 /* ... */ 3 private static final int VERSION = 2; 4 private static final String TAG = "ContatoHelper" ; 5 6 @Override 7 public void onCreate(SQLiteDatabase db) { 8 db.execSQL( "CREATE TABLE contato ( _id INTEGER PRIMARY KEY AUTOINCREMENT," + 9 "nome TEXT, telefone TEXT, email TEXT," + 10 // versao 2 11 "grupo INTEGER NOT NULL DEFAULT 0 );" ); 12 } 13 14 @Override 15 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 16 Log.w(TAG, "Atualizando banco de dados da versão " 17 + oldVersion + " para " + newVersion + "." ); 18 if (newVersion > oldVersion) { 19 switch (oldVersion) { 20 case 2: 21 try { 22 db.execSQL( "ALTER TABLE contato " + 23 "ADD COLUMN grupo INTEGER NOT NULL DEFAULT 0" ); 24 } catch (SQLException e) { 25 Log.e(TAG, "Erro ao executar SQL: " , e); 26 } 27 default: 28 Log.w(TAG, "Versão desconhecida: " + oldVersion + 29 ". Criando novo banco de dados." ); 30 db.execSQL( "DROP TABLE IF EXISTS contato" ); 31 onCreate(db); 32 } 33 } 34 } 35 } Código-fonte 32: Nova coluna grupo na base de dados [ContatoHelper.java]
  • 45. 3.3. UTILIZANDO AS PREFERÊNCIAS DO ANDROID 35 Vemos neste exemplo o uso da classe Log do pacote android.util. Ela possui apenas métodos estáticos, assim não precisamos instanciar, apenas faça a chamada dos métodos. Temos: Log.w() para mostrar warning’s, 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 public class ContatoHelper extends SQLiteOpenHelper { 2 /* ... */ 3 public Cursor listar() { 4 return getReadableDatabase() 5 .rawQuery( "SELECT _id, nome, telefone, email, grupo " + 6 "FROM contato ORDER BY nome" , null); 7 } 8 9 public int getGrupo(Cursor c) { 10 return c.getInt(4); 11 } 12 13 public Cursor ler(String id) { 14 String[] params = {id}; 15 return getReadableDatabase() 16 .rawQuery( "SELECT _id, nome, telefone, email, grupo " + 17 "FROM contato WHERE _id = ?" , params); 18 } 19 } Código-fonte 33: Modificação nas queries [ContatoHelper.java] 3.3.2 Array de Strings No arquivo de string’s do Android é possível criar vários recursos. Dentre eles temos Cor, Dimensão, 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 não seria necessário o uso de String Array’s.
  • 46. 36 CAPÍTULO 3. LIVRO DE RECEITAS 1 <?xml version="1.0" encoding="utf-8"?> 2 <resources> 3 <!-- ... --> 4 <string-array name= "array_grupos" > 5 <item>amigos</item> 6 <item>trabalho</item> 7 <item>conhecidos</item> 8 <item>família</item> 9 </string-array> 10 <string-array name= "index_array_grupos" > 11 <item>0</item><item>1</item> 12 <item>2</item><item>3</item> 13 </string-array> 14 </resources> Código-fonte 34: Array de Strings [strings.xml] 3.3.3 Spinner, diálogo de seleção O Spinner é ideal quando temos que escolher entre valores fixos, sejam eles estáticos ou dinâmicos. Nosso exemplo irá utilizar valores estáticos para popular o mesmo. Para isso utilizaremos o array grupos que criamos em res/values/strings.xml. Também ¯ veremos um exemplo de uso da classe android.R como visto em 2.1.2 em que é explicado a diferença 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 <TableRow 3 android:id= "@+id/tableRow4" 4 android:layout_width= "wrap_content" 5 android:layout_height= "wrap_content" > 6 7 <TextView 8 android:id= "@+id/textView4" 9 android:layout_width= "wrap_content" 10 android:layout_height= "wrap_content" 11 android:text= "Grupo:" /> 12 13 <Spinner 14 android:id= "@+id/sp_grupo" 15 android:layout_width= "wrap_content" 16 android:layout_height= "wrap_content" /> 17 </TableRow> 18 <!-- ... --> Código-fonte 35: Adicionando elemento Spinner [res/layout/salvar.xml]
  • 47. 3.3. UTILIZANDO AS PREFERÊNCIAS DO ANDROID 37 Agora já podemos carregar e popular o Spinner na classe SalvarActivity. 1 public class SalvarActivity extends Activity { 2 /* ... */ 3 private Spinner spGrupo = null; 4 5 private void carregar() { 6 /* ... */ 7 spGrupo = (Spinner) findViewById(R.id.sp_grupo); 8 ArrayAdapter<CharSequence> adapter = 9 ArrayAdapter.createFromResource(this, 10 R.array.array_grupos, android.R.layout.simple_spinner_item); 11 adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 12 spGrupo.setAdapter(adapter); 13 /* antes de verificar o parâmetro contatoId */ 14 } 15 16 private void carregarContato() { 17 spGrupo.setSelection(helper.getGrupo(c)); 18 c.close(); 19 } 20 21 private void ir() { 22 btSalvar.setOnClickListener(new View.OnClickListener() { 23 /* ... */ 24 contato.setGrupo(spGrupo.getSelectedItemPosition()); 25 /* antes de validar e salvar */ 26 } 27 } 28 } Código-fonte 36: Utilização de Spinner [SalvarActivity.java] Note a utilização 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 preferências do Android. Neste exemplo a usaremos para decidir qual grupo do array grupos aparecerá selecionado por padrão. A princípio é um exemplo ¯ bem simples, mas que pode ser ajustado para outras finalidades, o que importa realmente é a ideia. Para começar criaremos um layout em res/layout chamado preferencias.xml. No projeto clique com botão 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 opção PreferenceScreen, então
  • 48. 38 CAPÍTULO 3. LIVRO DE RECEITAS Finish. Utilizando a ferramenta ADT adicione um elemento ListPreference a PreferenceScreen. Defina os parâmetros necessários como mostra o código abaixo: 1 <?xml version="1.0" encoding="utf-8"?> 2 <PreferenceScreen xmlns:android= "http://schemas.android.com/apk/res/android" > 3 <ListPreference 4 android:summary= "Selecione o grupo padrão" 5 android:dialogTitle= "Escolha um Grupo" 6 android:entries= "@array/array_grupos" 7 android:entryValues= "@array/index_array_grupos" 8 android:key= "lista_grupos" 9 android:title= "Grupos" /> 10 </PreferenceScreen> Código-fonte 37: XML descrevendo layout de preferências [res/xml/preferencias.xml] Crie uma nova classe chamada EditarPreferencias em contatos.app.view her- dando de PreferenceActivity. Agora de uma maneira bem simples implementaremos essa classe. Veja: 1 package app.contatos.view; 2 3 import android.os.Bundle; 4 import android.preference.PreferenceActivity; 5 import app.contatos.R; 6 7 public class EditarPreferencias extends PreferenceActivity { 8 9 @Override 10 protected void onCreate(Bundle savedInstanceState) { 11 super.onCreate(savedInstanceState); 12 addPreferencesFromResource(R.xml.preferencias); 13 } 14 } Código-fonte 38: Activity para mostrar preferências [EditarPreferencias.java] Para chamar a nova Activity temos ainda que mapeá-la no AndroidManifest e criar um item no menu. 1 <activity android:name= ".view.EditarPreferencias" ></activity> Código-fonte 39: Mapeando Activity EditarPreferencias [AndroidManifest.xml]
  • 49. 3.3. UTILIZANDO AS PREFERÊNCIAS DO ANDROID 39 1 <?xml version="1.0" encoding="utf-8"?> 2 <menu xmlns:android= "http://schemas.android.com/apk/res/android" > 3 <!-- ... --> 4 <item 5 android:id= "@+id/menu_pref" 6 android:icon= "@android:drawable/ic_menu_preferences" 7 android:title= "Preferências" > 8 </item> 9 </menu> Código-fonte 40: Adicionar item Preferências ao menu principal [res/menu/main menu.xml] ¯ Agora que adicionamos um item ao menu, temos que capturar o evento quando o usuário o selecionar e direcioná-lo às Preferências. Isso deve ser feito em MainActivity. 1 /* ... */ 2 @Override 3 public boolean onOptionsItemSelected(MenuItem item) { 4 if (item.getItemId() == R.id.menu_add) { 5 irPara(SalvarActivity.class); 6 return true; 7 } else if (item.getItemId() == R.id.menu_pref) { 8 irPara(EditarPreferencias.class); 9 return true; 10 } 11 return super.onOptionsItemSelected(item); 12 } 13 14 private void irPara(Class<?> clazz) { 15 irPara(clazz, null); 16 } 17 18 private void irPara(Class<?> clazz, String id) { 19 Intent intent = new Intent(MainActivity.this, clazz); 20 if (id != null) { 21 intent.putExtra(_ID, id); 22 } 23 startActivity(intent); 24 } Código-fonte 41: Ir para Preferências pelo menu principal [MainActivity.java] Note que para ter um código mais eficiente e otimizado tivemos que mudar o método irParaSalvar para irPara passando como parâmetro a classe que desejamos ir. Essa mudança é boa mais causa um impacto em outros trechos do código. Conserte-os da
  • 50. 40 CAPÍTULO 3. LIVRO DE RECEITAS seguinte maneira: 1 /* ... */ 2 private void configurar() { 3 listView.setOnItemClickListener(new OnItemClickListener() { 4 public void onItemClick(AdapterView<?> parent, View view, 5 int position, long id) { 6 irPara(SalvarActivity.class, String.valueOf(id)); 7 } 8 }); 9 10 listView.setOnItemLongClickListener(new OnItemLongClickListener() { 11 public boolean onItemLongClick(AdapterView<?> parent, View view, 12 final int position, final long id) { 13 /* ... */ 14 public void onClick(DialogInterface dialog, int which) { 15 switch (which) { 16 case 0: // editar 17 irPara(SalvarActivity.class, String.valueOf(id)); 18 break; 19 /* ... */ 20 21 } 22 } 23 } 24 } 25 } Código-fonte 42: Mudança em método irParaSalvar [MainActivity.java] Por fim temos que selecionar o item que o usuário quer que esteja selecionado por padrão ao inserir um novo contato. Assim, em SalvarActivity adicione o trecho: 1 private void carregar() { 2 /* ... */ 3 contatoId = getIntent().getStringExtra(MainActivity._ID); 4 if (contatoId != null) { 5 carregarContato(); 6 } else { 7 SharedPreferences preferencias = 8 PreferenceManager.getDefaultSharedPreferences(this); 9 spGrupo.setSelection( 10 Integer.parseInt(preferencias.getString( "lista_grupos" , "0" ))); 11 } 12 } Código-fonte 43: Obtem o valor padrão definido nas Preferências [SalvarActivity.java]
  • 51. 3.4. GRUPO DE CONTATOS USANDO GRID 41 3.4 Grupo de Contatos usando Grid Uma das coisas mais legais quando falamos de aparelhos móveis é a ideia da visão 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 implementação vamos criar uma tela que mostra os grupos de contatos em forma de Grid e ao clicar levaremos o usuário a lista de contatos mostrando apenas aqueles contatos de um determinado grupo. 3.4.1 Layout usando GridView Para começar criaremos um layout em res/layout chamado grupos item.xml. Ele irá ¯ conter a imagem e o texto que serão exibidos no GridView. Faça como mostra o trecho abaixo: 1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android= "http://schemas.android.com/apk/res/android" 3 android:layout_width= "fill_parent" 4 android:layout_height= "match_parent" 5 android:gravity= "center" 6 android:orientation= "vertical" > 7 8 <ImageView 9 android:id= "@+id/iv_icone" 10 android:layout_width= "wrap_content" 11 android:layout_height= "96.0dip" 12 android:scaleType= "fitCenter" /> 13 14 <TextView 15 android:id= "@+id/tv_texto" 16 android:layout_width= "fill_parent" 17 android:layout_height= "wrap_content" 18 android:layout_marginBottom= "20.0dip" 19 android:layout_marginTop= "2.0dip" 20 android:gravity= "center" 21 android:text= "TextView" 22 android:textAppearance= "?android:textAppearanceMedium" /> 23 </LinearLayout> Código-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 código abaixo:
  • 52. 42 CAPÍTULO 3. LIVRO DE RECEITAS 1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android= "http://schemas.android.com/apk/res/android" 3 android:layout_width= "match_parent" 4 android:layout_height= "match_parent" 5 android:orientation= "vertical" > 6 7 <GridView 8 android:id= "@+id/gv_grupos" 9 android:layout_width= "match_parent" 10 android:layout_height= "wrap_content" 11 android:numColumns= "3" > 12 <!-- Preview: listitem=@layout/grupos_item --> 13 </GridView> 14 15 </LinearLayout> Código-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 comentário e nele temos a referência ao layout grupos item. Para ¯ isso apenas clique com botão direito do mouse na GridView e na opção 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 { 2 3 private GridView grid = null; 4 5 @Override 6 protected void onCreate(Bundle savedInstanceState) { 7 super.onCreate(savedInstanceState); 8 9 setContentView(R.layout.grupos); 10 carregar(); 11 } 12 13 private void carregar() { 14 grid = (GridView) findViewById(R.id.gv_grupos); 15 } 16 } Código-fonte 46: Activity para visualizar Grupos [GruposActivity.java]
  • 53. 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 { 3 4 private Context context; 5 6 public IconeAdapter(Context context) { 7 super(); 8 this.context = context; 9 } 10 11 static class GruposHolder { 12 public ImageView icone; 13 public TextView texto; 14 } 15 16 public int getCount() { 17 return 0; 18 } 19 20 public Object getItem(int position) { 21 return null; 22 } 23 24 public long getItemId(int position) { 25 return 0; 26 } 27 28 public View getView(int position, View convertView, ViewGroup parent) { 29 return null; 30 } 31 } Código-fonte 47: Adapter responsável 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: amigos trabalho conhecidos família