Guia Aberto Android ed.2

7.605 visualizações

Publicada em

0 comentários
3 gostaram
Estatísticas
Notas
  • Seja o primeiro a comentar

Sem downloads
Visualizações
Visualizações totais
7.605
No SlideShare
0
A partir de incorporações
0
Número de incorporações
1.293
Ações
Compartilhamentos
0
Downloads
403
Comentários
0
Gostaram
3
Incorporações 0
Nenhuma incorporação

Nenhuma nota no slide

Guia Aberto Android ed.2

  1. 1. por Átila Camurça 2a Edição 27 de outubro de 2012
  2. 2. ii
  3. 3. Sumário1 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 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 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 . . . . . . . . . . . . . . . . . . . . . . . . 203 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. 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 . . . . . . . . . . . 46A Sobre o Autor 49Glossário 51
  5. 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. 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. 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. 8. viii LISTA DE TABELAS
  9. 9. Lista de Figuras 2.1 Layout linha da Lista . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 3.1 Tela de Grupos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 ix
  10. 10. x LISTA DE FIGURAS
  11. 11. Capítulo 1Preparando o Ambiente deDesenvolvimento1.1 IntroduçãoO 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, paracomeçar um ambiente de desenvolvimento precisa ser estável, e para isso nada melhor queo 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 utilizara versão mais recente. O mesmo para o plugin ADT. Usaremos especificamente para os exemplos a seguir a versão 2.2 do Android. EssaAPI é uma ótima escolha inicial, pois é a mais utilizada pelos aparelhos mais simples querodam Android. É claro que você poderá instalar outras versões e compilar seus aplicativospara tablets, etc. 1
  12. 12. 2 CAPÍTULO 1. PREPARANDO O AMBIENTE DE DESENVOLVIMENTO1.2 InstalaçãoA instalação do Java JDK 6 no Ubuntu 10.04 não é a mesma que no Ubuntu 12.04. Issoporque na época de lançamento do lucid, em 2010, a empresa que desenvolvia o Javaera 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 ehardware. 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 6A 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 → Gerenciadorde pacotes Synaptic. No menu do Synaptic clique em Configuração → Repositórios. Na aba OutroSoftware temos vários itens que representam repositórios. Marque os dois repositórios queterminam com partner. Feche e depois clique em Editar → Recarregar informaçõesdos pacotes ou simplesmente Ctrl + R. Após a atualização dos pacotes existentes nos repositórios já é possível encontrar oJava JDK 6. No campo de Pesquisa rápida digite: sun-java6. Clique com botãodireito no pacote sun-java6-jdk e selecione a opção Marcar para instalação. Depoisbasta Aplicar as mudanças. Para isso clique em Editar → Aplicar as alteraçõesmarcadas 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 executeos 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-jdkUm pouco de LinuxPara 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 querepresentam algo importante no âmbito dos comandos, são eles $ e #. Estes caracteresindicam 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 7Segundo 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 compiladocom suporte a versão 6.
  13. 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 selecioneProperties. Na lista de itens do lado esquerdo selecione Java Compiler. Daí basta clicarem Enable project specific settings e logo abaixo escolher o nível de compilação emCompiler compliance level, escolha 1.6.1.2.2 Android SDKPara 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 2bons locais para abrigar bibliotecas no Linux, são elas: /opt e /usr/local/lib. Nesseexemplo 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/androidObs.: troque usuario na primeira linha pelo seu login do sistema.O poder do LinuxDê 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 semque 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 qualqueroutro diretório. Agora saindo do modo root e usando seu próprio usuário instalaremos aAPI.1.2.3 Android 2.2 API 8Ainda no terminal, agora como usuário comum, vamos abrir o aplicativo que instala qual-quer uma das API disponibilizadas pelo Android.$ android
  14. 14. 4 CAPÍTULO 1. PREPARANDO O AMBIENTE DE DESENVOLVIMENTO O aplicativo Android SDK and AVD Manager irá aparecer. Clique em Avaliablepackages e procure pela versão 2.2 API 8 do Android. Selecione e clique em InstallSelected. 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. Aindano Android SDK and AVD Manager clique em Virtual devices, depois em New... Dê um nome. Você pode usar qualquer nomenclatura, mas é interessante que tenhaalgo haver com a versão. Assim, caso você tenha que testar seu código em outras versõesvocê poderá saber qual emulador utilizar. Por exemplo use android-2.2. Em Targetescolha a versão, neste caso Android 2.2 - API Level 8. Pronto, apenas clique emCreate AVD.DicasA 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 fazcom 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 peloemulador.1.2.5 Eclipse JunoO 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ãoEclipse IDE for Java EE Developers. Em todo caso as duas vão servir para o desenvolvimento, pois ambas vem com suportea Java. O Eclipse não possui instalador, no caso ele já vem pré-compilado. Basta apenasdescompactar e executar o arquivo eclipse. Para sua comodidade você pode adicionar o Eclipse no menu do Ubuntu. Isso podeser feito apenas clicando com o botão direiro do mouse no menu principal e escolhendo aopçã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 comoadicionar um item ao menu visível a todos os usuários.1.2.6 Plugin ADTPara 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. 15. 1.2. INSTALAÇÃO 5a serem instalados, clique em Next. Agora basta aceitar os termos de uso e clicar emFinish. Após o download e a instalação, reinicie o Eclipse. No Eclipse Marketplace você pode encontrar outras ferramentas bastante úteis paraum 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 ADTAgora que o plugin foi instalado temos que dizer ao Eclipse onde nós instalamos o AndroidSDK. Isso pode ser feito clicando no menu Window → Preferences. Selecione Androidno painel lateral esquerdo. Em SDK Location clique em Browse... e indique o diretóriodo SDK, caso não lembre, ele está em /usr/local/lib/android-sdk. Clique em Applyna 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 pluginADT localizada em http://developer.android.com/sdk/eclipse-adt.html.Testando o ADTPara testar o Android Development Tools ou ADT crie um projeto Android. No menudo Eclipse selecione File → New → Project... Selecione Android Application Project e clique em Next. Dê um nome qualquerao seu aplicativo, por exemplo hello.android. Note que o ADT tenta dar um nomeao seu pacote e ao diretório de arquivos a partir do nome que você digitou. Deixe comoestá. Em Build SDK é preciso escolher qual API vamos utilizar, em nosso caso escolhaa 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 cliqueem 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 primeiraaplicação rodando.DicasUma vez que você abriu o emulador não o feche. Você irá notar que ao abrir pela primeiravez ele leva um tempo para isso. Neste caso ao atualizar o código-fonte apenas rodeo aplicativo novamente. O plugin ADT fará com que o aplicativo seja reinstalado noemulador. 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 mostraras mensagens de log do emulador. Caso você encontre problemas com seu código o LogCatserá seu melhor aliado. Para acessá-lo no Eclipse clique no menu Window → Show View→ Other..., clique em Android → LogCat.
  16. 16. 6 CAPÍTULO 1. PREPARANDO O AMBIENTE DE DESENVOLVIMENTO1.2.7 Sqlite3Sendo o Sqlite o banco de dados embutido na plataforma Android, nada melhor do queaprendermos um pouco sobre ele. O Sqlite é um banco de dados relacional bastante utilizado por dispositivos e sistemasembarcados por ser leve, robusto, de fácil configuração e, acima de tudo, livre. Para ainstalaçã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 dousuário root e faça os seguintes testes:# exit$ sqliteSQLite version 2.8.17Enter ".help"for instructionssqlite> Você deverá ver algo parecido. Para sair utilize o comando .exit. Veja outros detalhesna página oficial do projeto: http://www.sqlite.org/.Tipos de dadosUtilize 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 Sqlite1.2.8 SqlitemanPara uma gerência mais produtiva usaremos o Sqliteman para acessar e modificar bancosde dados. A instalação é feita via linha de comando. Abra um terminal e:$ sudo su# apt-get install sqliteman
  17. 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 ); 910 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. 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áginahttp://developer.android.com/design/style/iconography.html.
  19. 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. 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. 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 @Override2 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. 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 }1516 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. 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 <TableRow14 android:id= "@+id/widget33"15 android:layout_width= "fill_parent"16 android:layout_height= "wrap_content"17 android:orientation= "horizontal" >18 <TextView19 android:id= "@+id/textView1"20 android:layout_width= "wrap_content"21 android:layout_height= "wrap_content"22 android:text= "Nome" ></TextView>23 <EditText24 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 <Button30 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. 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 }1011 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. 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;1112 public ContatoHelper(Context context) {13 super(context, DATABASE_NAME, null, VERSION);14 }1516 @Override17 public void onCreate(SQLiteDatabase db) {18 db.execSQL( "CREATE TABLE contato (_id INTEGER PRIMARY KEY AUTOINCREMENT,"19 + " nome TEXT, fone TEXT, email TEXT);" );20 }2122 @Override23 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. 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 }1314 private void carregar() {15 /* ... */16 btSalvar = (Button) findViewById(R.id.bt_salvar);17 }1819 private void ir() {20 btSalvar.setOnClickListener(new OnClickListener() {2122 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 }3233 @Override34 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. 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 <LinearLayout10 android:layout_width= "fill_parent" android:layout_height= "wrap_content"11 android:orientation= "vertical" >12 <TextView13 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 <TextView17 android:id= "@+id/linha_fone" android:layout_width= "fill_parent"18 android:layout_height= "wrap_content" ></TextView>19 <TextView20 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. 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 }1011 public String getFone(Cursor c) {12 return c.getString(2);13 }1415 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 } 910 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. 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 } 910 @Override11 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 }1819 @Override20 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. 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 }1213 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 }2021 @Override22 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. 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 } 910 private void irParaSalvar() {11 irParaSalvar(null);12 }1314 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 }2122 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. 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 }1112 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 }2021 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. 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. 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: // editar15 irParaSalvar(String.valueOf(id));16 break;17 case 1: // deletar18 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 }3435 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. 35. 3.1. MOSTRANDO DIÁLOGOS 25Interface como parâmetro de um métodoVocê já deve ter notado o uso de interface’s como parâmetro dos métodos, por exemplona linha 4 e 11 do código acima. Essa prática obriga ao programador implementar aclasse na passagem dos parâmetros. Essa ideia vem de algumas linguagens de programação que possuem funções comoparâmetros para outras funções. Como o Java não suporta essa característica, a soluçãoveio em forma de uma interface, a qual o programador é obrigado a implementar seusmétodos. Com isso o método que recebe a interface como parâmetro sabe exatamente oque ela tem disponível. A partir dessa observação, podemos justificar o uso da palavra reservada final emalguns 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 criaruma 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çãoDeletar dados é uma ação que deve ser feita com cuidado, então sempre é bom confirmarcom o usuário se ele deseja realmente deletar, no nosso caso, um contato. Para issousaremos o AlertDialog.Builder mais uma vez, agora apenas com uma mensagem e osbotões Sim ou Não. Ainda em MainActivity criaremos um outro AlertDialog.Builder no momento queo usuário clicar em Deletar. Segue o trecho:
  36. 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: // editar12 irParaSalvar(String.valueOf(id));13 break;14 case 1: // deletar15 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. 37. 3.1. MOSTRANDO DIÁLOGOS 273.1.3 Entrada de diferentes tipos de dadosO 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 inseridosnos 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 ehí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 oatributo inputType dos campos telefone e e-mail e altere os valores da seguinte maneira:
  38. 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. 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 }2122 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 }2728 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 }3435 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. 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. 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: // chamar13 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. 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-mail14 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. 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 } 910 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. 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 211 "grupo INTEGER NOT NULL DEFAULT 0 );" );12 }1314 @Override15 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. 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 }1213 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. 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:" />1213 <Spinner14 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. 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 }1516 private void carregarContato() {17 spGrupo.setSelection(helper.getGrupo(c));18 c.close();19 }2021 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. 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 @Override10 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. 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 }1314 private void irPara(Class<?> clazz) {15 irPara(clazz, null);16 }1718 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. 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 }); 910 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: // editar17 irPara(SalvarActivity.class, String.valueOf(id));18 break;19 /* ... */2021 }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. 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" />1314 <TextView15 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. 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>1415 </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 }1213 private void carregar() {14 grid = (GridView) findViewById(R.id.gv_grupos);15 }16 } Código-fonte 46: Activity para visualizar Grupos [GruposActivity.java]

×