You are on page 1of 84

Pgina 1 de 84

Lio 1: Desenvolvimento para Android


A plataforma Android baseada em sistema operacional Linux, adaptada para funcionamento em dispositivos mveis, como: smart phones, PDAs e Tablets. Para o desenvolvimento de aplicativos, foi disponibilizada uma mquina virtual, especialmente otimizada para uso em dispositivos mveis, alm de um ambiente de programao completo, com componentes visuais, de acesso a dados e redes. Interessante notar que a mquina virtual Dalvik um projeto Open Source (http://code.google.com/p/dalvik/), e NO UMA MQUINA VIRTUAL JAVA ! Isso mesmo: DALVIK NO JAVA! Existe uma aplicao, chamada dx, que pode converter o bytecode compilado a partir da mquina virtual Java (especificao da Oracle), no bytecode da Dalvik. A Google disponibilizou um ambiente de programao baseado em Java , que permite o desenvolvimento de aplicaes para a plataforma Android. Ele possui emuladores de dispositivos Android e conversores de bytecode. Segundo pesquisa da empresa Canalys , no quatro trimestre de 2010, quase 33 milhes de smartphones equipados com o sistema Android foram entregues, comparado com 31 milhes equipados com o sistema Symbian, da Nokia. Arquitetura do ambiente Android

A arquitetura do ambiente de desenvolvimento Android dividida em camadas. Sua aplicao roda na camada superior, por exemplo: contatos, telefone, jogos, calendrio, seu programa etc. Abaixo desta camada, vem um framework de componentes, que formam uma API de gerenciamento e servios para uso das aplicaes. Abaixo da camada de framework, temos as bibliotecas de servios, como OpenGL e SQLite, e as bibliotecas principais do ambiente, alm da prpria mquina virtual Dalvik. Finalmente, abaixo de tudo, temos o Kernel Linux. Embora seja possvel, devido a grande diversidade de dispositivos, no recomendado programar aplicaes em C/C++. O ambiente de programao Android fornece tudo o que voc necessita para criar aplicaes sinistras! Voc no precisa programar em C/C++ ou usar chamadas ao Kernel. Tudo o que necessita para criar aplicaes Android, do SDK e de um ambiente de programao Java. Cada aplicao Android executada por uma instncla da mquina virtual Dalvik, rodando em um processo separado dentro do sistema operacional.

Pgina 2 de 84

Componentes Uma aplicao Android um conjunto de componentes, que podem ser: Activities atividades ou telas; Services servios em background; Content Providers disponibilizam dados; Broadcast Receivers respondem a avisos gerais do sistema;

Uma aplicao Android orientada a eventos. Um evento um sinal, que pode ter sido originado pelo usurio (um toque) ou no (o timer, o bloqueio de tela etc). Logo, uma aplicao dividida em diversos tipos de componentes (activities, services etc), que compartilham um nome de pacote (sim, muito importante) e de aplicao comum, por exemplo: br.com.thecodebakers.hpp.Hppfree Os tipos de componentes so declarados e implementados na camada framework, e voc os estende para criar seus componentes especficos. View e ViewGroups

Uma View um elemento de interface. Comparando com uma pgina HTML, seriam os elementos de formulrio, como: botes, caixa de texto, radio buttons etc. As Views podem gerar e receber Eventos, que podem ser interceptados no cdigo-fonte. As Views podem ser agrupadas em ViewGroups, que fornecem o layout de arrumao na tela. Existem Views fornecidas pelo framework, que j agregam a parte visual e algum tipo de comportamento. So chamadas de Widgets. Se a sua aplicao possuir algum tipo de interface visual, o que o caso para a maioria delas, ento conter algumas Telas (activities), com Layouts (ViewGroups) e Views arrumadas nelas. atravs das Views que voc e o usurio se comunicam.

Pgina 3 de 84
Activity

Uma Activity uma tela onde o usurio pode fazer algo. Note que o relacionamento entre Activity e caso de uso no 1 para 1. Um caso de uso pode envolver vrias activities. Para criar uma Activity necessrio criar um arquivo de layout, que contm um ViewGroup e um ou mais ViewGroups ou Views internos, todos arrumados de acordo com a usabilidade da sua aplicao. Depois, necessrio criar a subclasse de Activity, que ser invocada quando o usurio solicitar. A parte de cdigo quem comanda o espetculo, usando a parte de layout. Todos os eventos gerados pelas Views do Layout, e pelos controles do aparelho (boto de menu, menu de contexto e boto back) podero ser tratados no cdigo de sua activity. Uma activity pode iniciar outros componentes de sua aplicao, como: outras Activities, Services etc; Service http://developer.android.com/guide/topics/fundamentals/services.html Um componente que executa operaes de longo prazo e em background; Podemos iniciar um service em outro componente. Ele continuar a executar mesmo que o usurio mude de aplicao. Outros componentes podem se conectar com o nosso service. Exemplos: I/O, servios de rede, de GPS, de alerta etc. Imagine uma aplicao de vendas. Os vendedores recebem atualizaes de Clientes e as acessam atravs da sua aplicao, O Download automtico de atualizaes poderia ser feito por um Service de sua aplicao. Um service, uma instncia de: android.app.Service, fica rodando em Background e pode executar tarefas longas, repetitivas ou a intervalos determinados. E tambm pode ser acessado por outras aplicaes. Um Media Player, por exemplo, utiliza um Service, que fica tocando a msica mesmo que a interface do media player seja fechada. Sua aplicao pode criar seus prprios Services ou usar Services fornecidos por outros. A criao de Services est fora do escopo deste curso, mas abordada em cursos mais avanados.

Pgina 4 de 84
Content Provider http://developer.android.com/guide/topics/providers/content-providers.html Amazenam e recuperam dados, disponibilizando-os para outras aplicaes. Exemplos: Contacts, Agenda etc. Voc tambm pode criar Content Providers para outras aplicaes; O Android vem com vrios Content Providers, como por exemplo as informaes de contato. Voc pode obter a lista de contatos do usurio (desde que autorizado por ele), acrescentar, remover etc. Voc no precisa criar um Content Provider para lidar com os dados de sua aplicao, mas, se quiser compartilh-los, ento ter que pensar nisto. Como as aplicaes Android so muito relacionadas com MashUps, bom pensar em compartilhar os dados de suas aplicaes, tornando-as mais populares. O desenvolvimento de content providers est fora do escopo deste curso. Broadcast Receiver http://developer.android.com/reference/android/content/BroadcastReceiver.html Classe que recebe alertas gerais do sistema. Podem ser gerados pelas activities ou no. Exemplo: SCREEN_OFF gerado pelo sistema quando a tela bloqueada. Voc pode tomar atitudes de acordo com o tipo de alerta recebido. Um Broadcast Receiver (derivado de: android.content.BroadcastReceiver) segue o padro GoF Observer. Ele se registra e fica observando se determinado evento geral acontece. diferente da classe de uma Activity, que somente observa eventos gerados pelas suas Views. Este tipo de componente pode receber eventos gerados pelo cdigo de sua aplicao, de outras aplicaes ou mesmo do sistema Android. Quando a tela desligada, por exemplo, possvel tomar alguamas atitudes. Nosso projeto: Hercules Password Protector (http://code.google.com/p/hercules-password-protector) usa um Broadcast Receiver para fechar o cofre caso a tela tenha sido desligada. A criao de Broadcast Receivers est fora do escopo deste curso.

Lio 2: Ambiente de desenvolvimento


Android APK Para ser executada e distribuda, sua aplicao Android tem que ser empacotada dentro de um arquivo com formato e extenso apk (Android Package). Algumas coisas so muito importantes neste arquivo: O hashcode de todas as pastas calculado e colocado dentro do MANIFEST.MF, que fica dentro do META-INF; A pasta res contm todos os recursos no compilveis da aplicao, como: arquivos XML, Layouts, menus, imagens etc; Arquivo dex. Este contm todo o bytecode da sua aplicao, traduzido para bytecode Dalvik; Arquivo arsc. Este contm os strings e uma tabela com todas as entradas do diretrio res, em formato binrio;

Antes de instalar um APK, voc deve assin-lo digitalmente. Isto pode ser feito com um certificado de assinatura de cdigo ou com uma chave auto-assinada. O processo de montagem manual de um APK bastante complexo e est fora do escopo deste curso. Veremos como criar APKs utilizando a IDE "eclipse".

Pgina 5 de 84
A APP dentro do Device Tudo acontece dentro do diretrio /data, em seu dispositivo Android. A figura mostra um shell de comandos conectado a um emulador Android. Veremos como administrar dispositivos mais adiante.

Dentro da pasta /data/dalvik-cache, temos os arquivos .dex acessados, e dentro da pasta /data/app, temos os arquivos apk de cada aplicao que instalamos.

Android Market Toda infra-estrutura para voc distribuir sua aplicao para o grande pblico. Pode ser gratuita ou paga. http://market.android.com. De acordo com pesquisas da loja de aplicativos GetJar, o mercado de aplicativos para dispositivos mveis, ou apps, deve crescer de 7 bilhes de downloads para cerca de 50 bilhes at 2012, tornando-se um mercado mais lucrativo que o de CD's. O crescimento da plataforma Android, cujo nmero de novos aparelhos superou a Symbian no terceiro trimestre de 2010, tornando-se a mais utilizada no mundo, apontado (juntamente com o iPad) como o fator impulsionador do mercado apps. Na plataforma Android, temos o site Android Market, que pode ser facilmente acessado pelos dispositivos mveis. Neste site possvel encontrar inmeros aplicativos, tanto gratuitos como pagos. E voc pode facilmente publicar suas aplicaes nele. Ns, The Code Bakers, temos algumas aplicaes publicadas no Android Market. Voc pode publicar suas aplicaes no Android Market. As nicas exigncias so: 1. Sua aplicao tem que estar assinada com uma chave criptogrfica privada, cuja validade termine depois de 22 de Outubro de 2033; 2. Sua aplicao tem que definir os atributos: android:versionCode e android:versionName no elemento <manifest>, de seu arquivo AndroidManifest.xml; 3. Sua aplicao tem que definir os atributos: android:icon e android:label no elemento <application> do arquivo AndroidManifest.xml; 4. Voc tem que fornecer um cone de alta resoluo (512 x 512 pixels) independentemente do cone de lanamento da aplicao; 5. Voc tem que fornecer o apk da sua aplicao; 6. Voc tem que fornecer pelo menos dois screen shots, de 320 x 480 pixels; 7. Voc tem que ter uma conta no Android Market, pagando US$ 25,00 pelo registro (uma nica vez);

Pgina 6 de 84
Todo o processo de publicao feito pela Internet e no h nenhum tempo de aprovao, ou seja, publicou, valeu! Sua aplicao pode ser gratuita ou paga. Se for paga, ento h necessidades posteriores (fora do escopo deste curso). Ambiente de desenvolvimento Para desenvolver aplicaes Android, podemos utilizar a IDE "eclipse", acrescentando um "plug-in" chamado ADT, e o framework do Android (Android SDK). O desenvolvimento feito em Java e, quando compilado, transformado em bytecode Dalvik. No necessrio possuir um dispositivo Android! Voc pode desenvolver e executar em um "emulador", que permite emular vrios tamanhos de tela e caractersticas de dispositivos mveis.

Configurao do ambiente Baixar o eclipse (ltima verso), s com Java; Baixar o Android SDK: o Windows: http://dl.google.com/android/android-sdk_r10-windows.zip o Mac: http://dl.google.com/android/android-sdk_r10-mac_x86.zip o Linux: http://dl.google.com/android/android-sdk_r10-linux_x86.tgz Baixar o plug-in ADT: configurar eclipse update site: "https://dl-ssl.google.com/android/eclipse/";

O SDK que voc est baixando apenas para configurar a instalao. Na segunda etapa, baixaremos atravs do eclipse as APIs necessrias. Descompacte-o em qualquer diretrio e anote este como a raiz do SDK. Baixe o eclipse e, dentro dele, configure o site de download indicado. Isto feito em Help / Install New Software / Add Site. Selecione todos os arquivos e baixe. Selecione o menu: Window / Preferences e selecione Android, para indicar ao eclipse onde est instalado o SDK. Indique o diretrio clicando no boto Browse. Baixando as plataformas especficas O ambiente composto por vrios outros componentes: Plataformas, exemplos, APIs e documentao. Para desenvolver, voc precisa uma plataforma, de modo a poder criar um AVD (Android Virtual Device), ou seja, um emulador. O mnimo necessrio : O SDK (voc j baixou e instalou); Platform (voc pode baixar pelo Android SDK and AVD Manager - menu: Window / SDK and AVD Manager do eclipse); Platform-tools;

Pgina 7 de 84

Podemos instalar vrias plataformas e APIs, dependendo da verso do Android e da API que desejamos.

Ns sempre instalamos a API level 7, pois corresponde verso do Android dos nossos celulares. Voc no precisa instalar todos os SDKs. Veja quais so as verses de Android e os API levels:

Pgina 8 de 84
Laboratrio 1 Baixe e instale todo o seu ambiente de desenvolvimento.

Lio 3: Obtendo e analisando um projeto pronto


Eclipse Neste curso, temos que assumir que voc j possua alguns conhecimentos bsicos: Java e eclipse. Por que eclipse? Por que no o NetBeans? Por que no fazer "na mo"? Bem, ns achamos que "eclipse" a IDE mais utilizada pelos desenvolvedores. um chute, mas baseado na nossa experincia como professores e como membros de vrias comunidades Open Source. Em segundo lugar, o plugin ADT foi desenvolvido para "eclipse". Voc pode fazer tudo "na mo", sem IDE alguma, mas vai ser muito mais difcil. Se voc no conhece "eclipse", existe farto material na Internet, inclusive este curso gratuito: https://www.buzzero.com/Feedib/curso-online-JAVA-ECLIPSE.html

ANDROID VERSION x API LEVEL Existem muitas verses do Android, assim como de sua API de programao. Isto muito importante! Voc deve baixar a plataforma (via SDK and AVD Manager) correspondente ao pblico-alvo que voc quer atingir. Atualmente, a maioria dos aparelhos que temos visto usa Android 2.2 (e 2.3 em segundo lugar). Voc pode estabelecer os requisitos para sua aplicao atravs de trs atributos de seu arquivo AndroidManifest.xml: android:minSdkVersion: Qual o menor nvel de API que sua aplicao suporta. O default 1; Se sua aplicao exige um determinado nvel de API, voc deve informar isto; android:targetSdkVersion: Qual o nvel de API que sua aplicao prefere executar. E,m alguns casos, permite que sejam usados elementos do nvel desejado, ao invs do nvel mnimo; android:maxSdkVersion: Qual o nvel mximo de SDK que sua aplicao suporta;

E voc deve desenvolver em uma plataforma (AVD) compatvel com o nvel de API que voc espera. Veja as verses do Android e o nvel de API de cada uma, at agora:

Code name (no code name) (no code name) Cupcake Donut Eclair Eclair Eclair Froyo Gingerbread Gingerbread Honeycomb Honeycomb

Version 1.0 1.1 1.5 1.6 2.0 2.0.1 2.2.x 2.3 - 2.3.2 2.3.3 - 2.3.4 3.0 3.1

API level API level 1 API level 2 API level 3, NDK 1 API level 4, NDK 2 API level 5 API level 6 API level 8, NDK 4 API level 9, NDK 5 API level 10 API level 11 API level 12

2.1 (incl. 2.1-update 1) API level 7, NDK 3

Pgina 9 de 84
Segundo nossas estatsticas, at agora (Junho 2011), as verses "Eclair" (2.1) e "Froyo" (2.2), so as mais utilizadas pelas pessoas que baixaram nossas aplicaes do Android Market.

Google Code e Subversion Ns mantemos todo o nosso cdigo-fonte dentro do "Google Code", que um repositrio de projetos Open Source. Ele fornece acesso a servidores de controle de verso (CVS, Subversion e Mercurial), que permitem aos usurios baixar e subir atualizaes. Ns optamos por utilizar sempre o Subversion, logo, para obter os projetos, necessrio que voc instale um novo plugin no "eclipse", chamado: "Subeclipse". A URL do update site : http://subclipse.tigris.org/update_1.6.x. Para instalar o plugin: 1. 2. 3. 4. 5. Clique no menu "Help / Install New Software..."; Clique no boto "Add..." para adicionar o update site; Informe a URL: "http://subclipse.tigris.org/update_1.6.x" e adicione; Feche a Janela e selecione o site recm-adicionado; Aps carregar, marque todos. Pode demorar um pouco. Certifique-se de aceitar a licena de uso;

Agora, voc pode fazer "checkout" de projetos armazenados no Servidor SVN (subversion). Para isto, veja qual a URL do servidor do projeto: 1. No site do Google Code do projeto, por exemplo, o BioMago, selecione a aba "Source"; 2. No conjunto de abas logo abaixo, deixe "Checkout" selecioando. Voc ver uma caixa com o ttulo: "Use this command to anonymously check out the latest project source code:", logo, anote a URL que est logo aps as palavras "svn checkout". No caso do BioMago, a URL : "http://biomago.googlecode.com/svn/trunk/"; Desta forma, voc ter a URL que deve ser informada ao configurar o "repositrio SVN" dentro do "eclipse". Se quiser saber mais sobre Controle de Verses e Subversion, recomendamos o site da Wikipedia: http://pt.wikipedia.org/wiki/Subversion.

Um projeto no eclipse Agora, sente-se em posio de ltus, respire fundo e murmure: "Ohmmmmmm", ou seja, relaxe e entre em meditao profunda, de modo a prestar ateno no que vamos dizer neste momento. Sabemos que voc est com pressa. Ns, tcnicos, sempre temos pressa em fazer tudo e no temos pacincia para ler manuais. Existe at um ditado famoso: "Quanto tudo mais falhar, leia o Manual!" Antes de voc fazer um projeto seu no Android, colocar no Celular e mostrar para a Me, o Pai, o Av, a Namorada ou o Namorado, melhor conhecer um projeto j existente. Voc tem que ver como estruturado, quais so as pastas, quais so os principais arquivos etc. Assim, quando chegar o momento de fazer seu prprio programa, evitar diversos problemas (e xingamentos). Tenha pacincia e v com calma. O laboratrio desta lio voc conseguir baixar um projeto, analisar o cdigo-fonte e executar no emulador. Agora, pode sar da posio de ltus! Vamos usar o Subversion para importar um projeto para a nossa workspace; Crie um repositrio: http://biomago.googlecode.com/svn/trunk:

Pgina 10 de 84
Selecione Window / Show View / SVN Repositories e clique com o boto direito, selecionando: New / Repository location. Depois, informe a URL acima;

Agora, vamos baixar o projeto para nossa Workspace: Selecione File / Import / SVN / Checkout projects from SVN, selecione o repositrio que voc acabou de criar, aceite os defaults, e importe o projeto;

A estrutura bem simples. Na pasta src temos todo o cdigo-fonte Java desenvolvido. Na pasta gen, temos uma classe muito importante: R.java! Nunca altere este arquivo! Ele contm identificadores para imagens, layouts, menus e strings da aplicao. Ele auto-gerado a cada novo recurso que adicionamos ao projeto. A pasta res contm os recursos em si: imagens (drawables), layouts (de activities), menus, estilos e strings. O arquivo AndroidManifest.xml a declarao da aplicao. Ele contm todas as configuraes necessrias para empacotar, distribuir e executar a aplicao. O arquivo default.properties contm as propriedades do projeto. A mais importante qual Plataforma est sendo usada para executar o projeto. Para mudar isto: selecione o projeto e, com o boto direito, selecione: Properties. Abra a parte Android e selecione a plataforma desejada. Ateno: Para executar esta aplicao, voc deve ter baixado a plataforma: Google Inc.:Google APIs:7. Porm, se voc baixou apenas o Android SDK 7, ento deve mudar a plataforma, conforme ensinado anteriormente. Executando a aplicao Sua aplicao ser executada DENTRO de um programa emulador de ambiente Android. Voc precisa criar um "AVD" (Android Virtual Device) para isto. claro que pode executar diretamente no seu Celular, o que contra-producente.

Criando um Android Virtual Device - AVD (Emulador) Para criar um AVD: 1. Clique no menu "Window" e selecione SDK and AVD Manager; 2. Clique em new; 3. Informe os dados desejados: o name: o nome do seu dispositivo virtual; o target: a verso de Android e o nvel de API que ele vai suportar; o SD-card (size): o tamanho em megabytes do SD Card; o Skin: a tela. Selecione "builtin". Recomendamos usar HVGA; 4. Clique em Create AVD e v tomar um caf... Demora MUUUUUUIIIIITO!

Pgina 11 de 84
Voc s precisar criar AVDs uma nica vez, ou ento, sempre que desejar testar em um dispositivo diferente. Voc pode criar AVDs que simulem o seu Celular ou Tablet, ou ento o que voc espera encontrar no mercado. Porm, o Google sempre se refere a uma configurao chamada de "Baseline": Tela: HVGA (320x480) Se voc usar esta configurao, ser fcil adaptar seu programa para utilizar outras formas e tamanhos de tela. Guarde o nome do AVD que voc criou. Ele pode ser econtrado na pasta: Linux: ( uma pasta oculta): ~/.android/avd/[nome do avd]; Windows: DOCUMENTS_AND_SETTINGS/android/avd/[nome do avd];

Executando a aplicao Selecione seu projeto, na Janela "Project Explorer", e faa o seguinte: 1. Selecione: Run / Run Configurations; 2. Abra a aba target, e indique qual AVD o preferencial; 3. Depois, selecione apply e run;

Nas prximas vezes, s clicar no projeto e selecionar "Run as / Android Application"

Emulador

O emulador como se fosse um dispositivo mvel mesmo! Ele possui todas as teclas de um aparelho tpico, inclusive um teclado de hardware. Ele tem as teclas home, menu, back e magnify. A tecla menu desbloqueia o aparelho. Se quiser, pode at alternar entre em p (portrait) e deitado (landscape) usando CONTROL ESQUERDO + F11. Voc conhece o Android? No? Ento aproveite! Acione a tecla back, saia do aplicativo e veja o que o Android oferece a voc, Talvez voc esteja se perguntando: eu preciso ter um dispositivo Android para desenvolver? A resposta NO! Porm, ajuda bastante. Ns temos alguns smartphones Sony Xperia (um X10 e um X10 mini), alm de um Samsung S. Ah! E para depurar a mesma coisa, s que voc tem que acionar Debug e colocar breakpoints no cdigofonte.

Pgina 12 de 84
Problemas de publicao do Blogger O Blogger, servio do Google que utilizamos para manter nossa comunidade, est apresentando problemas intermitentes de publicao. Logo, tivemos que dividir algumas lies, incluindo esta, em duas partes, de modo a diminuir o tamanho e o nmero de imagens. Laboratrio O laboratrio desta lio voc conseguir instalar o plugin subeclipse, conectar ao servidor SVN, baixar o projeto BioMago (http://code.google.com/p/biomago/), analisar o cdigo-fonte e conseguir executar o aplicativo.

Lio 4: Criando sua primeira aplicao Android


Est na hora de criar um "Hello world" O aprendizado de toda linguagem de programao comea com um famoso programa, do tipo: "Hello World". Vamos fazer a mesma coisa! Siga as instrues a seguir, de modo a criar uma aplicao simples no "eclipse". 1) Para comear, vamos criar uma nova Workspace: Depois de cri-la, configure o Android SDK. Abra o menu: "window" / "preferences", selecione "Android" e aponte para a localizao do SDK. Se voc j tem uma workspace criada (a do projeto anterior), ento pode utiliz-la. Lembre-se de fechar o projeto "BioMago", para no confundir (selecione o projeto e, no menu de contexto, clique em "Close Project"). 2) Com a Workspace criada, hora de criar um projeto: Selecione o menu: "File / New / Android Project". Pode ser que a opo "Android Project" no aparea, neste caso, selecione: "Project...", escolhendo "Android" na tela seguinte. Preencha os campos conforme a lista abaixo: Informe o campo: "Project Name" com o nome do futuro projeto (no use espaos nem caracteres especiais); Deixe selecionados os campos: "Create new project in workspace" e "Use default location"; Marque o campo "Build target". Ns s temos dispositivos Android 2.1. Se quiser uma verso posterior, tem que baixar a plataforma. Role a tela para cima; Preencha o campo: "Application Name" com o nome que voc quer que as pessoas conheam o seu projeto; Preencha o campo: "Package Name" com o nome do pacote Java. Em Android este nome muito importante. Normalmente, usamos o nome de domnio ao contrrio, acrescido do nome do projeto; Marque o campo "Create Activity" e informe o nome da classe da Activity principal, que o assistente criar para ns (este um class name!); Informe o campo "Min SDK version" com a verso de SDK mnima necessria para que sua aplicao seja executada. Se estiver usando Android 2.1, ento use "7";

Pgina 13 de 84

Ao clicar "Next", note que oferecida a opo de criar um projeto de teste. Neste momento, deixe desmarcada e clique "finish"; Aps algum tempo, seu projeto estar criado. Selecione seu projeto, abra suas propriedades e selecione "Android". Voc ver que a API desejada estar marcada. 3) Configure o AVD e execute o projeto no emulador: Para executar o projeto, voc deve ter criado um AVD (Android Virtual Device). No curso, h instrues sobre como fazer isto. Selecione seu projeto, escolha "Run Configurations". Marque "Android Application", e clique no boto "new" da caixa de dilogo. Selecione o AVD "target", aponte o nome do projeto, depois pressione: "Apply" e "Run". Da prxima vez, no ter que fazer isto.

Ao aparecer o Emulator com a "cara de um celular" na tela, pressione o boto "menu" para desbloque-lo (se aparecer um dilogo de espera, selecione o boto "Wait"). Examinando o cdigo-fonte gerado Pera... Ns no escrevemos nada! Como pode haver cdigo-fonte? O plug-in "ADT" gera uma aplicao "Hello World" automaticamente, logo, todo o cdigo-fonte e configuraes necessrios j esto prontos.

Pgina 14 de 84
Vamos examinar a aplicao. Para comear, ela j possui uma activity com um layout criado, alm de recursos, como strings e cones: Classe da Activity "Principal.java", dentro de "src" e dentro do pacote Java que voc informou. Layout "main.xml" (os layouts e todos os arquivos XML do Android devem ter nomes em minsculas), dentro de "res/layout". cone "icon.png", dentro de cada uma das trs pastas "drawable", dentro de "res". Dois strings "hello" e "app_name", criados dentro de um arquivo "strings.xml", dentro da pasta: "res/values". Uma classe "R.java", criada automaticamente dentro da pasta: 'src/gen". Um arquivo "AndroidManifest.xml", criado na raiz do projeto. Um arquivo "default.properties", contendo as propriedades do projeto. Um arquivo "proguard.cfg", criado na raiz do projeto - ProGuard um ofuscador de cdigo, que "embaralha" o byte code da aplicao, dificultando a engenharia reversa. Este um arquivo que configura esta ferramenta. Vamos examinar o cdigo-fonte da nossa Activity:
1. package br.com.thecodebakers.primeiro; 2. 3. import android.app.Activity; 4. import android.os.Bundle; 5. 6. public class Principal extends Activity { 7. /** Called when the activity is first created. */ 8. @Override 9. public void onCreate(Bundle savedInstanceState) { 10. super.onCreate(savedInstanceState); 11. setContentView(R.layout.main); 12. } 13. }

O mtodo "onCreate" invocado quando a Activity criada (no existe na pilha). A chamada do mtodo "setContentView()" indica qual o layout que deve ser exibido na tela que a Activity vai exibir.

Ciclo de vida de activities

Quando uma activity est em estado "running", est visvel, com todo seu estado preservado e pode receber eventos, seja do sistema ou de suas Views.

Pgina 15 de 84
Se outra atividade ou dilogo receber o foco, a activity passa para o estado "Paused". Ela continua "visvel" e retm seu estado. Ela pode ser destruda pelo sistema, caso haja extrema necessidade de memria e recursos. Neste estado, ideal que as animaes sejam pausadas e o estado seja salvo. Outra atividade recebeu o foco e o controle, ocultando totalmente a primeira, que passa a estar em estado "Stopped". Ela poder ser desativada pelo sistema, caso haja necessidade de memria. Ela continuar a reter seu estado. H uma nuance de diferena entre o estado "Paused" e o "Stopped", pois ambos partem do pressuposto que a activity foi "oculta". A nuance a visibilidade. Uma activity em estado "Paused" no est totalmente oculta, um exemplo disto quando uma caixa de dilogo aberta (ou uma janela de notificao). J uma activity em estado "Stopped" foi completamente ocultada por outra Activity, por exemplo, neste comando:
1. public void clicouLinear(View view) { 2. Intent i = new Intent (this.getApplicationContext(), LinearDemo.class); 3. this.startActivity(i); 4. }

Ao executar a linha com a chamada: "startActivity()", a atividade a qual este cdigo-fonte pertence passar a ficar em estado "Stopped", pois acaba de iniciar outra Activity. O Estado "Killed", na verdade no existe. A Activity fica nesse estado somente por uns poucos momentos, enquanto seu mtodo "onDestroy()" est sendo executado. A no ser em casos extremamente especficos, ns no encerramos manualmente as activities, deixando esta tarefa a cargo do sistema. Para cada transio de estado, um mtodo "callback" da classe Activity invocado. Voc pode ou no sobrescrev-los, dependendo da sua necessidade. Normalmente, sobrescrevemos apenas o mtodo "onCreate()", mas existem os mtodos: onCreate quando a actitivy est para se tornar "Running". onStart a activity est para se tornar visvel. onRestart a activity estava "Stopped" e foi ativada novamente. onResume a activity vai comear a interagir com o usurio, recebendo input e eventos. onPause a activity est parcialmente oculta. Neste mtodo, voc pode fazer "commit" de alteraes ou parar animaes, de modo a poupar recursos do sistema. onStop a activity est totalmente oculta por outra activity e esta funo chamada. onDestroy a activity est para ser eliminada da memria. Existem outros "callbacks" importantes, como: "onBackPressed()", invocado quando a tecla "back" do dispositivo acionada.

Arquivo "AndroidManifest.xml" Abra o arquivo "AndroidManifest.xml", dentro da raiz do projeto. Note que ele possui diversas informaes sobre seu projeto. Para comear, dentro do TAG <manifest>, ele possui alguns atributos interessantes: package: muito importante! Sua aplicao conhecida pelo nome do pacote;

Pgina 16 de 84
android:versionCode e android:versionName: nmero da verso da aplicao. Primeiro em forma numrica e depois em forma String;

Dentro do tag <application> temos atributos importantes: android:icon: identificao do cone da aplicao, de acordo com os nomes de imagens dentro da classe "R"; android:label: ttulo da aplicao. Todas as activities que no especificarem este atributo, herdaro o valor deste;

Ainda dentro do tag <application>, ns inserimos os tags de nossas activities. O Assistente do ADT faz isto para ns, porm, se inserirmos mais classes de activities, temos que inserir tags <activity> manualmente: android:name: o nome da classe (ser concatenado ao string especificado no atributo "package", do tag <manifest>); Se a activity for utilizada para lanar a aplicao, ento temos que colocar um tag <intent-filter> com dois subtags. Veja a activity principal ("main") para ver como se faz;

Existe muito mais para se saber sobre o arquivo "AndroidManifest.xml". Sugerimos que voc leia os manifestos dos nossos projetos ou ento entre no site do Android (http://developer.android.com/guide/topics/manifest/manifest-intro.html).

Lio 5: Layout e interface com usurio


Criao de layout Um Layout um arquivo XML que define quais ViewGroups existem e quais Views elas contm. Pontos importantes: Toda activity deve possuir pelo menos uma View para interagir com o usurio; Normalmente, usamos um arquivo de layout, contendo um ViewGroup e algumas Views; Todos os elementos de layout so referenciados na classe R.java; Baixe o projeto http://layout-exercise.googlecode.com/svn/trunk/: 1. No eclipse, abra a view: SVN repositories; 2. Adicione o repositrio acima; 3. Expanda o repositrio; 4. Selecione a pasta Layouts e faa Checkout; Examine o arquivo res/layout/main.xml:
1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2. android:orientation="vertical" 3. android:layout_width="fill_parent" 4. android:layout_height="fill_parent" 5. > 6. <TextView 7. style="@style/titulo_link.vermelho" 8. android:layout_width="fill_parent" 9. android:layout_height="wrap_content" 10. android:text="@string/linear" 11. android:onClick="clicouLinear" 12. /> 13. <TextView 14. style="@style/titulo_link.verde" 15. android:layout_width="fill_parent" 16. android:layout_height="wrap_content" 17. android:text="@string/table" 18. android:onClick="clicouTable" 19. /> 20. <TextView

Pgina 17 de 84
21. style="@style/titulo_link.azul" 22. android:layout_width="fill_parent" 23. android:layout_height="wrap_content" 24. android:text="@string/relative" 25. android:onClick="clicouRelative" 26. /> 27. <TextView 28. style="@style/titulo_link.lilas" 29. android:layout_width="fill_parent" 30. android:layout_height="wrap_content" 31. android:text="@string/with_images" 32. android:onClick="clicouWithImages" 33. /> 34. <TextView 35. style="@style/titulo_link.laranja1" 36. android:layout_width="fill_parent" 37. android:layout_height="wrap_content" 38. android:text="@string/dontDoIt01" 39. android:onClick="clicouDont01" 40. /> 41. <TextView 42. style="@style/titulo_link.piscina" 43. android:layout_width="fill_parent" 44. android:layout_height="wrap_content" 45. android:text="@string/dontDoIt02" 46. android:onClick="clicouDont02" 47. /> 48. <TextView 49. style="@style/titulo_link.amarelo" 50. android:layout_width="fill_parent" 51. android:layout_height="wrap_content" 52. android:text="@string/listacombarra" 53. android:onClick="clicouLista" 54. /> 55. </LinearLayout>

Todo layout um arquivo ANDROID XML, cujo nome deve comear com letras minsculas, e deve residir na pasta: res/layout. Ele deve possuir um e somente um ViewGroup principal, que, neste caso, o LinearLayout. O LinearLayout coloca tudo em sequncia. Execute a aplicao e selecione LinearLayout:

Pgina 18 de 84

Todas as views filhas so organizadas em sequncia, enquando couberem na mesma linha. Voltando ao arquivo main.xml, note que temos 7 Views dentro do nosso ViewGroup principal e todas so do tipo TextView, Uma TextView serve para exibir textos. Agora, abra o seu primeiro projeto, cujo layout mais simples, e veja o arquivo res/main.xml:
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. > 7. <TextView 8. android:layout_width="fill_parent" 9. android:layout_height="wrap_content" 10. android:text="@string/hello" 11. /> 12. </LinearLayout>

Temos uma nica TextView, com trs propriedades informadas: android:layout_width Qual a largura que a View prefere ter, dentro de seu parent, que, neste caso o ViewGroup LinearLayout. android:layout_height Qual a altura que a View prefere ter dentro de seu parent. android:text Qual o texto que ser exibido dentro da View. As propriedades android:layout_width e android:layout_height so muito importantes e so obrigatrias. Ns podemos especificar trs valores: FILL_PARENT A view quer ser to grande naquela dimenso (altura ou largura) como o seu parent. Ela encher o ViewGroup; WRAP_CONTENT A view quer ser grande o suficiente para conter o texto (ou imagem) atribudo; Unidades Podem ser dp - density independent values, sp - scale independent, pt - 1/72 de polegada ou px -pixels; No nosso caso, estamos estabelecento que a TextView ser da largura de seu parent e ter a altura suficiente para conter o texto que atribumos (este o padro para TextView). Na propriedade android:text especificamos um string resource. Nossa aplicao pode ter vrios tipos de recursos (resources): layouts, estilos, strings, imagens etc; os nomes dos recursos ficam compilados em uma tabela binria, chamada de <projeto>.arsc. Para identificar o recurso, usamos um nmero inteiro, que o seu ndice na tabela. Sempre que criamos alguma coisa na pasta res, o ADT altera a classe R.java, dentro da pasta gen. Ele cria uma constante dentro da inner class apropriada. Eis o R.java do nosso primeiro projeto:
1. package br.com.thecodebakers.primeiro; 2. 3. public final class R { 4. public static final class attr { 5. } 6. public static final class drawable { 7. public static final int icon=0x7f020000; 8. } 9. public static final class layout {

Pgina 19 de 84
10. 11. 12. 13. 14. 15. 16. } public static final int main=0x7f030000; } public static final class string { public static final int app_name=0x7f040001; public static final int hello=0x7f040000; }

Temos trs inner classes que so constantes dentro desta classe: attr, que representa atributos (no estamos usando), drawable, que representa imagens, layout, que representa layouts de views, e string, que representa recursos de strings. Outro muito importante o id, que representa os identificadores que criamos dentro de nossos layouts (veja a classe R.java do projeto Layouts). No layout de nossa activity (primeiro projeto), dissemos o seguinte: android:text="@string/hello" Logo, o texto que ser exibido o que est contido dentro do recurso de strings chamado hello. E onde fica ele? Dentro de um arquivo XML, que fica na pasta res:
1. <?xml version="1.0" encoding="utf-8"?> 2. <resources> 3. <string name="hello">Hello World, Principal!</string> 4. <string name="app_name">Primeiro Projeto</string> 5. </resources>

Por que isto? para facilitar a localizao (L10N) de nossa aplicao. Finalmente, temos tambm os ids. Abra o projeto BioMago, que importamos na primeira aula. Execute o programa e cadastre um registro. Note que, ao cadastrar, o BioMago tem que pegar o nome e a data de nascimento. A atividade que faz o cadastramento a Edicao.java e seu layout R.layout.edicao, ou o arquivo: edicao.xml. Vamos primeiramente ver o arquivo de layout:
1. <RelativeLayout 2. xmlns:android="http://schemas.android.com/apk/res/android" 3. android:layout_width="fill_parent" 4. android:layout_height="fill_parent"> 5. 6. <TextView 7. android:layout_alignParentTop="true" 8. android:layout_centerHorizontal="true" 9. android:text="@string/lblNome" 10. style="@style/titulo" 11. android:layout_height="wrap_content" 12. android:layout_width="fill_parent" 13. android:id="@+id/lblnome"/> 14. <EditText 15. android:layout_below="@+id/lblnome" 16. android:layout_centerHorizontal="true" 17. android:id="@+id/txtNome" 18. android:maxLines="1" 19. android:layout_height="wrap_content" 20. android:layout_width="fill_parent"/> 21. 22. <TextView 23. android:layout_below="@+id/txtNome" 24. android:layout_centerHorizontal="true" 25. style="@style/titulo" 26. android:text="@string/lblNascimento" 27. android:layout_height="wrap_content" 28. android:layout_width="fill_parent" 29. android:id="@+id/lbldata"/>

Pgina 20 de 84
30. 31. <DatePicker 32. 33. android:layout_below="@+id/lbldata" 34. android:layout_centerHorizontal="true" 35. android:id="@+id/dtData" 36. android:layout_height="wrap_content" 37. android:layout_width="fill_parent" 38. ></DatePicker> 39. 40. <ImageView 41. android:layout_alignParentBottom="true" 42. android:layout_alignParentLeft="true" 43. android:src="@drawable/ok" 44. android:layout_gravity="left" 45. android:id="@+id/btnSalvar" 46. android:layout_height="wrap_content" 47. android:layout_width="wrap_content" 48. android:onClick="salvar" 49. ></ImageView> 50. <ImageView 51. android:layout_alignParentBottom="true" 52. android:layout_alignParentRight="true" 53. android:src="@drawable/cancelar" 54. android:layout_gravity="left" 55. android:id="@+id/btnCancelar" 56. android:layout_height="wrap_content" 57. android:layout_width="wrap_content" 58. android:onClick="cancelar" 59. ></ImageView> 60. </RelativeLayout>

Neste projeto, usamos outro tipo de ViewGroup, que o RelativeLayout. Note a View EditText, que est em negrito:
1. <EditText 2. android:layout_below="@+id/lblnome" 3. android:layout_centerHorizontal="true" 4. android:id="@+id/txtNome" 5. android:maxLines="1" 6. android:layout_height="wrap_content" 7. android:layout_width="fill_parent"/>

O que isso? A propriedade id permite que nos referenciamos a uma View dentro do cdigo-fonte Java, podendo obter o valor que o usurio digitou, por exemplo. O que informamos dentro da propriedade foi @+id/txtNome, que significa: se no existir o id txtNome, crie-o. Uma entrada foi criada dentro de R.java:
view plaincopy to clipboardprint?

1. public final class R { 2. public static final class attr { 3. ... 4. } 5. public static final class drawable { 6. ... 7. } 8. public static final class id { 9. ... 10. public static final int txtNome=0x7f07000a; 11. ... 12. } 13. public static final class layout { 14. ... 15. }

Pgina 21 de 84
16. 17. 18. 19. 20. 21. 22. 23. 24. 25. } public static final class menu { ... } public static final class string { ... } public static final class style { ... }

Ou seja, criamos um novo identificador de View dentro de nosso projeto, e podemos us-lo para nos referenciar EditText que criamos. Para obter o nome do usurio, o cdigo da Activity tem que declarar uma varivel do tipo: android.widget.EditText:
1. public class Edicao extends Activity { 2. ... 3. private EditText txtNome; 4. 5. public void salvar (View view) { 6. txtNome = (EditText) this.findViewById(R.id.txtNome); 7. Elemento elemento = new Elemento(); 8. elemento.setNome(txtNome.getText().toString()); 9.

Assim, podemos acessar a View e pegar o nome que o usurio informou. A EditText possui alguns atributos e propriedades muito interessantes, por exemplo, o atributo XML android:inputType nos permite determinar qual tipo de dado o usurio pode digitar, e o atributo: android:password substitui o valor digitado por um crculo, como se fosse um campo de senha. Podemos pegar o contedo de uma EditText com o mtodo getText(), mas note que ele somente devolve um Editable. Se quisermos pegar o string, temos que usar o mtodo: getText().toString(). E, se quisermos converter em um nmero: Long.valueOf(txt.getText().toString()); Se informarmos numberSigned no atributo XML android:inputType, nossa EditText somente aceitar a digitaco de algarismos, com ou sem sinal. Para concluir esta parte, precisamos ter uma maneira de reagir aos eventos provocados pelo usurio, como o clique de um boto, por exemplo. Todo elemento Clicvel possui o atributo XML: android:onClick, que nos permite nomear um mtodo de callback dentro da classe da Activity. Por exemplo, abra o layout main,xml e a Activity Principal.java, do projeto Layouts:
1. <TextView 2. style="@style/titulo_link.vermelho" 3. android:layout_width="fill_parent" 4. android:layout_height="wrap_content" 5. android:text="@string/linear" 6. android:onClick="clicouLinear" 7. />

1. public void clicouLinear(View view) { 2. Intent i = new Intent (this.getApplicationContext(), LinearDemo.class); 3. this.startActivity(i); 4. }

Repare que no layout, a TextView est apontando o android:onClick para clicouLinear, e que na classe da Activity, temos um mtodo com a assinatura: public void clicouLinear (View view). O nome do mtodo tem que ser o mesmo informado no atributo, e a assinatura tem que ter void como retorno, e uma instncia de

Pgina 22 de 84
View como argumento. Este mtodo ser invocado quando aquela TextView for clicada pelo usurio. E o que o mtodo faz? Ele invoca outra Activity! Ele cria uma instncia de android.content.Intent, que serve para determinar o que ser executado. Pode ser uma Actrivity do projeto ou um aplicativo externo, como uma pgina Web. Neste caso, estamos criando um Intent que chama a classe da atividade LinearDemo. O mtodo startActivity() inicia a outra atividade. Tambm poderamos mostrar uma caixa de dilogo, uma mensagem, tipo JOptionPane, s que usamos outra classe para isto:
1. 2. 3. 4. 5. 6. 7. 8. Resources res = this.getResources(); new AlertDialog.Builder(this) .setMessage(res.getString(R.string.erro_data_posterior)) .setNeutralButton(res.getString(R.string.lblOK), new DialogInterface.OnClickList ener() { public void onClick(DialogInterface dialog, int which) { } }) .show();

Para comear, apontamos para os recursos da aplicao usando a classe android.content.res.Resources. Ela serve para obtermos recursos, por exemplo strings, dentro do cdigo-fonte Java. Nos arquivos XML usamos apenas @string/<nome>, mas no cdigo Java precisamos usar: <instncia de Resources>.getString(identificador). Lembrando que todo resource string est possui seu identificador dentro da classe R.java. Depois, criamos uma instncia de android.app.AlertDialog.Builder e outra de AlertDialog; Poderamos reescrever este cdigo-fonte assim:
1. AlertDialog.Builder construtor = new AlertDialog.Builder(this); 2. construtor.setMessage(res.getString(R.string.erro_data_posterior)) 3. .setPositiveButton("Ok", new DialogInterface.OnClickListener() { 4. public void onClick(DialogInterface dialog, int id) { 5. // comandos... 6. } 7. }); 8. AlertDialog alert = construtor.create(); 9. alert.show();

Dois pontos importantes: 1 Todos os dilogos so MODELESS; 2 Use sempre string resources e evite literais; Agora, voc tem todos os elementos para fazer o laboratrio 2.

Laboratrio 2 Vamos criar uma aplicao que interage com o usurio. Ela receber um nmero e far sua fatorao (decomposio em nmeros primos), exibindo um dilogo que mostrar o resultado. 1 Crie um novo projeto Android, conforme fizemos no Laboratrio 1; 2

Pgina 23 de 84
Edite o layout main.xml e acrescente:
a Uma TextView contendo o rtulo: Nmero (dever estar dentro de um string resource); b Uma EditView que receba o nmero digitado (deve apenas receber nmeros e deve ter id); c Um boto Button, que invoque o callback para fazer e mostrar a fatorao;

3 O callback dever decompor o nmero informado em fatores primos, e usar um dilogo para mostrar o resultado; O crivo de Eratstenes Para decompor em fatores primos, necessrio, primeiramente, obter uma lista de nmeros primos! Segundo a Wikipedia: O Crivo de Eratstenes um algoritmo e um mtodo simples e prtico para encontrar nmeros primos at um certo valor limite. Segundo a tradio, foi criado pelo matemtico grego Eratstenes (c. 285-194 a.C.), o terceiro bibliotecrio-chefe da Biblioteca de Alexandria. Felizmente, para voc, estvamos de bom humor e providenciamos uma implementao do Crivo, que pode ser encontrada ao final da lio. O resultado de sua aplicao deve ser como a figura:

Implementao do Crivo
1. package br.nom.sampaio.cleuton.factorwiz; 2. import java.util.ArrayList; 3. import java.util.Iterator; 4. import java.util.List; 5. import android.view.View; 6. 7. public class FatoracaoBO { 8. private static List<Long> primos; 9. private static long sinalUltimo = 1; 10. public static String fatorar (long numero) { 11. String resultado = null; 12. 13. if (numero == 0) { 14. resultado = "0"; 15. } 16. else { 17. if (numero > 0 && numero < 3) { 18. resultado = Long.toString(numero); 19. } 20. else {

Pgina 24 de 84
21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. Long valor = numero; if (numero < 0) { sinalUltimo = -1; valor = numero * (-1); } primos = crivo(valor); resultado = calcular(valor); } } return resultado; } private static String calcular(Long numero) { String resultado = ""; Long valor = numero; Iterator<Long> it = primos.iterator(); Long primo = it.next(); while (valor > 1) { long resto = valor % primo; if (resto > 0) { primo = it.next(); } else { if (resultado.length() > 0) { resultado += "x"; } valor = valor / primo; if (valor == 1) { primo = primo * sinalUltimo; } resultado += Long.toString(primo); } } return resultado; } private static List<Long> crivo (long n) { List<Long> lprimos = new ArrayList<Long>(); for (long x = 2; x <= n; x++) { lprimos.add(x); } long p = 2; Iterator<Long> it = lprimos.iterator(); while (Math.pow((double)p,2) <= n) { int m = 2; while (m*p <= n) { it = lprimos.iterator(); while (it.hasNext()) { Long valor = it.next(); if (valor==(m*p)) { it.remove(); break; } } m++; } it = lprimos.iterator(); while (it.hasNext()) { Long valor = it.next();

Pgina 25 de 84
87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. } if (valor > p) { p = valor; break; } } } return lprimos; }

Lio 6: Internacionalizao e localizao


Internacionalizao i18n significa Internationalization, ou internacionalizao, que preparar uma aplicao para vrios idiomas e/ou culturas. l10n significa Localization, ou localizao, que adaptar uma aplicao internacionalizada para um determinado idioma / cultura. So aspectos muito importantes em um projeto de software, principalmente hoje em dia, com a economia globalizada. Talvez voc j tenha ouvido falar nesses termos, porm, o que talvez no saiba, que h muito mais alm da simples traduo dos termos (o que pode ser feito no Google Translator!). As prprias palavras utilizadas, a ordem da escrita (de trs para frente ou vertical), as imagens que voc est utilizando, enfim, diversos itens podem ser mal interpretados em suas aplicaes. muito difcil internacionalizar uma aplicao, embora a API do Android oferea algumas facilidades, o problema social e humano. Na verdade, existem vrias empresas, como a RS Globalization, que oferecem servio de internacionalizao de produtos. Para ter uma ideia, veja "checklist" da comunidade do OpenOffice: Se a caracterstica ser traduzida para um idioma com ordem da direita para a esquerda, seu layout deve ser examinado literalmente utilizando um espelho. A ordem das palavras (adjetivos, pronomes e substantivos) pode variar de um idioma para outro. Eu me assegurei que no existem elementos GUI dentro de textos? A equipe examinou com cuidado a internacionalizao de um componente de terceiros, antes de utiliz-lo dentro do seu produto? As figuras humanas, partes do corpo e especialmente mos, foram evitados a todo custo? A nica figura aceitvel aquele bonequinho utilizado em banheiros, sem cabelo, sem roupas, sem mos e sem dedos. Mos: nem tente! No existe uma s posio de mos que no seja ofensiva em algum lugar da Terra. E no assuma que exista uma posio com significado universal, como o sinal de "ok", por exemplo. Foram evitadas figuras que contenham palavras? Especialmente trocadilhos ou representaes de palavras? Voc ser certificou que um nico cone no seja utilizado com significados diferentes? O texto escolhido para a interface de usurio deve refletir um produto internacional. Evite jarges, regionalismos, textos "bonitinhos" e humor.

Alm disto, outros itens importantes so: cores, figuras de animais e sons. Muito cuidado com eles! Procure saber se est utilizando cores prprias (em alguns lugares, a cor da bandeira do vizinho ofensiva!) Figuras de animais so extremamente complicadas, por exemplo, ces, que so animais de estimao por aqui, podem significar alimento em outro lugar! E sons? Gemidos, gritos, sussurros, e at mesmo "bips" podem ser considerados ofensivos.

Pgina 26 de 84
Localizao Uma vez que sua aplicao esteja internacionalizada, ou seja, no mnimo: No existam literais "string" dentro do cdigo-fonte No existam literais "string" dentro de elementos de layout

Para que seja possvel fazer a localizao (L10N) de uma aplicao, necessrio que ela esteja preparada para isto, ou seja, Internacionalizada (i18n). Isto feito atravs de algumas atitudes importantes, a comear pelos textos exibidos. Vamos ver um exemplo:
1. AlertDialog.Builder construtor = new AlertDialog.Builder(this); 2. construtor.setMessage(O registro foi alterado) 3. .setPositiveButton("Ok", new DialogInterface.OnClickListener() { 4. public void onClick(DialogInterface dialog, int id) { 5. // comandos... 6. } 7. }); 8. AlertDialog alert = construtor.create(); 9. alert.show();

Neste exemplo, temos dois literais string dentro de uma caixa de dilogo. Se decidirmos criar uma verso para o Ingls (ou Francs), teremos que alterar o cdigo-fonte da aplicao, o que tornar difcil manter vrias verses simultaneamente. Vejamos outro exemplo ruim:
1. <TextView 2. style="@style/titulo_link.vermelho" 3. android:layout_width="fill_parent" 4. android:layout_height="wrap_content" 5. android:text="Informe seu nome" 6. android:onClick="clicouLinear" 7. />

Repare que informamos um literal string na propriedade android:text. Isto tambm dificultar a criao de verses da aplicao para outros idiomas. Agora, abra o projeto Layouts e mude o idioma do simulador para en (Ingls): 1. 2. 3. 4. Abra o exemplo Layouts (http://layout-exercise.googlecode.com/svn/trunk/); Mande rodar; Saia da aplicao e selecione Custom locale; Selecione en english e mantenha pressionado o mouse (menu de contexto). Selecione Apply; 5. Agora, procure o cone da aplocao Layout exercise e rode novamente;

Voc ver que a aplicao automaticamente passou a exibir os elementos em Ingls (inclusive seu ttulo). Isto porque ela foi Localizada para Ingls. Na prtica, recomendamos que voc sempre crie a aplicao com o idioma default em Ingls, fazendo as localizaes necessrias. Desta forma, mesmo que voc no a tenha preparado para determinado idioma (Espanhol, por exemplo), ela aparecer em Ingls. Prticas para promover a Internacionalizao Para criar uma aplicao Internacionalizada, JAMAIS USE LITERAIS STRING! A no ser para criar mensagens de log, usando a classe android.util.Log (Log.d(Teste, Mensagem)). Crie STRING

Pgina 27 de 84
RESOURCES (ou recursos String), dentro da pasta res/values. Para isto, basta selecionar a pasta e escolher new / Android XML File, selecionando values. Dentro do arquivo de String resources, inicie com um TAG: <resources></resources> e acrescente os tags <string></string>, como no exemplo:
1. <?xml version="1.0" encoding="utf-8"?> 2. <resources> 3. <string name="hello">Hello World, Principal!</string> 4. <string name="app_name">Laboratorio2</string> 5. <string name="numero">Nmero</string> 6. <string name="resultado">Resultado</string> 7. <string name="fatorar">Fatorar</string> 8. </resources>

Temos vrios string resources criados e o ADT automaticamente os compilar dentro do arquivo .arsc, criando entradas dentro da classe R.java:
1. package br.com.thecodebakers.lab02; 2. 3. public final class R { 4. public static final class attr { 5. } 6. public static final class drawable { 7. public static final int icon=0x7f020000; 8. } 9. public static final class id { 10. public static final int txtNumero=0x7f050000; 11. } 12. public static final class layout { 13. public static final int main=0x7f030000; 14. } 15. public static final class string { 16. public static final int app_name=0x7f040001; 17. public static final int fatorar=0x7f040004; 18. public static final int hello=0x7f040000; 19. public static final int numero=0x7f040002; 20. public static final int resultado=0x7f040003; 21. } 22. }

Podemos utilizar string resources dentro de cdigo-fonte Java e dentro de arquivos de layout. Vamos ver como usar em um arquivo de 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. > 7. <TextView 8. android:layout_width="fill_parent" 9. android:layout_height="wrap_content" 10. android:text="@string/numero" 11. /> 12. <EditText 13. android:id="@+id/txtNumero" 14. android:layout_width="fill_parent" 15. android:layout_height="wrap_content" 16. /> 17. <Button 18. android:text="@string/fatorar" 19. android:onClick="fatorar"

Pgina 28 de 84
20. android:layout_width="wrap_content" 21. android:layout_height="wrap_content" 22. /> 23. </LinearLayout>

Note que usamos dois resource strings neste layout: um para o rtulo do campo a ser digitado e outro para o do boto de clculo. Ambos esto definidos dentro de res/values/strings.xml (o nome do arquivo no importa). Se usarmos @string/ e teclarmos CTRL+ESPAO, ser aberta uma lista de escolha contendo todos os resource strings declarados. Para usar resource strings dentro do cdigo-fonte Java, temos que obter uma instncia da classe : android.content.res.Resources desta forma: Resources <varivel> = this.getResources(); Vejamos um exemplo prtico:
1. public void fatorar(View view) { 2. Resources res = getResources(); 3. EditText txtNumero = (EditText) this.findViewById(R.id.txtNumero); 4. long numero = Long.valueOf(txtNumero.getText().toString()); 5. String resultado = FatoracaoBO.fatorar(numero); 6. new AlertDialog.Builder(this) 7. .setMessage(res.getString(R.string.resultado) + ": " + resultado) 8. .setNeutralButton("OK", new DialogInterface.OnClickListener() { 9. public void onClick(DialogInterface dialog, int which) { 10. } }).show(); 11. }

A classe Resources contm o mtodo getString() (entre outros), que nos permite obter o texto de um resource string, dado o seu ndice (dentro da tabela .arsc). Onde obtemos este nmero? Ah! Dentro da classe R.java! Como criar Localizao de uma aplicao Uma aplicao internacionalizada pode ser facilmente localizada. Toda a pasta res/values pode ser localizada desta forma: res/values-pt para portugus! Basta usarmos a tabela internacional de idiomas (ISO 639-1) e dialetos (ISO 3166-1) como sufixo do nome da pasta values. Exemplos: res/values-pt Portugus em geral. res/values-pt-rBR Portugus do Brasil (o r para informar que as duas letras a seguir so o cdigo da regio). res/values-en-rUS Ingls dos Estados Unidos. Uma vez criada a pasta do idioma, basta copiar os arquivos de recursos (estilos, strings, cores etc) para dentro dela e traduzir seu contedo. A pasta sem sufixo passa a ser a localizao default. Sugerimos que seja sempre em ingls. O emulador possui uma aplicao Custom Locale, que permite alterar o idioma dele. Se o pas / idioma no estiver l, possvel adicionar um. Neste caso, no usamos r. Exemplo: pt_BR. No s os values (estilos, strings etc) podem ser localizados, mas as imagens tambm. As pastas drawable tambm podem possuir o sufixo de pas e idioma. Devemos lembrar que certas imagens podem ter entendimento diferente, dependendo do pas.

Laboratrio 3

Pgina 29 de 84
Internacionalize o exerccio anterior, criando a verso para Portugus e deixando o Ingls como a localizao default. Teste em ambos os idiomas. Se for "jogar a toalha", temos o zip da soluo dentro do projeto: http://code.google.com/p/curso-basicothecodebakers/downloads

Lio 7: menus e estilos


Menu de opes Toda activity pode ter menus: Menu de opes (options menu) acionado pela tecla "menu" do dispositivo; Menu de contexto (context menu) acionado pelo "touch and hold";

Recupere o projeto "BioMago", que utilizamos nas lies anteriores (http://code.google.com/p/biomago/).

O menu de opes utilizado para opes gerais, que se aplicam Activity como um todo. Ele acionado quando o usurio aciona a tecla "menu" do dispositivo. O menu de contexto utilizado em listas (veremos mais adiante), quando vrios itens so exibidos simultaneamente. Ele se aplica a um s item. Devemos evitar colocar opes de item dentro do menu de opes e opes gerais dentro do menu de contexto. O Menu de Opes deve conter TODOS os comandos da Activity, independentemente se h botes para eles na tela. Ele a opo preferencial de comandos do usurio. Entre colocar um boto na tela e colocar um comando no menu, prefira sempre a segunda opo. Para criar um menu de opes, devemos criar um menu resource, que um arquivo Android XML, dentro da pasta: "res/menu". Apesar de ser possvel, no localizamos o menu em si, mas os Strings que ele exibe. Eis um arquivo de menu:
1. 2. 3. 4. 5. <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/mnuIncluirRegistro" android:title="@string/mnu_novo_registro" />

Pgina 30 de 84
6. 7. <item android:id="@+id/mnuAjuda" 8. android:title="@string/mnu_ajuda" /> 9. 10. 11. </menu>

Cada elemento "item" uma entrada de menu, cujo rtulo est na propriedade: "android: title". Note tambm que foram atribudos "ids" a cada elemento, de modo que possam ser referenciados no cdigo-fonte. Podemos ter cones no meu, mas teremos que fornecer as imagens, ou utilizar as que esto no Android. Por exemplo:

1. <?xml version="1.0" encoding="utf-8"?> 2. <menu xmlns:android="http://schemas.android.com/apk/res/android"> 3. 4. <item android:id="@+id/mnuIncluirRegistro" 5. android:icon="@android:drawable/ic_menu_add" 6. android:title="@string/mnu_novo_registro" /> 7. 8. <item android:id="@+id/mnuAjuda" 9. android:icon="@android:drawable/ic_menu_help" 10. android:title="@string/mnu_ajuda" /> 11. 12. 13. </menu>

S devemos ficar atentos porque os cones do Android podem variar, quando mudamos a plataforma ou a verso. Uma vez que criamos nosso menu resource, precisamos "infl-lo" dentro da Activity. E isto feito no "callback" "onCreateOptionsMenu()". Este "callback" invocado apenas uma nica vez, quando o menu precisa ser criado. Se voc quiser alterar o menu antes de exibi-lo, use o "callback": "opPrepareOptionsMenu()".

Pgina 31 de 84
1. 2. 3. 4. 5. 6. @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.menu_lista, menu); return true; }

Usamos a classe "android.view.MenuInflater" para transformar nosso XML de menu em uma estrutura de objetos de menu. claro que o identificador do nosso menu foi criado dentro da classe "R.java", bastando pass-lo no mtodo "inflate", juntamente com o menu recebido. Ao invs de fazer isto, poderamos criar o menu "na mo", preenchendo os itens necessrios dentro do "callback". Isto est fora do escopo deste curso e no recomendamos que seja feito. Agora s falta uma coisa: interceptar quando o usurio clicar em um item do menu! Como voc deve ter advinhado, h um "callback" para quando um item do menu de opes clicado: "onOptionsItemSelected() ". Eis o cdigo usado no projeto "BioMago:
1. @Override 2. public boolean onOptionsItemSelected(MenuItem item) { 3. switch (item.getItemId()) { 4. case R.id.mnuIncluirRegistro: 5. this.incluirRegistro(null); 6. return true; 7. case R.id.mnuAjuda: 8. Intent i = new Intent (this.getApplicationContext(), 9. Ajuda.class); 10. this.startActivity(i); 11. return true; 12. default: return super.onOptionsItemSelected(item); 13. } 14. }

Este "callback" recebe uma instncia de "android.view.MenuItem", classe que representa um item de menu. Se analisarmos a propriedade "id", atravs do seu "getter" ("item.getItemId()"), podemos comparar com os "ids" criados em nossa classe "R.java" (lembre-se: todo "id" criado tambm dentro da classe "R.java", e voc criou "ids" para os itens de menu dentro do XML!). A parte sobre menu de contexto veremos mais adiante. Agora hora de mais exerccios! Laboratrio 4 - Menu de opes Vamos criar uma nova Activity para a Ajuda: 1. Crie um novo arquivo de layout chamado: "ajuda.xml", dentro de "res/layout" (new / Android XML file layout); 2. Crie um bonito layout, com um texto explicativo sobre sua aplicao. Veja como fizemos no projeto BioMago; 3. Crie uma classe que estenda "android.app.Activity" e escreva seu "callback" "onCreate()", inicializando o seu layout. Veja o "callback" da activity principal; 4. Altere o arquivo "AndroidManifest.xml" para acrescentar a sua activity. Veja como o do BioMago foi feito;

Agora, vamos criar um menu resource: 1. Crie um string resource: "ajuda", com os textos apropriados em Portugus e Ingls!

Pgina 32 de 84
2. Crie uma pasta "menu", dentro da pasta "res"; 3. Selecione a pasta "menu" e crie um novo Android XML File, do tipo "menu"; 4. Coloque os itens: "novoRegistro" e "ajuda". Tenha cuidado com os "ids" e com os "titles". Use os strings que j existem;

Finalmente, vamos inflar o menu dentro do nosso cdigo-fonte: 1. No cdigo da Activity principal (Principal.java), adicione o "callback": "onCreateOptionsMenu()", conforme fizemos na apostila e no BioMago; 2. No mesmo cdigo, acrescente o "callback": "onOptionsItemSelected() ", conforme a apostila e o BioMago, alterando as opes do "switch" para: o calcular o fatorial; o invocar a activity de ajuda;

Se voc no conseguir fazer, relaxe! Ns j colocamos a soluo dentro do projeto do curso (http://code.google.com/p/curso-basico-thecodebakers/downloads/list). Estilo Um estilo um conjunto de propriedades que afetam a visualizao de um item. Podem ser definidas diretamente ou em um arquivo XML (similar ao conceito de CSS). Tambm existe o conceito de herana, onde um estilo "herda" de outros. Exemplo:
1. <style name="titulo_link" parent="@android:style/TextAppearance.Large"> 2. <item name="android:textColor">#ffffff</item> 3. <item name="android:typeface">monospace</item> 4. <item name="android:textStyle">bold</item> 5. <item name="android:layout_height">wrap_content</item> 6. <item name="android:clickable">true</item> 7. </style> 8. <style name="titulo_link.vermelho"> 9. <item name="android:textColor">#ff0000</item> 10. </style>

Podemos utilizar o estilo derivado em qualquer View:


1. 2. 3. 4. 5. 6. 7. <TextView style="@style/titulo_link.vermelho" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/linear" android:onClick="clicouLinear" />

Podemos definir vrias propriedades, dependendo do tipo de elemento, por exemplo: TextView / EditText "android:gravity" como alinhar o texto se ele for menor que a "View". Os valores possveis so: "top", "bottom", "left", "right", "center_vertical", "center_horizontal", "center", "fill_vertical", "fill_horizontal" etc; "android:height" altura da View. A unidade pode ser: px (pixels), dp (density-independent pixels), sp (scaled pixels basedos no tamanho de letra preferido), in (polegadas), mm (milmetros).;

Pgina 33 de 84
"android:textColor" uma cor em formato RGB Html (ou uma referncia a outro estilo); "android: textSize" tamanho da letra. Pode usar qualquer unidade das j mencionadas; "android:textStyle" "normal", "bold" ou "italic"; "android: typeFace" "normal", "sans", "serif" e "monospace" (**);

(**) Se voc quiser utilizar fontes externas, possvel carregar arquivos "TTF" - Trye Type Font, como "asset" e configurar em sua aplicao, Mas isto est fora do escopo deste curso. Os estilos podem ficar dentro de arquivos XML, localizados na pasta "res/values". Veja o projeto "Layouts".

Lio 8: Temas e imagens


Temas (Themes) Um Tema (ou "Theme") um conjunto de estilos aplicatos a uma Activity inteira (ou a uma aplicao inteira). definido como os estilos e pode ser aplicado a uma Activity (tag <activity>, do layout) ou aplicao inteira (tag <application>) no arquivo "AndroidManifest.xml". Abra o projeto "BioMago" novamente e veja o arquivo "AndroidManifest.xml":
1. <manifest xmlns:android="http://schemas.android.com/apk/res/android" 2. package="br.com.thecodebakers.biomago" 3. android:versionCode="01010001" 4. android:versionName="@string/NOME_VERSAO"> 5. 6. <uses-sdk android:minSdkVersion="7" /> 7. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 8. <application android:icon="@drawable/icon" android:label="@string/NOME_VERSAO"> 9. <activity android:name=".activities.main" 10. android:theme="@style/imagem" 11. android:label="@string/NOME_VERSAO"> 12. <intent-filter> 13. <action android:name="android.intent.action.MAIN" /> 14. <category android:name="android.intent.category.LAUNCHER" /> 15. </intent-filter> 16. </activity>

Note que aplicamos um tema chamado "imagem", que dever estar dentro de um arquivo Android XML, entre tags <style></style>, na pasta "res/values". Tambm dever existir uma entrada em "R.java", criada automaticamente. Eis o estilo:
1. <style name="imagem" parent="@android:style/Theme.Black"> 2. <item name="android:windowBackground">@drawable/fundo</item> 3. </style>

Ele usa o item "android:windowBackground", que permite informar um recurso de imagem (drawable) para ser aplcado ao fundo da tela. Se procurarmos nas pastas "res/drawable..." veremos um arquivo "fundo.png", que o fundo de tela, adaptado para formato "em p" (portrait -port) ou "deitado" (landscape -land). O Android j possui vrios temas que podemos usar, como: "@android:style/Theme.Black", ou podemos herdar duas propriedades com o atributo "Parent".

Pgina 34 de 84
Recursos de imagem Um "drawable" "algo que se pode desenhar", como uma imagem, por exemplo. Eles podem ser divididos por: resoluo, idioma, orientao da tela etc, separando os arquivos em pastas, de acordo com os atributos das imagens. As pastas "drawable" ficam dentro da pasta "res", em seu projeto. A cada imagem criada l, uma nova entrada criada na classe "R.java", sobre a qual ns j falamos anteriormente. Cada pasta "drawable" pode ter um ou mais sufixos, indicando ao Android qual o tipo de recurso que est l.

No projeto "BioMago" podemos ver estas pastas com seus recursos. Quando usamos uma imagem, o Android automaticamente seleciona de qual pasta ele vai pegar, dependendo da configurao do dispositivo mvel (ou do emulador) em uso. As telas dos dispositivos que executam aplicaes Android podem ter caractersticas totalmente diversas. A plataforma define como configurao bsica (Baseline Configuration): HVGA (320x480) em uma tela de 3.2" polegadas. recomendvel que voc inicie seu desenvolvimento sempre usando esta configurao. Para ver um exemplo, voc deve ter criado um AVD utilizando a configurao default ("HVGA"). Para iniciar um emulator fora do eclipse, abra uma janela console e digite: Para Linux 1 - Abra a pasta onde instalou o Android-SDK e v para a subpasta "tools"; 2 - Digite o comando: ./emulator -avd <nome do avd>; Para Windows 1 - Abra a pasta onde instalou o Android-SDK e v para a subpasta "tools"; 2 - Digite o comando: emulator -avd <nome do avd>; Agora, abra outra janela de comandos (deixando a original aberta) e veja se o seu emulador est sendo executado corretamente: Para Linux 1 - Abra a pasta onde instalou o Android-SDK e v para a subpasta "platform-tools"; 2 - Digite o comando: ./adb devices; Voc ver o seu emulador listado, incluindo qual Porta TCP ele est escutando. Depois, digite: ./adb logcat para ver o log de execuo. Para Windows 1 - Abra a pasta onde instalou o Android-SDK e v para a subpasta "platform-tools"; 2 - Digite o comando: adb devices; Voc ver o seu emulador listado, incluindo qual Porta TCP ele est escutando. Depois, digite: adb logcat para ver o log de execuo. muito importante aprender a utilizar corretamente o ADB, por fora do "eclipse". Voltando ao nosso assunto, as caractersticas das imagens podem ser: Tamanho Em polegadas medidas na diagonal maior; Taxa de aspecto Se muito mais alta ou muito mais larga que a configurao bsica;

Pgina 35 de 84
Resoluo Quantidade de pixels na tela, normalmente medida por pixels horizontais x pixels verticais 1 pixel = 1/72 de polegada Densidade Distribuio dos pixels pela tela medida em DPI; muito importante adaptar os recursos de imagem de acordo com o tipo de tela que estamos esperando. Podemos at mesmo delimitar o tipo de dispositivo no qual nosso aplicativo roda, por exemplo, dentro do arquivo "AndroidManifest.xml", podemos especificar o elemento <supports-screens></supports-screens>, que permite estabelecer os tamanhos de tela suportados e se nossa aplicao sabe lidar com diferentes densidades: "android:smallScreens" (true / false) "android:normalScreens (true / false) "android:largeScreens (true / false) "android:anyDensity" (true / false) se "true", o android desabilita seu mecanismo de escala automtica de pixels, confiando na aplicao para isto. Se "false", o android liga seu mecanismo e faz a escala automaica

Padres de sufixos Para simplificar a vida do desenvolvedor, a plataforma Android criou os seguintes padres: Para tamanho de tela: small, normal, large e xlarge; Para densidade: ldpi (baixa), mdpi (mdia), hdpi (alta) e xhdpi (muito alta); Podemos classificar os recursos de imagem, colocando-os nas pastas apropriadas. O Android fornece uma tabela com os vrios tipos de diretrios, de acordo com o tipo de tela ou idioma (http://developer.android.com/guide/topics/resources/providing-resources.html#AlternativeResources). Vamos reproduzir aqui os mais importantes:

sufixo Idioma e regio Tamanho de tela

Exemplo -pt, -pt-rBR, -en-rUS -small, -normal, -large, -xlarge

Descrio Idioma e regio dos recursos contidos nesta pasta

Recursos classificados por tamanho de tela

Orientao -port, -land

Orientao da tela, se est "em p": portrait, ou "deitada": landscape

Densidade -ldpi, De -mdpi, -hdpi, -xhdpi e -nodpi acordo com a densidade da tela. Se no for importante, use "nodpi"

Podemos classificar nossos recursos de imagem combinando estes sufixos. desde que seja EXATAMENTE NA ORDEM DA TABELA, por exemplo: "res/drawable-normal-port" : recursos de imagem para telas de tamanho normal () em orientao "em p"; "res/drawable-land-hdpi" : recursos de imagem para telas em orientao "deitada" e de alta densidade; Se tentarmos criar uma pasta assim: "res/drawable-ldpi-port", tomaremos um erro porque a ordem est incorreta. Todos os diretrios de recursos, como: layouts, values e drawables, podem ter sufixos, desde que a ordem seja seguida.

Pgina 36 de 84
Calculando a densidade Nada impede que voc use um s tamanho, independentemente de densidade ou tamanho da tela. O Android tenta carregar a imagem de acordo com a densidade da tela. Se no houver (por exemplo, voc no est usando o sufixo de densidade ou ento est usando "-nodpi") o Android tentar escalar a imagem para a densidade correta. Providenciando as imagens de acordo com a densidade, ns evitamos este trabalho e nos certificamos de que as imagens apaream corretamente, de acordo com a configurao bsica do Android. Os cones de lanamento (Launch Icons) so um bom exerccio de densidade. Eis o tamanho (em pixels) dos cones de lanamento, de acordo com a densidade da tela: ldpi: 36 x 36 pixels; mdpi: 48 x 48 pixels; hdpi: 72 x 72 pixels;

Podemos criar imagens de densidades e tamanhos diferentes utilizando programas grficos como o GIMP (http://www.gimp.org/) . Criamos uma cpia da imagem do cone em tamanho maior (72 x 72 pixels), colocamos na pasta "-drawable-hdpi". Depois, vamos diminuindo a imagem e colocando na pasta correspondente, at que tenhamos completado as trs.

Portrait / Landscape O Android automaticamente re-inicia nossa activity caso ocorra alguma mudana na configurao, como a orientao da tela, por exemplo. Neste caso, os mtodos "onDestroy()" e "onRestart()" sero invocados. No faz parte do escopo deste curso interceptar este comportamento. H certos dipos de imagens (e at layouts) que podem variar, dependendo da orientao da tela. Neste caso, podemos criar imagens de background adequadas e coloc-las nas pastas corretas ("-port" ou "-land"), respeitando a ordem mostrada na tabela anterior. Observaes Os nomes das imagens em cada subdiretrio de "drawable" devem ser iguais! No use: letras maisculas, hfens e caracteres especiais (incluindo espaos) nos nomes das imagens! Laboratrio 5 Este um "Big lab"! Dentro do projeto do curso (http://code.google.com/p/curso-basico-thecodebakers/downloads/list), h um arquivo "exemplos_temas.zip", que contm algumas sugestes de imagens, tanto de cones como de backgrounds, para que voc melhore sua aplicao de fatorao. Use sempre a ltima como ponto inicial. Neste laboratrio, voc vai: 1. Melhorar a aplicao, substituindo o boto por uma imagem (uma imagem "clicvel", como o programa "BioMago" usa para inserir novo registro ajuste a imagem de acordo com a densidade da tela; 2. Centralize a imagem e a caixa de texto. Crie estilos para ambos; 3. Crie fundos de tela para orientaes diferentes;

Tente fazer! Se estiver ameaado(a) de divrcio, no insista! Baixe logo a soluo (http://code.google.com/p/curso-basico-thecodebakers/downloads/list).

Pgina 37 de 84

Lio 9: Listas
Trabalhando com listas Listas so estruturas lineares contendo elementos, dentre os quais podemos escolher qualquer um com softtouch (toque curto) sobre ele. Tambm possvel selecionar o menu de contexto de um elemento com touchand-hold (toque longo) sobre ele.

Uma lista uma view do tipo "ListView", e implementada usando um Layout e um Adapter, dentro da classe Java da Activity. Os elementos de uma lista podem ser selecionados com soft-touch e podemos criar "Intents" contendo a posio do elemento, passando-a como "extra" para outra activity. Montagem de uma lista Abra o projeto "Layouts" (http://code.google.com/p/layout-exercise/) para ver a implementao bsica de uma view. Para comear, temos o arquivo de Layout:
1. <LinearLayout 2. 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. > 7. <ListView android:id="@android:id/list" 8. android:layout_width="fill_parent" 9. android:layout_height="fill_parent" 10. android:layout_weight="1" 11. android:background="#999999" 12. /> 13. 14. <RelativeLayout 15. android:layout_width="fill_parent" 16. android:layout_height="wrap_content" 17. > 18. <ImageView 19. android:layout_width="wrap_content" 20. android:layout_height="wrap_content"

Pgina 38 de 84
21. android:src="@drawable/terra_icone" 22. android:id="@+id/btnIncuir" 23. android:layout_centerHorizontal="true" 24. ></ImageView> 25. </RelativeLayout> 26. </LinearLayout>

Aqui, combinamos uma "ListVIew" e uma "ImageView", formando uma barra inferior. Isto feito atribuindo-se "1" ao "peso" (android:layout_weight) da "ListView". Assim, possvel a convivncia de ambos, conforme a figura apresentada anteriormente. O preenchimento da lista feito dentro do cdigo-fonte da "Activity":
1. public class ListaComBarra extends Activity { 2. private static final String TAG = "main"; 3. private ListView listView; 4. private String [] lv_arr = new String[3]; 5. private ArrayAdapter<String> adapter = null; 6. 7. @Override 8. public void onCreate(Bundle savedInstanceState) { 9. super.onCreate(savedInstanceState); 10. setContentView(R.layout.listascombarra); 11. listView = (ListView)findViewById(android.R.id.list); 12. listView.setTextFilterEnabled(true); 13. } 14. 15. @Override 16. protected void onStart() { 17. super.onStart(); 18. Resources res = this.getResources(); 19. lv_arr[0] = res.getString(R.string.lista1); 20. lv_arr[1] = res.getString(R.string.lista2); 21. lv_arr[2] = res.getString(R.string.lista3); 22. adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1 , lv_arr); 23. listView.setAdapter(adapter); 24. listView.setOnItemClickListener(this); 25. }

O evento "onStart()" invocado quando a Activity vai comear a receber inputs do usurio. Para comear, usamos o "id" da lista padro do Android: "android.R.id.list", porque usamos isto no Layout: "@android:d/list". um padro usar sempre este "id" porque podemos usar Activities especiais (ListActivity), que so assunto para outro curso. Criamos um vetor de Strings e o passamos para uma instncia de "android.widget.ArrayAdapter", que uma classe adaptadora para passar elementos para a ListView. No construtor, passamos uma referncia para a prpria Activity, um formato de layout e o prprio vetor. Pronto! A lista est construda.

Processando seleo de elementos Abra o projeto "BioMago". O usurio seleciona um elemento com "soft-touch", ou seja, clicando sobre o elemento desejado. Uma das maneiras de fazer isto implementar a interface: "android.widget.AdapterView.OnItemClickListener", que oferece o mtodo "onItemClick()" que nos permite saber qual item foi selecionado:
1. @Override 2. public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {

Pgina 39 de 84
3. 4. 5. 6. 7. // Houve um soft-touch na lista // Pegamos o elemento e mostramos o biorritmo dele. String elementoBruto = listaElementos.get(arg2); ... }

O terceiro argumento do mtodo (arg2) o ndice do elemento selecionado (comeando em zero). Atravs dele, podemos obter o elemento em uma varivel de instncia e passar para a outra Activity. No momento, preste ateno apenas a esta linha.

Intents com "extras" Podemos "pendurar" informao dentro dos "Intents", passando-as para a Activity seguinte. Por exemplo, eis um cdigo que invoca outra activity passando "extras":
1. 2. 3. 4. 5. Intent i = new Intent(this.getApplicationContext(), GrafBio.class); i.putExtra("nome", dados[0]); i.putExtra("data", dados[1]); this.startActivity(i);

Agora, veja o cdigo (da activity de destino) que recebe e trata a informao contida nos "extras":
1. Bundle extras = getIntent().getExtras(); 2. if (extras != null) { 3. imagem.setNome(extras.getString("nome"));

Um intent serve para invocar outra Activity da mesma aplicao ou de outra aplicao. Por enquanto, estamos utilizando apenas para invocar Activities internas. Ele tambm pode carregar "Strings" como argumentos para a Activity que est sendo invocada. Assim, podemos passar informaes entre Activities. Na Activity de origem, simplesmente usamos o mtodo "putExtra (String, String)", passando o nome e o valor do String que queremos "pendurar" no Intent. Na Activity de destino, pegamos o "Bundle" (android.os.Bundle) que veio anexado ao "Intent", O mtodo "getIntent()", da classe "Activity" nos permite obter uma referncia para o Intent passado para ela. Podemos at testar se veio algo ou no. O mtodo "getString()" da classe "Bundle", nos permite obter um string atravs do seu nome. Laboratrio 6 Listas Vamos alterar o projeto "Layouts" para usar uma lista na primeira Activity: 1. Altere o layout "main" para usar uma lista, ao invs de TextViews; 2. Na Activity "Principal.java", Crie um vetor de instncia e dentro de "onStart()" o preencha; 3. Implemente "OnItemClickListener" e o mtodo "onItemClick()"; Eis a imagem da nova "cara" da activity:

Pgina 40 de 84

Extra: se houver tempo, insira uma TextView em pelo menos duas das Activities, mostrando o String que veio no Extra. Passe o nome selecionado.

Tente fazer! Se estiver difcil, siga nosso conselho anterior: sente-se em posio de ltus e medite por 1 hora, fazendo o som: "OOOOMMMMMM"! Caso ainda no consiga, ento baixe logo a soluo (http://code.google.com/p/curso-basico-thecodebakers/downloads/list).

Lio 10: Context menu e instalao de aplicaes


Context Menu

um menu "popup", exibido pela ao touch-and-hold (pressionar e segurar) sobre um item, que pode ser um elemento de lista. Serve para aes executadas sobre um nico e determinado elemento.

Pgina 41 de 84

Um context menu criado como um recurso de menu, dentro da pasta "res/menu", da mesma maneira que o Options menu. Abra o projeto BioMago e veja o arquivo de menu "menu_contexto.xml":
1. 2. 3. 4. 5. 6. 7. 8. 9. <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/mnuCntExibir" android:title="@string/mnu_exibir_grafico" /> <item android:id="@+id/mnuCntExcluir" android:title="@string/mnu_excluir" /> </menu>

Criamos dois itens neste menu, com os string resources e ids bem identificados. Depois, na Activity, temos que: 1) criar o menu a partir do recurso e 2) interceptar o clique no menu de contexto. A primeira coisa sobrescrever o mtodo "onCreateContextMenu()", da classe "Activity":
1. 2. 3. 4. 5. 6. 7. 8. 9. @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); Resources res = getResources(); menu.setHeaderTitle(res.getString(R.string.mnu_titulo_menu)); MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.menu_contexto, menu); }

Usamos um "MenuInflater" da mesma maneira que fizemos com o Options Menu, passando o identificador do nosso Menu Resource para ele. A diferena que temos que informar um ttulo (que deve ser um resource string), pois menus de contexto sempre possuem um ttulo. No "onCreate()" da Activity, precisamos usar o mtodo: "registerForContextMenu(listView);" Passando a instncia da View que pode gerar menu de contexto. Neste caso, passamos a instncia da ListView que criamos em nosso Layout. Para interceptar o clique em um menu de contexto, sobrescrevemos o mtodo: "onContextItemSelected()", da classe "Activity". Eis o exemplo do BioMago:
1. @Override 2. public boolean onContextItemSelected(MenuItem item) { 3. AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo(); 4. final Elemento elemento = (Elemento)bo.getListaPessoas().get(info.position); 5. SimpleDateFormat sdf = (SimpleDateFormat) SimpleDateFormat.getDateInstance(); 6. sdf.applyPattern("dd/MM/yyyy"); 7. switch (item.getItemId()) { 8. case R.id.mnuCntExibir: 9. Intent i = new Intent(this.getApplicationContext(), GrafBio.class); 10. i.putExtra("nome", elemento.getNome()); 11. i.putExtra("data", sdf.format(elemento.getNascimento())); 12. this.startActivity(i); 13. return true; 14. case R.id.mnuCntExcluir: 15. Resources res = getResources(); 16. String txtSim = res.getString(R.string.txtSim); 17. String txtNao = res.getString(R.string.txtNao); 18. new AlertDialog.Builder(this).setMessage(R.string.msg_confirmar_exclusao) 19. .setPositiveButton(txtSim, new DialogInterface.OnClickListener() { 20. public void onClick(DialogInterface dialog, int which) { 21. comandarExclusao(elemento); 22. } }) 23. .setNegativeButton(txtNao, new DialogInterface.OnClickListener() {

Pgina 42 de 84
24. public void onClick(DialogInterface dialog, int which) { 25. return; 26. } }) 27. .show(); 28. 29. return true; 30. default: return super.onContextItemSelected(item); 31. } 32. }

Usamos um "AdapterContextMenuInfo" para obter a posio do elemento na lista. Pode ser a propriedade "id", que retorna o id do elemento na lista, ou a propriedade "position", que retorna a posio do elemento dentro da lista (comeando de zero). Tudo depende de como voc quer localizar o elemento selecionado.

Instalao de aplicaes no seu dispositivo mvel Podemos instalar aplicaes de 3 maneiras: A partir do Android Market Copiando para o aplicativo (via Astro ou semelhante) Utilizando o progama "ADB"

Enquanto voc estiver desenvolvendo e testando sua aplicao, melhor usar o utilitrio "ADB" Antes de passarmos o laboratrio, pensamos que seria o momento de conversar sobre mais funcionalidades do utilitrio "ADB". Como este um curso bsico, no queremos ficar perdendo tempo explicando detalhes que no interessam. O objetivo, neste momento, que voc crie aplicaes o mais rapidamente possvel. Porm, chegou a hora de instalarmos as aplicaes no seu dispositivo mvel (Celular ou Tablet). Se voc ainda no tem um dispositivo com Android, pode pular esta parte, embora possa utilizar o "ADB" para instalar em um emulador. O ADB fica na subpasta "platform-tools", dentro da pasta onde o Android SDK est instalado. Para utiliz-lo, necessrio abrir um "prompt de comandos" (ou janela "Terminal", se estiver utilizando Linux). Com o ADB podemos fazer diversas tarefas, entre elas: Instalar uma aplicao, seja em um dispositivo real ou em uma instncia de emulador; Encaminhar portas TCPForwarding Ports; Copiar arquivos de/para um dispositivo ou instncia de emulador; Abrir um Shell de comandos para o dispositivo ou emulador;

Ns j vimos como listar os dispositivos/emuladores ativos (adb devices), e tambm como ativar a janela de log (adb logcat). Agora, o que nos interessa como instalar aplicativos no seu dispositivo. O ADB uma aplicao distribuda, que roda em trs partes: Cliente: que permite enviar comandos ou pegar informaes de um dispositivo. O Cliente executado no seu desktop, ativado pelo comando "adb"; Servidor: que roda como um "daemon" (um servio) no seu desktop, de modo a permitir a comunicao entre o Cliente e o Dispositivo; Remoto: que roda como um "daemon" no dispositivo/emulador, se comunicando com o Servidor do seu desktop;

Pgina 43 de 84
Criao de certificado e assinatura de cdigo A assinatura digital de uma aplicao protege seus usurios ao garantir que ela autntica e que no foi adulterada. Antes de instalar necessrio assinar digitalmente o seu APK. Se voc no fizer isto, no poder instalar via ADB, embora seja possvel executar copiando o APK diretamente para seu dispositivo. A tendncia do projeto Android acabar com o uso de aplicaes sem assinatura digital, logo, recomendamos que voc sempre assine. Para assinar, preciso um certificado digital de Code Signing ou Assinatura de Cdigo (para saber mais: http://www.di.ufpe.br/~flash/ais98/cripto/criptografia.htm). Voc tem duas opes: adquirir um certificado emitido por uma Autoridade Certificadora reconhecida, ou criar um certificado auto-assinado. Para adquirir um certificado de assinatura de cdigo, voc pode procurar boas empresas, como estas abaixo: Serasa: Validade 12 meses: R$ 1.255,20 (*) Verisign: Validade 12 meses: US$ 499,00 (*) Thawte: Validade 12 meses: US$ 299,00 (*)

(*) A validade e os preos podem variar. Estas cotaes estavam disponveis on-line (nas pginas das empresas) e foram obtidas em Junho de 2011. Existem vrias empresas no Brasil, como a Comodo, a CertSolutions e a Certisign, e voc pode contatlas para obter informaes sobre certificados de Code Signing para aplicaes Java.

Certificado auto-assinado Voc pode emitir um certificado e assinar seu cdigo com ele. Isto garante que o seu cdigo no foi violado, mas apenas para voc mesmo. Porm, quem garante aos outros que voc quem diz ser? Quem garante que o Certificado realmente pertence a voc? por isso que recomendamos a aquisio e uso de um certificado de Assinatura de Cdigo emitido por uma empresa reconhecida. A compra e instalao de um certificado de Assinatura de Cdigo um processo complexo. Futuramente, quando tivermos "grana" para ter um destes, vamos publicar um artigo explicando este processo. Porm, os custos so altos. Ns mesmos no tivemos condies de comprar um certificado desses at agora! Estamos usando certificado auto-assinado em nossas aplicaes. E para desenvolvimento e teste esta a melhor opo. Se o seu produto for remunerado, ento pode comprar um Certificado e diluir o custo na formao do seu preo. O ADT ajuda voc a gerar um certificado auto assinado.

Gerando um pacote APK assinado Selecione o seu projeto na janela "Package Explorer" (ou "Project Explorer"), da sua workspace "eclipse", clique com o boto direito. No menu de contexto, selecione "Android tools" e "Export signed application package" (exportar pacote de aplicao assinado). A janela "Export Android Application" vai aparecer e voc dever selecionar seu projeto e clicar "next". Se voc j possui uma "keystore" (um arquivo que armazena certificados) e sabe a senha, ento s informar o caminho e digitar a senha. Agora, se ainda no tem uma "keystore", deve criar uma. Preencha os dados da tela e guarde muito bem a senha escolhida. Tome cuidado com o campo "Validity (years)", pois o Android Market exige que o certificado expire depois de 22 de Outubro de 2033. Pronto! Seu APK est gerado e assinado.

Pgina 44 de 84
Instalando no dispositivo via ADB Recomendamos fechar o "eclipse" e todas as instncias de emulador que estiverem ativas (a no ser que voc queira realmente instalar no emulador!) Depois, conecte o dispositivo na USB (veja o artigo: Desenvolvendo diretamente no dispositivo Android para saber detalhes da configurao USB). Abra uma janela "Prompt de comandos" (ou "Terminal", se for Linux). Abra a pasta onde o Android SDK est instalado e a subpasta "platform-tools". Digite o comando: adb install -r <path-do-APK-assinado> Se voc estiver utilizando Linux, digite "./" antes do "adb". Agora s executar diretamente a aplicao do seu dispositivo.

Laboratrio 7 Context menu Crie um context menu no projeto do lab 6. As opes sero: Mostrar Item e Ajuda. claro que voc vai ter que criar uma Activity de Ajuda tambm! Voc j sabe o que vamos dizer, no ? Tem que tentar! Como vai criar o prximo "Angry birds" se no se esforar para fazer os laboratrios? Bem, se esse argumento ainda no te convenceu, ento baixe a soluo (http://code.google.com/p/curso-basico-thecodebakers/downloads/list).

Lio 11: Persistencia e retorno de activities


Persistncia Podemos ler e gravar dados de vrias formas: Propriedades Bancos de Dados SQLite Arquivos de dados

Neste curso, vamos apenas gravar arquivos internos, na memria do aparelho. H vrias maneiras de ler e gravar dados em um dispositivo Android. Podemos gravar propriedades particulares da aplicao, propriedades compartilhadas, Bancos de Dados SQLite, arquivos dentro do dispositivo e arquivos dentro do SD Card. Neste curso, veremos como gravar arquivos dentro da memria interna do dispositivo. Por que? Porque ele fcil, simples e atende a 90% das necessidades. E a gravao de arquivos e a mesma sendo em armazenamento interno ou removvel. Deixaremos bancos de dados SQLite, propriedades e SD Card para outro curso.

Arquivos internos Para lidar com arquivos internos, usamos os mtodos: "openFileOutput" e "openFileInput", da classe Activity. Vamos ver como criar ou gravar arquivos:
1. FileOutputStream fos = 2. this.openFileOutput("dados.txt", 3. Context.MODE_PRIVATE); 4. OutputStreamWriter owr = new OutputStreamWriter(fos);

Pgina 45 de 84
5. 6. 7. 8. 9. 10. PrintWriter bw = new PrintWriter(owr); bw.println("BOM DIA"); bw.flush(); bw.close(); owr.close(); fos.close();

Um arquivo ser criado dentro de /data/data/./files: /data/data/br.com.thecodebakers.lab08/files. O mtodo "openFileOutput" pode criar arquivos dentro do diretrio interno da aplicao. O parmetro "mode" uma constante que significa:

Context.MODE_PRIVATE Vai criar um arquivo ou sobrescrever. E vai torn-lo privado da sua aplicao. Context.MODE_APPEND Vvai adicionar dados a um arquivo existente. Context.MODE__WORLD_READABLE Vpermite que outras aplocaes leiam o arquivo. Context.MODE_WORLD_WRITEABLE Vpermite que outras aplicaes gravem no arquivo. Para leitura, usamos o mtodo "openFileInput()", que retorna uma instncia de "FileInputStream" com o arquivo que desejamos ler:
1. FileInputStream fin = this.openFileInput("dados.txt"); 2. InputStreamReader ir = new InputStreamReader(fin); 3. BufferedReader br = new BufferedReader(ir); 4. StringBuffer texto = new StringBuffer(); 5. while (true) { 6. String lido = br.readLine(); 7. if (lido == null) { 8. break; 9. } 10. texto.append(lido); 11. }

SQLite SQLite um "engine" de banco de dados "embutido", ou seja, para ser utilizado DENTRO de outras aplicaes. Ele no possui servidor e apenas uma biblioteca de funes de banco de dados, com SQL e mecanismo de controle de transaes. Alm disto, totalmente domnio pblico. O Android j inclui a biblioteca do SQLite e possui alguns pacotes para facilitar seu uso. android.database.sqlite.*. Ns no vamos abordar SQLite neste curso (embora tenhamos a inteno de criar um curso separado), porm, se quiser ver um exemplo em ao, Baixe o projeto Hrcules Password Protector, adicionando o repositrio: http://code.google.com/p/hercules-password-protector.

Invocando activities e recebendo retorno No Android nada sncrono ou modal. Pois, ao construirmos aplicaes desta forma, prendemos recursos desnecessariamente, o que aumenta o consumo de bateria em dispositivos mveis. Sabemos que podemos passar "extras" dentro de um "Intent", mas como receber o resultado de outra Activity? Por exemplo, abrimos uma Activity para que o usurio selecione o contato desejado etc. Criamos um exemplo para demonstrar isto.

Pgina 46 de 84

Este processo envolve duas Activities: uma ser a principal e a outra ser a sub-activity. A principal invoca a sub e aguarda um resultado. Baixe o exemplo "sub.zip" (http://code.google.com/p/curso-basicothecodebakers/downloads/detail?name=sub.zip&can=2&q=). Veja o cdigo da Activity principal que invoca a sub-activity:
1. public void chamar(View view) { 2. Intent i = new Intent(this.getApplicationContext(),Outra.class); 3. startActivityForResult(i, CODIGO_SUBATIVIDADE); 4. }

O mtodo "startActivityForResult()" invoca um callback especial quando a sub-atividade finalizada: "onActivityResult()". Note que passamos um "Intent" e um literal inteiro. Atravs do "Intent", podemos identificar qual a Activity que est sendo invocada e podemos at mesmo passar parmetros. O literal "int" um cdigo para nos informar qual foi a Activity que invocou "onActivityResult()":
1. @Override 2. protected void onActivityResult(int requestCode, int resultCode, Intent data) { 3. super.onActivityResult(requestCode, resultCode, data); 4. if (requestCode == CODIGO_SUBATIVIDADE) { 5. Bundle extras = data.getExtras(); 6. String texto = extras.getString("valor"); 7. new AlertDialog.Builder(this) 8. .setMessage(texto) 9. .setTitle(R.string.titulo) 10. .setNeutralButton("OK", new DialogInterface.OnClickListener() { 11. public void onClick(DialogInterface dialog, int which) { 12. } 13. }) 14. .show(); 15. } 16. }

A sub-activity pode exibir uma lista de seleo ou mesmo fazer qualquer outra coisa. Ao concluir, ela ter que ser finalizada (invocando o mtodo "finish()"). Eis o nosso exemplo:
1. public void fechar (View view) { 2. txt = (EditText) this.findViewById(R.id.txt1); 3. Intent retorno = new Intent(); 4. retorno.putExtra("valor", txt.getText().toString()); 5. setResult(RESULT_OK, retorno); 6. finish(); 7. }

Desta forma, a Activity principal vai ser acionada e vai receber um "Intent" com dados.

Laboratrio 8 Arquivos Crie uma aplicao que leia e grave um arquivo texto. No momento em que a activity for iniciada, procure por um arquivo interno. Se ele existir, carregue uma EditText com seu contedo. Se no existir, mostre uma mensagem na EditText. O usurio poder digitar alguma coisa e clicar em um boto para salvar no arquivo. Eis uma proposta de Activity:

Pgina 47 de 84

Esse o ltimo laboratrio. O projeto final no ter soluo publicada, logo, sua ltima chance! Caso ainda no esteja convencido, ento baixe a soluo (http://code.google.com/p/curso-basicothecodebakers/downloads/list).

Projeto final Vamos criar uma lista de compras! Normalmente, quando vamos ao mercado, precisamos criar uma lista de compras, que voc possa utilizar no Supermercado. Deve haver uma lista de produtos mais comuns, os quais o usurio pode selecionar para comprar. Ao comprar, o produto deve ser marcado na lista, para evitar confuso. Voc pode criar um arquivo com a lista de itens a serem comprados e marcar se j comprou. Crie um arquivo interno para a lista e voc poder editar este arquivo. Lembre-se de criar imagens, cones, fundo etc. A beleza e usabilidade que sero os principais atrativos do seu software. Para este projeto no haver "cola"! Voc dever implementar sozinho(a), de modo a testar seus conhecimentos. Depois, se ficar "irado", faa upload para o Android Market! T na hora de transformar o tempo investido no curso em grana!

Curso de SQLite no Android

O foco desse curso o uso do SQLite no Android, mas para um melhor entendimento do produto, pretendemos mostrar o seu funcionamento independente do ambiente Android. Nas prximas lies nos concentraremos no nosso objetivo, que o seu uso no desenvolvimento de apps Android. Iniciamos o curso de SQLite fazendo a seguinte pergunta, por que devo aprender o SQLite? Bem, essa pergunta fcil de responder, o Android j vem com o suporte nativo ao banco de dados SQLite. Claro que no s por causa disso, mas que um grande motivo rsrsrs...

Pgina 48 de 84

Mas vamos ao que interessa, afinal, como funciona o SQLite? SQLite uma biblioteca desenvolvida em linguagem C que implementa um bando de dados SQL embutido. Programas que usam a biblioteca SQLite podem ter acesso a banco de dados SQL sem executar um processo RDBMS separado. Quais as suas principais caractersticas? Transaes atmicas, consistentes, isoladas e durveis, ou seja, segue o conceito de ACID; Configurao zero, no necessrio nenhuma configurao para usar o banco, tampouco administr-lo; Implementa o padro SQL92; Um banco de dados completo armazenado em um nico arquivo (.db) que multiplataforma; Suporte a base de dados com terabytes de dados armazenados; Cdigo pequeno e compacto, menor que 325KB se for configurado com todos os recursos ou 190Kb, se usar apenas algumas configuraes opcionais; API simples de usar; Sem dependncias externas para outras bibliotecas;

Tipos de dados Quando falamos de banco de dados pensamos logo nos tipos de dados. O SQLite trabalha com tipagem dinmica de dados, sim dinmica. O contedo pode ser armazenado como: INTEGER valores inteiros at 8 bytes REAL valores de ponto flutuante TEXT armazena strings (UTF-8, UTF-16BE e UTF-16LE) BLOB armazena dados binrios NULL um valor nulo

Analisando os tipos de dados acima, voc no sentiu falta de nada, cad o tipo booleano, e o tipo Date/Time? Bem, o SQLite armazena o tipo booleano como: 0 para falso, e 1 para verdadeiro. J o tipo Date/Time pode ser armazenado como: TEXT, REAL ou INTEGER. Onde podemos usar o SQLite, em que tipo de aplicao? Dispositivos e sistemas embarcados; Aplicaes client/server; Sites de pequeno e mdio porte; Aprendizado de banco de dados;

Quem usa o SQLite? Adobe; Apple, adivinha em quais produtos : iPhone, iPod Touch e iPad;

Pgina 49 de 84
Dropbox; Firefox; Google, podemos destacar os principais produtos: o Chrome e o Android; Microsoft; Skype;

No site do SQLite tem uma vasta lista de grandes empresas que utilizam o SQLite em seus produtos. Exercicio 1 Instalando o SQLite Como o foco desse curso o SQLite no Android, a seguir vamos apenas mostrar como instalar o SQLite no Linux/Windows para fins de testes e estudo. No Linux, voc pode baixar via APT-GET da seguinte maneira: # apt-get update # apt-get install sqlite ou pode baixar o arquivo a ltima verso do arquivo Precompiled Binaries for Linux do site oficial do SQLite. Escolhemos esse tipo de instalao por ser mais simples. No Windows, favor baixar o arquivo sqlite-shell-win32-x86-3070701.zip (verso atual) e executar sqlite.exe aps descompactar o arquivo zip. Se voc no gosta de executar comandos via shell, no se desespere, existem vrios aplicativos cliente para o SQLite. Eu sugiro a ferramenta SQLiteStudio por ser Open Source (GPL v2) e multiplataforma. Instando o SQLiteStudio no Linux Para executar a ferramenta no Linux, aps o download do arquivo sqlitestudio-<VERSION>.bin s necessrio dar permisso de execuo, conforme a seguir: chmod +x sqlitestudio-<VERSION>.bin Para permitir a execuo sem a necessidade de colocar o caminho completo do arquivo, renomeie o arquivo para sqlitestudio e inclua no PATH do seu Linux. No Windows, baixe o aplicativo sqlitestudio-<VERSION>.exe. No esquea de colocar no PATH para possibilitar a chamada de qualquer lugar (diretrio). Parabns!!! Voc acabou de instalar o SQLite na sua mquina. Se voc reparou o processo de instalao e configurao do SQLite muito simples e rpido. Para criar o seu banco de teste com o shell, execute o seguinte comando: ./sqlite3 curso Obs.: um arquivo .db ser gerado no mesmo path do shell. Para criar uma tabela entre com o comando create table no shell, conforme exemplo abaixo: sqlite>CREATE TABLE aluno (nome VARCHAR(100), email VARCHAR(100)); Para verificar se a tabela foi criada, execute o seguinte comando: sqlite> .tables Nas prximas lies, abordaremos o SQLite no Android com exemplos e exerccios.

Pgina 50 de 84

Lio 2: Conhecendo a API SQLite para Android


Como j dito na lio 1, o Android j tem suporte nativo ao banco de dados SQLite. Nesta lio pretendemos detalhar a API com exemplos prticos e didticos. Na primeira lio, criamos o banco de dados via shell ou usando a ferramenta SqliteStudio, o caminho poderia ser especificado no momento da criao do database. No ambiente Android, o banco fica armazenado num path especifico, conforme o nome do pacote da sua aplicao, conforme a seguinte estrutura de diretrios: /data/data/pacote.sua.app.android/databases. Isso significa que o banco de dados visvel apenas para a sua aplicao. Existe uma forma de acessar os bancos criados por outras aplicaes, atravs da API Content Providers, ela permite o compartilhamento dos dados de outras aplicaes. No abordaremos o acesso via ContentProviders nesse curso. Mas como eu crio o banco de dados no meu device, Tio? Muita calma nessa hora jovem mancebo! Na primeira lio, aprendemos como criar o banco de dados SQLite de formal manual (shell ou outra ferramenta), j imaginou toda vez que voc criar um banco de dados para a sua app Android ter que copiar o arquivo .db manualmente para a estrutura de diretrios citada acima. Imagina atualizar o banco em milhares de dispositivos, tarefa rdua n. Vimos ento que podemos criar o banco de dados no Android de duas maneiras: manualmente, copiando o .db gerado para o diretrio data/data/pacote.sua.app.android/databases, ou via programao. Nessa lio pretendemos abordar a criao de banco via programao, atravs das classes disponibilizadas na API do Android. Criando o banco de dados via programao Para criar o banco via programao necessrio o entendimento da API do Android, que disponiliza um conjunto de classes para acessar o SQLite. Inicialmente devemos criar uma classe que estenda a classe SQLiteOpenHelper, essa classe responsvel por gerenciar a criao e atualizao do banco de dados no Android. Abaixo vamos demonstrar um exemplo prtico baseado na aplicao HPP (Hercules Password Protector), onde criamos uma classe chamada DBHelper, que estende a classe SQLiteOpenHelper, consequentemente herda os seus mtodos: onCreate (cria o banco no momento de sua instalao) e onUpgrade (atualiza o banco). Segue a implementao completa da classe citada acima:
1. public 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. ; 14. 15. 16. 17. 18. 19. 20. 21. 22. class DBHelper extends SQLiteOpenHelper { private static final String DATABASE_NAME = "hppfree.db"; public static final int DATABASE_VERSION = 1; private static final String TABLE_NAME = "elemento"; public DBHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL("CREATE TABLE " + TABLE_NAME + "(uid TEXT, textoSecreto BLOB)") } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { if ((newVersion - oldVersion) > 2) { db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME); onCreate(db); } }

Pgina 51 de 84
23. 24. }

Bem, j mostramos a classe que vai gerenciar o banco, agora voc precisa entender como usar esse banco nas suas classes DAO . Primeiramente, na sua classe que far papel de DAO, ou algo parecido, voc deve criar uma instancia da classe DBHelper (criada anteriormente), e uma instancia da classe SQLiteDatabase. Essa classe disponibiliza mtodos para gerenciar um banco de dados SQLite. Ela possui mtodos para incluir, alterar, e executar outros comandos SQL. Repare no exemplo retirado do aplicativo HPP, criamos a classe DAO e nessa classe instanciamos a classe SQLiteDatabase, como tambm a classe DBHelper.
1. public class DBAdapter implements IDBAdapter { 2. 3. private SQLiteDatabase db = null; 4. private DBHelper dbHelper= null; 5. 6. public DBAdapter(Context context) { 7. dbHelper = new DBHelper(context); 8. } 9. 10. public long insert(String uuid, byte[] lob) throws SQLException{ 11. this.db = dbHelper.getWritableDatabase(); 12. ContentValues cv = new ContentValues(); 13. cv.put("uid", uuid); 14. cv.put("textoSecreto", lob); 15. long retorno = db.insert("elemento", null, cv); 16. db.close(); 17. return retorno; 18. } 19.

Ainda falando do trecho de cdigo acima, repare que no construtor do DAO criamos uma instancia do DBHelper e passamos como parmetro para a classe Helper (SQLiteOpenHelper) o contexto da aplicao:
1. public DBAdapter(Context context) { 2. dbHelper = new DBHelper(context); 3. }

Acredito que vendo uma implementao pronta muitas dvidas iniciais sero sanadas rapidamente. Mas como ficou o acesso e o insert dos dados? Para manipulao dos dados, leitura ou gravao, necessrio entender que existem dois mtodos da classe SQLiteOpenHelper, so eles: - getReadableDatabase() : cria ou abre um banco para leitura. - getWritableDatabase(): cria ou abre um banco para leitura e gravao Como vamos gravar uma informao na base dados, utilizamos o mtodo getWritableDatabase.
1. public long insert(String uuid, byte[] lob) throws SQLException{ 2. this.db = dbHelper.getWritableDatabase(); 3. ContentValues cv = new ContentValues(); 4. cv.put("uid", uuid); 5. cv.put("textoSecreto", lob); 6. long retorno = db.insert("elemento", null, cv); 7. db.close(); 8. return retorno; 9. }

Pgina 52 de 84

Repare que nesse caso necessrio usar a classe ContentValues, que representa um conjunto de valores dos comandos SQL. Outro ponto importante do mtodo insert chamada db.insert, que recebe o nome da tabela e o ContentValues como parmetro, e insere na base de dados. A diferena do mtodo update para o insert que ele recebe como parmetro uma string contendo o campo que representa a clusula Where, e os argumentos representados pelo sinal ?, conforme a seguir:
1. db.update("elemento", cv, "uid = ?", new String[]{ uid });

Todas as consultas retornam um tipo de objeto chamado Cursor, conforme o seguinte exemplo:
1. Cursor cursor = db.query("elemento", columns,null, null, null, null, null);

Onde os parmetros da query so: nome da tabela, array com os nomes das colunas, clusula Where, argumentos do where e as clusulas groupby, having e order by. O mtodo para listar os dados ficou assim:
1. ... 2. Cursor cursor = db.query("elemento", columns,null, null, null, null, null); 3. cursor.moveToFirst(); 4. 5. while(!cursor.isAfterLast()){ 6. Elemento elemento = new Elemento(); 7. elemento.setUUID(cursor.getString(0)); 8. elemento.setLob(cursor.getBlob(1)); 9. 10. lista.add(elemento); 11. cursor.moveToNext(); 12. } 13. ...

Nas prximas lies iniciaremos um exerccio prtico com o SQLite.

Lio 3 - Criando um CRUD no SQLite


Nas duas primeiras lies explicamos como funciona o SQLite como funciona a API do Android. Nesta lio vamos fazer um exerccio para fixar o contedo dado at o momento. Para agilizar um pouco o processo de criao de aplicao, vamos utilizar como fonte de consulta o cdigo do projeto HPP (Hercules Password Protector) disponvel no Google Code. No exerccio criaremos uma app que far o cadastro de um curso, e mostrar o resultado de uma busca na tela. Para facilitar o entendimento do exerccio criamos uma tela com dois campos: nome e descrio do curso, e depois botes: salvar e pesquisar, conforme abaixo:

Pgina 53 de 84

Em seguida, criaremos a Activity para suportar os mtodos da tela acima:


1. public class CursoSQLite extends Activity { 2. 3. private ICursoAdapter cursoAdappter ; 4. private String id; 5. 6. private EditText nome; 7. private EditText descricao; 8. private Elemento elemento; 9. 10. @Override 11. public void onCreate(Bundle savedInstanceState) { 12. super.onCreate(savedInstanceState); 13. setContentView(R.layout.main); 14. cursoAdappter = new CursoAdapter(this); 15. } 16. 17. public void salvar(View view) { 18. 19. nome = (EditText) findViewById(R.id.txtNome); 20. descricao = (EditText) findViewById(R.id.txtDescricao); 21. elemento = buscarPorNome(); 22. 23. elemento.setNome(nome.getText().toString()); 24. elemento.setDescricao(descricao.getText().toString()); 25. 26. //verfica se ja existe o valor 27. if (elemento == null) 28. { 29. cursoAdappter.incluir(elemento); 30. }else{ 31. cursoAdappter.alterar(elemento); 32. } 33. 34. } 35. 36. public void pesquisar (View view) { 37. nome = (EditText) findViewById(R.id.txtNome); 38. descricao = (EditText) findViewById(R.id.txtDescricao); 39. Elemento el = buscarPorNome();

Pgina 54 de 84
40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. } nome.setText(el.getNome()); descricao.setText(el.getDescricao()); this.id = el.getId().toString(); } public Elemento buscarPorNome() { elemento = cursoAdappter.buscarPorNome(nome.getText().toString()); return elemento; }

Os passos citados acima foram abordados com mais detalhes no nosso curso de programao ANDROID . Agora vamos para a parte que importa, que desenvolver um Adapter para acessar o banco de dados e executar as operaes de CRUD. Conforme dito nas lies anteriores! Precisamos criar uma classe Helper que herda de SQLiteOpenHelper. Lembre-se que essa classe responsvel pela criao(mtodo onCreate) e atualizao(mtodo onUpgrade) do banco. Voc pode copiar a classe desenvolvida para o projeto HPP, chamada DBHelper, ela estende a classe SQLiteOpenHelper. Segue a classe criada para o projeto curso SQLite:
1. public class CursoDBHelper extends SQLiteOpenHelper { 2. 3. private static final String DATABASE_NAME = "curso.db"; 4. public static final int DATABASE_VERSION = 1; 5. private static final String TABLE_NAME = "elemento"; 6. 7. public CursoDBHelper(Context context) { 8. super(context, DATABASE_NAME, null, DATABASE_VERSION); 9. } 10. 11. @Override 12. public void onCreate(SQLiteDatabase db) { 13. db.execSQL("CREATE TABLE " + TABLE_NAME + "(nome TEXT, descricao TEXT)"); 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. } } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { if ((newVersion - oldVersion) > 2) { db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME); onCreate(db); } }

Repare que o nome do banco foi definido na varivel DATABASE_NAME (curso.db) , a verso na DATABASE_VERSION e o nome da tabela em TABLE_NAME. Agora vamos criar a classe de acesso aos dados (famoso DAO) e as variveis para acesso s classes CursoHelper e SQLiteDatabase, conforme a seguir:
1. public class CursoAdapter { 2. private SQLiteDatabase db = null; 3. private CursoDBHelper cursoDBHelper= null;

Pgina 55 de 84
4. 5. 6. 7. } public CursoAdapter(Context context) { dbHelper = new CursoDBHelper(context); }

Note que no construtor da classe CursoAdapter recebe como parmetro o Context, que deve ser repassado para a classe CursoDBHelper. Em seguida, vamos criar os mtodos para incluso, alterao, excluso:
1. public long incluir(Elemento elemento) throws SQLException{ 2. this.db = cursoDBHelper.getWritableDatabase(); 3. ContentValues cv = new ContentValues(); 4. cv.put("nome", elemento.getNome()); 5. cv.put("descricao", elemento.getDescricao()); 6. long retorno = db.insert("elemento", null, cv); 7. db.close(); 8. Log.i(TAG, "Registro criado com sucesso."); 9. return retorno; 10. 11. } 12. 13. public int alterar (Elemento elemento) throws SQLException{ 14. this.db = cursoDBHelper.getWritableDatabase(); 15. ContentValues cv = new ContentValues(); 16. cv.put("id", elemento.getId()); 17. cv.put("nome", elemento.getNome()); 18. cv.put("descricao", elemento.getDescricao()); 19. int retorno = db.update("elemento", cv, "id = ?", new String[]{ elemento.ge tId().toString() }); 20. db.close(); 21. Log.i(TAG, "Registro atualizado com sucesso."); 22. return retorno; 23. 24. } 25. 26. 27. public int excluir(String id)throws SQLException{ 28. Log.i(TAG, "Esse voce deve implementar..."); 29. }

Na lio 2 j explicamos o que significa o ContentValues e o mtodo getWritableDatabase. Ao executar o mtodo query de SQLiteDatabase, a consulta retorna um objeto chamado Cursor, esse objeto responsvel pelo acesso ao resultado da consulta.
1. Cursor c = db.query("elemento", columns,"nome = ?", args, null, null, "nome");

Repare que o mtodo query recebe algumas informaes como parmetros, so eles: String nome tabela String[] colunas tabela String clausula where String[] parametros Where String clausula groupBy String clasusula having String orderBy (na consulta acima estamos ordenando o resultado pelo nome do curso).

Segue a listagem completa da consulta pelo nome do curso:

Pgina 56 de 84
1. public Elemento buscarPorNome(String id){ 2. Elemento curso; 3. String[] columns = new String[]{"id", "nome", "descricao"}; 4. String[] args = new String[]{id}; 5. Cursor c = db.query("elemento", columns,"nome = ?", args, null, null, "nome" ); 6. 7. c.moveToFirst(); 8. curso = new Elemento(); 9. curso.setId((int)c.getLong(0)); 10. curso.setNome(c.getString(1)); 11. curso.setDescricao(c.getString(2)); 12. return curso; 13. }

O cdigo fonte desse projeto foi disponibilizado para download no google code. Se voc quiser pode baixar pelo QR Code:

O exerccio dessa lio criar o boto excluir com o cdigo necessrio para excluir o registro da base de dados.

Gerenciando o SQLite atravs do ADB (Android Debug Bridge)


Mas o que diabos o ADB? uma ferramenta muita importante para quem quer trabalhar com desenvolvimento Android, que vem junto com o SDK Android. Com a ferramenta ADB voc consegue executar diversas operaes (instalar apps, montar o carto de memria, e at gerenciar os bancos de dados das aplicaes), via linha de comando no emulador. Para trabalhar com o SQLite no ADB, siga os seguintes passos: Antes de qualquer coisa, no seu dispositivo, ative a "Depurao via USB". Abra uma janela de terminal(Linux) ou cmd (no caso do Windows); V para o diretrio onde est instalado o seu SDK do Android, exemplo: cd /caminho_diretorio_do_sdk/platform-tools/ Altere o path caminho_diretorio_do_sdk para o caminho do SDK do Android da sua mquina. Agora s executar o ADB, conforme abaixo: ./adb shell Iniciei mas recebi um erro no terminal:

Pgina 57 de 84
> ~/android-sdk-linux_x86/platform-tools$ ./adb shell * daemon not running. starting it now on port 5037 * * daemon started successfully * error: device not found Isso normal!!! Voc tem um dispositivo acoplado na USB da sua mquina ou emulador est executando nesse momento? Seno, execute o emulador e rode o comando novamente. Mas tio eu no sei criar um emulador, ento leia o seguinte artigo e aprenda como fazer . Sugerimos tambm a leitura do artigo Desenvolvendo diretamente no seu aparelho, ele vai abrir um pouco mais a sua mente, vai por mim. Ainda no conseguiu criar uma instancia do emulador (AVD) no Eclipse, ento faz na mo vai. Entra numa janela de terminal, v para o diretrio caminho_diretorio_do_sdk/tools e execute seguinte comando shell: ./android create avd -n curso_sqlite2.1 -t 2 Aps executar o comando acima o seu AVD foi criado, conforme a seguir: Android 2.1-update1 is a basic Android platform. Do you wish to create a custom hardware profile [no] Created AVD 'curso_sqlite2.1' based on Android 2.1-update1, with the following hardware config: hw.lcd.density=240 vm.heapSize=24 Para saber qual target usar, voc pode listar todas as targets instaladas na sua mquina e escolher uma opo, no meu caso, eu escolhi a verso 2.1 do Android. Para listar as targets execute o seguinte comando: android list targets

Agora vamos acessar o seu banco de dados atravs do ADB: ./adb shell Lembre-se que o ADB fica no diretrio PATH_SEU_ANDROID_SDK/platform-tools, e execute o seguinte comando:

Pgina 58 de 84

./adb -s emulator-5554 shell Para maiores informaes acessar a documentao do ADB x SQLite Uma vez conectado ao emulador, digite o comando sqlite3. Ao invocar esse comando, possvel especificar o caminho do banco de dados que se deseja explorar. Aps se conectar no emulador, acesse o SQLite especificando o pacote do banco do curso: # sqlite3 /data/data/br.com.thecodebakers.cursosqlite/databases/curso SQLite version 3.5.9 Enter ".help" for instructions sqlite> Voc acabou de acessar o banco SQLite via ADB! Agora possvel criar suas tabelas e executar suas operaes de CRUD no seu banco de dados. Segue alguns comandos que podem te ajuda no dia a dia: sqlite> .tables Lista todas as tabelas do seu banco sqlite>.schema Lista o esquema do seu banco, ou voc pode listar apenas o esquema de uma tabela, usando o comando a seguir: sqlite>.schema curso Seguem abaixo alguns exemplos comandos SQL: Para criar uma tabela: sqlite> CREATE TABLE curso (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, nome TEXT NOT NULL,data DATE); Para inserir um registro na tabela criada: sqlite> INSERT INTO curso (nome, data) VALUES ('curso sqlite no android', '2011-08-22');

Se voc seguiu toda a lio, voc j fez todo o laboratrio baseado no ADB. A ideia desse minicurso foi mostrar rapidamente como foi funciona o SQLite no Android, no se prendendo aos detalhes do banco, mas ao ambiente de desenvolvimento Android Espero que esse curso agregue valor para o seu conhecimento e sua evoluo profissional.

Gostou do curso de SQLite, ento clique no boto abaixo e ajude a The Code Bakers a continuar a publicar artigos, cursos e projetos.

Pgina 59 de 84

PhoneGap
Lio 1: Praparando o terreno
PhoneGap um framework open source para facilitar a criao de aplicaes mveis. Ele distribudo nos termos da licena MIT (http://www.phonegap.com/about/license), e pode ser utilizado para criar apps pagas ou gratuitas. Ele utiliza HTML 5, JavaScript (com uma API de extenso), e CSS, e fornece um meio-de-campo para integrar sua app com as plataformas suportadas: Android; iOS (iPhone, iPad, iPod); BlackBerry; WebOS (HP Palm); Symbian;

Mas ento, por que eu simplesmente no fao a pgina HTML sem usar o PhoneGap? No seria mais simples? A resposta sim, porm, no seria uma aplicao mvel. Voc teria problemas para distribu-la nas lojas especializadas (iTunes, Android Market etc). Alm disto, voc no teria acesso API PhoneGap, que permite fazer interface com os dispositivos. Por exemplo, como voc faria sua aplicao usar a cmera? E o GPS? Voc acabaria tendo que desenvolver uma camada nativa para cada tipo de aparelho, e adivinha s: exatamente o que o PhoneGap faz! Neste curso, vamos iniciar pela plataforma Android. Depois, vamos mostrar a parte especfica sobre iOS. Para os que quiserem outras plataformas, mostraremos tutoriais separados. Como funciona o processo de criao? Simples: 1. Crie um projeto, com pelo menos uma pgina chamada index.html. Seu projeto pode conter JavaScript (interno ou externo pgina), outras pginas, CSS, imagens etc. Ele deve ficar dentro de uma pasta www. Se quiser, pode usar o Git para criar e gerenciar seu projeto; 2. Use o mecanismo nativo (SDK) de cada plataforma, e crie um projeto. Infelizmente, cada uma tem suas caractersticas. Copie a pasta www para o local correto (depende da plataforma); 3. Compile e distribua!

O passo 1 muito importante, pois voc procurar separar seu projeto dos cdigos especficos de cada plataforma. Voc pode at escolher uma delas para usar seu ambiente, mas procure manter o mdulo www bem separado. Eu no sou programador! Preciso conhecer Java e Objective-C? Boa pergunta! Se voc conhece HTML 5 e arranha em JavaScript, j d para desenvolver uma app. Agora, infelizmente, necessrio fazer alguns ajustes, dependendo da plataforma. Algumas plataformas exigem maior trabalho de integrao, outras exigem menos, mas, infelizmente, alguma coisa voc vai ter que fazer. Outra coisa que pode fazer usar o PhoneGap Build! Assim, voc s se preocupa com o HTML 5 e JavaScript, deixando todo o trabalho de integrao cargo do servio, e recebe um pacote prontinho para rodar! Voc pode continuar a fazer o curso, se concentrando mais na parte de API e tcnicas de programao.

Pgina 60 de 84
Arrumando a casa Nesta primeira lio, vamos mostrar como instalar a plataforma (Android) e comear a criar uma aplicao. Se voc s pretende usar o PhoneGap Build, recomendamos que leia o tutorial: Como criar uma app em 5 minutos com o PhoneGap Build. Como dissemos anteriormente, vamos comear pela plataforma Android. Se voc quiser conhecer mais profundamente esta plataforma, lembro que temos um curso especfico sobre Android, o qual vamos utilizar para ensinar a baixar e instalar tudo. Aplicaes Android so desenvolvidas usando a linguagem Java, da Oracle. Logo, voc teve ter o Java Software Development Kit (Java SDK) instalado em sua mquina. Existe o Java Runtime Environment, que apenas executa aplicaes Java, mas voc precisa do compilador, logo, deve baixar e instalar o Java JDK. Depois, voc vai precisar de uma IDE (Integrated Development Environment), e ns vamos usar o eclipse. Finalmente, voc vai precisar do Kit de Desenvolvimento do PhoneGap. Para baixar e instalar o eclipse, o plug-in para Android (ADT) e o Android SDK, leia a lio 2 do curso bsico de Android: Lio 2: Ambiente de desenvolvimento. Ento voc deve ter o ambiente pronto para desenvolvimento. Agora, s falta baixar o Kit do PhoneGap, que pode ser obtido diretamente na pgina do PhoneGap, ou ento clicando nesse link diretamente: http://phonegap.googlecode.com/files/phonegap-0.9.6.zip. Ele multiplataforma, e tem duas pastas: __MACOSX e phonegap-0.9.6. Ns vamos usar esta ltima. Descompacte em um local do seu HD (pode extrair apenas a ltima pasta) e guarde esta localizao. Ns vamos nos referenciar a ela como $PHONEGAP_HOME mais tarde, porm, pode deixar o nome padro da pasta. O primeiro programa a gente nunca esquece! Quem diria que voc viraria um garoto (ou garota) de programa, heim? U? Por que o espanto? Estamos falando de programa de computador! Pensou que fosse o qu? Ns j amaciamos e partimos o bifinho para voc. Temos uma aplicao tima para servir de Hello World: http://gerador-de-desculpas-furadas.googlecode.com/files/ProjectExcuse.zip. s baixar e descompactar este arquivo ZIP, que contm uma pgina index.html. Normalmente, voc desenvolveria o seu prprio aplicativo, mas achamos que, para um primeiro contato, melhor ter algo pronto. Eu j tenho um jogo legal em flash! Ser que posso usar o PhoneGap para coloc-lo no iTunes e ganhar uma grana? Bem, temos boas e ms notcias. A boa que a comunidade PhoneGap est criando plugins para permitir o uso de Flash e tem algumas aplicaes tentando fazer isso em Android. A m notcia que a Apple no suporta Flash, logo, no sei se voc poder colocar sua aplicao no iTunes! Estude HTML 5, que tem muitos recursos que o Flash tinha. Se voc usar bem a combinao HTML 5 + JavaScript + CSS, vai poder fazer tudo o que faria com Flash. Bem, vamos criar logo nosso primeiro projeto PhoneGap, para rodar em plataforma Android. Lembrando que ns j temos um tutorial sobre o assunto: http://www.thecodebakers.org/2011/04/javasscript-noambiente-android.html. Primeiro passo: crie um projeto Android no eclipse. Abra o eclipse, crie uma nova workspace (se que j no fez isso quando instalou), e prepare-a para receber um projeto. Crie um novo projeto Android.

Pgina 61 de 84

A lio 4, do curso bsico, explica como fazer isto: Lio 4: Criando sua primeira aplicao Android. Segundo passo: adaptando seu projeto Android para receber o PhoneGap. P, eu no conheo eclipse! Calma, ns damos um jeito! Tem vrios tutoriais na Internet. Veja este: http://www.cin.ufpe.br/~phmb/ip/MaterialDeEnsino/IntroducaoAoEclipse/IntroducaoAoEclipse.htm. Voc conseguiu criar um projeto? timo! Ento, temos que fazer algumas alteraes para poder embutir nossa aplicao PhoneGap dentro do projeto. Para comear, crie duas pastas dentro do projeto: libs e assets/www (uma pasta www dentro de uma pasta assets). Para criar pastas em um projeto eclipse s selecion-lo com o boto direito, escolher new e folder. Seu projeto deve ficar como a figura:

Ficou assim? timo! Agora, abra a pasta $PHONEGAP_HOME/phonegap-x.x.x/Android (o x.x.x o nmero da verso. No nosso caso 0.9.6) e copie os arquivos: phonegap.x.x.x.jar (x.x.x o nmero da verso) para a pasta libs do seu projeto; phonegap.x.x.x.js (x.x.x o nmero da verso) para a subpasta www, dentro da pasta assets do seu projeto;

Agora, temos que adicionar as bibliotecas do PhoneGap ao projeto. Selecione o arquivo phonegap.x.x.x.jar (que est dentro de libs) e escolha: Build path... e Add to Build path. Existem outras formas de se fazer isto, mas esta a mais simples.

Bem, agora, sente-se em posio de ltus, endireite a coluna, repouse as mos sobre as pernas, respire fundo e murmure: OOOHMMMMMM! Faa isso por 10 minutos! necessrio porque voc vai mexer no

Pgina 62 de 84
cdigo-fonte Java do seu projeto! Ao criar o projeto, voc criou tambm uma classe Java, que a activity principal dele. No sabe o que activity? P, ns pedimos para voc ler as lies 2 e 4 do curso bsico... Voc no leu tudo? Ento volte e leia: Lio 2: Ambiente de desenvolvimento Lio 4: Criando sua primeira aplicao Android

Ela fica dentro da pasta src do projeto. Ao criar o projeto, voc criou um nome de pacote, normalmente, usamos o nome de domnio da empresa invertido, mais o nome do projeto. Em nosso caso, eu criei: org.thecodebakers.phonegap1. Dentro deste pacote est o arquivo-fonte em Java. Lembre-se que, ao criar o projeto, voc deu um nome para a activity principal. Veja a figura:

Ao dar um duplo-clique sobre o arquivo Java, abre-se uma janela de edio do lado direito, com o texto do arquivo. Localize a linha que diz: import e, logo abaixo dela, digite uma nova linha contendo: import com.phonegap.*;. Depois, localize a linha que diz: public class xxxxx extends Activity (o xxxx no importa!) e mude a palavra em negrito para: DroidGap. Finalmente, localize a linha que diz: setContentView(...); e a substitua por: super.loadUrl("file:///android_asset/www/index.html"); Seu cdigo deve ficar como este:
1. package org.thecodebakers.phonegap1; 2. 3. import android.app.Activity; 4. import android.os.Bundle; 5. import com.phonegap.*; 6. 7. public class Principal extends DroidGap { 8. /** Called when the activity is first created. */ 9. @Override 10. public void onCreate(Bundle savedInstanceState) { 11. super.onCreate(savedInstanceState); 12. super.loadUrl("file:///android_asset/www/index.html"); 13. } 14. }

Terceiro passo: copie seu aplicativo PhoneGap para dentro do projeto. Seu aplicativo PhoneGap pode ser totalmente desenvolvido fora do projeto Android. Neste caso, copie todos os arquivos para dentro da subpasta www, dentro da pasta assets, que voc criou na raiz do projeto. Em nosso exemplo, baixe a aplicao http://gerador-de-desculpasfuradas.googlecode.com/files/ProjectExcuse.zip, extraia o arquivo index.html e copie-o para dentro da subpasta assets/www.

Pgina 63 de 84

Quarto passo: rode e mostre para a Mame! Se voc leu tudo direitinho, ento j sabe o que um AVD, um emulador, no? Ento selecione seu projeto com o boto direito e escolha Run as... e Android Application e aguarde alguns porrilnios. Dependendo da sua mquina, vai demorar muito, a boa notcia que voc no precisa fechar o emulador para rodar novamente. Basta mant-lo aberto! Voc deve ver algo como isto:

o emulador com a sua aplicao PhoneGap executando! Agora s mostrar para todo mundo! O que falta? Certamente, faltam algumas coisas, entre elas: Colocar para rodar no seu celular ou tablet; Distribuir no Android Market; Converter para iPhone;

Mas vamos fazer como Jack, o estripador: por partes!

Lio 2: Entendendo o funcionamento do PhoneGap


Nesta lio, ainda estamos utilizando o PhoneGap para Android, embora a maioria dos conceitos seja para ambiente multi-plataforma. Em breve, teremos uma parte sobre as caractersticas especficas do iOS (iPad, iPhone etc). Vamos aprender como utilizar a API PhoneGap. O PhoneGap um framework que permite a voc desenvolver aplicaes em HTML 5 + JavaScript, com acesso aos recursos dos dispositivos mveis, utilizando uma API padronizada. Eis o que o PhoneGap expe para a camada JavaScript: Acelermetro (Accelerometer) - Usar o sensor de movimento do dispositivo; Cmera (Camera) - Capturar uma foto utilizando a cmera; Captura (Capture) - Capturar arquivos de mdia utilizando aplicaes de captura, por exemplo: gravador de udio; Bssola (Compass) - Obter a direo para onde o dispositivo est apontando; Conexo (Connection) - Verificar o estado da Rede e do celular; Contatos (Contacts) - Trabalhar com o arquivo de contatos do dispositivo; Dispositivo (Device) - Obter informaes especficas do dispositivo; Eventos (Events) - Observar e capturar eventos nativos atravs do JavaScript;

Pgina 64 de 84
Arquivo (File) - Lidar com o sistema de arquivos nativos atravs do JavaScript; Geolocalizao (Geolocation) - Tornar sua aplicao consciente de sua localizao; Media (Media) - Gravar e reproduzir arquivos de udio; Notificao (Notification) - Notificaes visuais, audveis e tcteis (vibrao) do dispositivo; Armazenamento (Storage) - Lidar com as opes de armazenamento nativas;

Logo, voc no precisa se preocupar em aprender a lidar com as caractersticas de cada equipamento individualmente. Porm, ser que d para desenvolver tudo assim? Caso voc queira fazer um processamento em segundo plano (ou background), ou ento queira usar uma caracterstica para a qual no existe o componente JavaScript do PhoneGap, como fazer? nesse momento que entra a arquitetura de plug-ins do PhoneGap.

Este diagrama vem do site de documentao do PhoneGap. Para desenvolver um plug-in, voc precisa criar duas camadas: um componente em cdigo nativo de cada dispositivo, e um componente JavaScript que expe sua funcionalidade para as aplicaes HTML 5. Plug-ins prontos Se voc quiser, pode baixar plug-ins prontos para suas necessidades, o repositrio de plug-ins do PhoneGap tem muita coisa, todos separados por plataforma. Um pequeno exemplo usando a API PhoneGap Vamos comear criando uma aplicao tpica PhoneGap. Embora voc possa utililizar qualquer HTML com JavaScript, existem alguns pr-requisitos para utilizar a API em toda sua plenitude. Crie um projeto Android no eclipse, como ensinamos na lio anterior. Dentro da pasta assets/www, crie um arquivo index.html. Eis o esqueleto geral de uma aplicao bsica:
1. <html> 2. <head> 3. <title>Integrando com a API PhoneGap</title> 4. <script type="text/javascript" charset="utf-8" src="phonegap.0.9.6.js" /> 5. </head> 6. <body> 7. <h3>Informaes</h3> 8. <div id="saida"> 9. <p>Inicializando o PhoneGap...</p> 10. </div> 11. </body> 12. </html>

Pgina 65 de 84
Note que estamos carregando o JavaScript do PhoneGap logo no incio. Agora, precisamos esperar o ambiente PhoneGap inicializar e depois carregamos as informaes dentro da div que criamos. Antes de mais nada, como vamos realmente utilizar a API PhoneGap neste programa, voc deve acrescentar as seguintes permisses no seu arquivo AndroidManifest.xml, que fica no raiz do projeto:
1. <uses-permission android:name="android.permission.INTERNET" /> 2. <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

Elas indicaro ao usurio que o seu programa tenta acessar a INTERNET do dispositivo, e tambm o estado da rede de comunicaes. Estas permisses devem ficar dentro do tag <manifest>:
1. <?xml version="1.0" encoding="utf-8"?> 2. <manifest xmlns:android="http://schemas.android.com/apk/res/android" 3. package="org.thecodebakers.phonegap.teste" 4. android:versionCode="1" 5. android:versionName="1.0"> 6. <uses-sdk android:minSdkVersion="7" /> 7. <uses-permission android:name="android.permission.INTERNET" /> 8. <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 9. <application android:icon="@drawable/icon" android:label="@string/app_name"> 10. <activity android:name=".Principal" 11. android:label="@string/app_name"> 12. <intent-filter> 13. <action android:name="android.intent.action.MAIN" /> 14. <category android:name="android.intent.category.LAUNCHER" /> 15. </intent-filter> 16. </activity> 17. </application> 18. </manifest>

Depois, interceptamos o evento deviceready, criado pelo PhoneGap, e colocamos nossa funo. Eis o cdigo-fonte (adaptado do existente na API do PhoneGap):
1. <html> 2. <head> 3. <title>Integrando com a API PhoneGap</title> 4. <script type="text/javascript" charset="utf-8" src="phonegap.0.9.6.js" /> 5. <script type="text/javascript" charset="utf-8"> 6. document.addEventListener("deviceready", exibirInfo, false); 7. function exibirInfo() { 8. var saida = document.getElementById("saida"); 9. saida.innerHTML = 'Device Name: ' + device.name + ' 10. ' + 11. 'Device PhoneGap: ' + device.phonegap + ' 12. ' + 13. 'Device Platform: ' + device.platform + ' 14. ' + 15. 'Device UUID: ' + device.uuid + ' 16. ' + 17. 'Device Version: ' + device.version + ' 18. '; 19. } 20. </script> 21. </head> 22. <body> 23. <h3>Informaes</h3> 24. <div id="saida"> 25. <p>Inicializando o PhoneGap...</p> 26. </div> 27. </body> 28. </html>

Se voc conhece JavaScript e HTML, ser fcil entender o que esta pgina faz. Quando o PhoneGap termina de inicializar (ele carregado pelo primeiro tag <script> da pgina, o evento deviceready ser levantado.

Pgina 66 de 84
E ento, nossa funo ser chamada. Logo, ela carregar o contedo da div saida. Para que este programa funcione, faltam duas coisinhas: primeiro, temos que alterar a classe Java da Activity, que foi criada automaticamente para o nosso projeto, de modo que ela invoque a nossa pgina HTML. E, em segundo lugar, temos que executar o programa em um AVD. Ah, voc no tem a menor ideia do que eu estou falando? Ento volte lio anterior e leia atentamente. Eis o cdigo-fonte da minha activity:
1. package org.thecodebakers.phonegap.teste; 2. 3. import com.phonegap.DroidGap; 4. 5. import android.app.Activity; 6. import android.os.Bundle; 7. 8. public class Principal extends DroidGap { 9. /** Called when the activity is first created. */ 10. @Override 11. public void onCreate(Bundle savedInstanceState) { 12. super.onCreate(savedInstanceState); 13. super.loadUrl("file:///android_asset/www/index.html"); 14. } 15. }

E, finalmente, eis o resultado da execuo do programa:

O nosso cdigo-fonte solicita API de Dispositivo as seguintes propriedades: device.name : o nome do produto (ou dispositivo); device.phonegap : verso do PhoneGap que est rodando; device.platform : qual o sistema operacional do dispositivo; device.uuid : o identificador universal do aparelho; device.version : verso do sistema operacional do dispositivo;

S isso? P, eu queria fazer mais! Ah, t bom. Ento vamos colocar um boto para dar uma vibrada no Celular, ok? Eu sei que pouco, mas temos que ir devagar. Eis o novo cdigo-fonte em HTML:
1. <html> 2. <head> 3. <title>Integrando com a API PhoneGap</title> 4. <script type="text/javascript" charset="utf-8" src="phonegap.0.9.6.js" /> 5. <script type="text/javascript" charset="utf-8"> 6. document.addEventListener("deviceready", exibirInfo, false); 7. function exibirInfo() { 8. var saida = document.getElementById("saida"); 9. saida.innerHTML = 'Device Name: ' + device.name + ' 10. ' +

Pgina 67 de 84
11. 'Device PhoneGap: ' + device.phonegap + ' 12. ' + 13. 'Device Platform: ' + device.platform + ' 14. ' + 15. 'Device UUID: ' + device.uuid + ' 16. ' + 17. 'Device Version: ' + device.version + ' 18. '; 19. } 20. function vibrar() { 21. navigator.notification.alert("Vibrando", 22. "Funcionou?", 23. "OK"); 24. 25. navigator.notification.vibrate(2000); 26. } 27. </script> 28. </head> 29. <body> 30. <h3>Informaes</h3> 31. <div id="saida"> 32. <p>Inicializando o PhoneGap...</p> 33. </div> 34. <input type="button" onclick="vibrar(); return false;" value="Vibrar" /> 35. </body> 36. </html>

Estamos utilizando a API notificaes, para mostar um alerta e fazer o dispositivo vibrar. Voc s vai sentir isso se colocar a aplicao rodando em seu Celular. Colocando para rodar em um Celular Android Ainda no vamos usar o Android Market! Para comear, gere um APK com certificado auto-assinado. Leia a partir do item Instalao de aplicaes no seu dispositivo mvel, da liao 10, do curso de Android bsico. Este o laboratrio desta lio. O projeto pode ser encontrado no Google Code: http://code.google.com/p/gerador-de-desculpas-furadas/downloads/list.

Usando plugins

O PhoneGap possui uma API padro bem completa, mas falta sempre alguma coisa... Por exemplo, Como compartilhar coisas no Facebook? Como enviar um e-mail? Essas funes so especficas de cada plataforma, logo, necessrio utilizar um plugin. Felizmente, para ns, o PhoneGap j possui uma boa biblioteca de plugins, que pode ser acessada no endereo: https://github.com/phonegap/phonegap-plugins. Eis os plugins que existiam no repositrio at a data de hoje (7 de Agosto de 2011): Analytics: Enviar estatsticas de visualizao de pginas no seu aplicativo para o Google Analytics

Pgina 68 de 84
BarcodeScanner: Como o prprio nome j diz, permite digitalizar cdigos de barra Bluetooth: Permite comunicao via bluetooth ChildBrowser: Cria um navegador "popup" com pginas externas, dentro da sua aplicao ClipboardManager: Integrao com a "Clipboard" nativa ContactView: Permite integrar com o Intent visualizador de contatos nativo do Android, ao invs de lidar com a Contacts API FileUploader: Para enviar arquivos do dispositivo a um servidor FtpClient: Como o prprio nome diz, um cliente para FTP PayPalPlugin: Este muito importante! Serve para voc enviar pagamentos, ou seja, implementar "inapp buy" PowerManagement: Permite acesso s funes de "power management" nativas Share: Cria um "Intent" ACTION_SEND, para compartilhar informaes SoftKeyboard: Mostra ou oculta o teclado StatusBarNotification: Permite escrever mensagens na barra de notificaes do Android TTS: Permite usar as caractersticas de "Text-to-speach". Podemos passar um texto para ser "falado" WebIntent: Permite invocar qualquer "Intent" do Android

Mas, como se desenvolve um plugin? Tenho certeza que est muito cedo para isto, mas, se insiste... Primeiramente, voc TEM que conhecer Java e TEM que saber programar em Android. Se j fez nosso Curso Bsico de Programao Android, ento d para comear. Primeiramente, voc tem que criar uma classe Java. que estenda com.phonegap.api.Plugin. Nesta classe, voc implementa o mtodo execute, desta forma:
1. public class MeuPlugIn extends Plugin { 2. public PluginResult execute(String 3. acao, JSONArray args, String callbackId) { 4. if (action.equals("acao")) { 5. // ... 6. // ... 7. } 8. } 9. }

Entre os argumentos que ele recebe, est o nome da ao que deve ser executada. Depois, precisamos fazer a ponte entre o JavaScript e a nossa classe. Temos que criar um objeto e um mtodo. Depois, para que o PhoneGap saiba que seu plugin existe, necessrio registrar nosso plugin com ele. Para isto, usamos um mtodo addConstructor que nos permite adicionar nosso plugin. Isto feito em um arquivo JavaScript:
1. var MeuPlugIn = function () {}; 2. MeuPlugIn.prototype.acao = function (params, success, fail) { 3. return PhoneGap.exec(success, fail, 'MeuPlugIn', 'acao', [params]); 4. }; 5. 6. PhoneGap.addConstructor(function () { 7. // Cria uma instncia do nosso plugin 8. PhoneGap.addPlugin('meuplugin', new MeuPlugIn()); 9. // Associa classe que executa o servio 10. PluginManager.addService('MeuPlugIn', 'org.thecodebakers.meuplugin'); 11. });

Para invocar um plugin, bastam duas coisas: 1 - Instanciar o PhoneGap e o plugin: <script type="text/javascript" charset="utf-8" src="phonegap.0.9.6.js" /> <script type="text/javascript" charset="utf-8" src="webintent.js" />

Pgina 69 de 84
2 No momento certo, invocar o plugin: window.plugins.meuplugin.acao({ arg1: 'val1', arg2: 'val2', // etc }); No vamos entrar em mais detalhes aqui porque no o momento. Melhorando o Gerador de Desculpas Furadas Lembra do programa que fizemos na primeira lio? Bem, vamos adicionar um boto para compartilhar a Desculpa Furada que ele criou. Para comear, crie um projeto Android (falamos sobre isso na primeira lio deste curso), com o cdigo do Gerador (http://gerador-de-desculpasfuradas.googlecode.com/files/ProjectExcuse.zip). Se voc fez a primeira lio deste curso, deve ter uma Workspace com o projeto j criado nela. Se no leu, ento leia a primeira lio. Como vamos compartilhar a desculpa gerada? Bem, para comear, vamos olhar a documentao da API do PhoneGap (http://docs.phonegap.com/). Se no acharmos nada que sirva, ento olhamos o repositrio de plugins (https://github.com/phonegap/phonegap-plugins/tree/master/Android). Achamos dois! Os plugins Share e WebIntent atendem ao nosso propsito. Porm, o plugin WebIntent mais completo e permite chamar qualquer Intent, incluindo aplicaes que tenhamos desenvolvido. Isto bem interessante, pois abre uma janela infinita de probabilidades. Vamos usar o WebIntent. Como se usa um plugin? Normalmente, o prprio autor d instrues, porm, resumindo: Copie o arquivo java para a pasta src do seu projeto, tomando cuidado de criar a subpasta de pacote que ele pede (neste caso: "src/com/borismus/webintent"); Copie o arquivo js para a pasta assets/www; Leia as instrues para saber como chamar a funo desejada;

O WebIntent foi criado por Boris Smus (http://smus.com/about), e ele possui um Blog no qual expe seus projetos: http://smus.com/android-phonegap-plugins. Vamos acessar o GitHub do projeto WebIntent, e baixar os dois arquivos (https://github.com/phonegap/phonegap-plugins/tree/master/Android/WebIntent ): WebIntent.java e webintent.js. O arquivo WebIntent.java possui uma declarao de pacote, logo, devemos criar os diretrios corretos dentro da pasta src (pode criar como Java Package) e copi-lo para l. O arquivo webintent.js deve ser copiado para a pasta assets/www. Alteraes no arquivo index.html Temos que adicionar o boot do plugin, logo abaixo da carga inicial do PhoneGap:
1. 2. 3. 4. 5. <html> <head> <title>Gerador de desculpas furadas&lt;/title> <script type="text/javascript" charset="utf-8" src="phonegap.0.9.6.js" /> <script type="text/javascript" charset="utf-8" src="webintent.js" />

E precisamos colocar um boto, que pegue o texto da div onde o gerador colocou a desculpa, e envie como EXTRA_TEXT no Intent. Voc no sabe o que o EXTRA_TEXT? Ento leia nosso tutorial Compartilhando imagens, videos e outros. Inclumos mais uma funo no nosso bloco de scripts:
1. function compartilhar() { 2. var extras = {}; 3. extras[WebIntent.EXTRA_SUBJECT] = "Querido(a) chefe!"; 4. extras[WebIntent.EXTRA_TEXT] = document.getElementById("output").innerHTML; 5. window.plugins.webintent.startActivity({ 6. action: WebIntent.ACTION_SEND, 7. type: 'text/plain', 8. extras: extras

Pgina 70 de 84
9. 10. 11. 12. 13. 14. 15. } }, function() {}, function() { alert('Erro ao compartilhar'); } );

Note que estamos criando uma coleo de argumentos, contento o EXTRA_SUBJECT (assunto da mensagem) e o EXTRA_TEXT (texto). Depois, passamos duas outras funes: uma para o evento de trmino da ao e outra para o caso de erro. No queremos ser avisados quando ele terminar, ento passamos uma funo vazia. Agora, s criar um boto:
1. &<input type="button" value="Compartilhar" 2. onclick="compartilhar()" />

Pronto! Eis a sada:

Se voc clicar no boto Compartilhar, o Intent ACTION_SEND ser invocado e mostrar as telas para voc escolher o canal e enviar, conforme j falamos no tutorial Compartilhando imagens, videos eoutros. Jogou a toalha? Que isso?! Assim voc me entristece... Tudo bem, ns j temos um projeto no Google Code com a resposta pronta. S que acrescentamos o AdMob tambm. Ento, voc mata o coelho com duas cassetadas: http://code.google.com/p/gerador-de-desculpas-furadas/source/checkout.

Lidando com arquivos


O PhoneGap possui uma API bem interessante, que te permite lidar com elementos do dispositivo sem se preocupar com detalhes de cada sistema operacional. Uma das interfaces desta API a "File", que permite lidar com arquivos. Nesta lio, vamos ver como lidar com esta interface, lendo e gravando arquivos no "sdcard". JSON - Ser o de "Sexta-feira 13"?

Pgina 71 de 84
Para entender legal a programao PhoneGap, necessrio entender um pouco de JavaScript, o que , digamos, meio "estressante". O JSON uma das causas deste "stress"... Segundo o meu site preferido, a Wikipedia: "JSON (com a pronncia ['dejzn]), um acrnimo para "JavaScript Object Notation", um formato leve para intercmbio de dados computacionais. JSON um subconjunto da notao de objeto de JavaScript, mas seu uso no requer Javascript exclusivamente." Para entender bem a programao PhoneGap necessrio saber criar expresses JSON. Outro site muito interessante o http://www.json.org/, que ensina tudo o que voc precisa saber sobre esta tcnica. Veja um exemplo:

{ "Aluno" : { "nome": "Joo", "notas": [ 8, 9, 7 ] } }

Ns podemos criar e passar objetos utilizando a sintaxe JSON. Ponteiros de funo

Em JavaScript muito comum passarmos ponteiros de funo como argumentos. Podemos fazer isto de duas maneiras: explcita e implcita. Da maneira explcita:
1. 2. 3. 4. 5. 6. 7. 8. window.resolveLocalFileSystemURI("file:///sdcard", <B>ok</B>, function () { alert('Erro ao tentar acessar o sdcard'); }); } <B>function ok(diretorio)</B> { ... }

Note que a funo "ok" foi passada como argumento, logo, o mtodo "resolveLocalFileSystemURI" pode invoc-la. Isto chamado de "callback", e um dos princpios da programao assncrona, caracterstica do PhoneGap. A maneira implcita declarar a funo dentro da chamada de outra:
1. window.resolveLocalFileSystemURI("file:///sdcard", ok, 2. <B>function () { 3. alert('Erro ao tentar acessar o sdcard'); 4. }</B> 5. );

o mesmo exemplo anterior, s que passamos outro ponteiro de funo. Esta funo implcita (nem tem nome) e d um alerta. Um projeto de exemplo Criamos um projeto de exemplo para esta lio, cujo zip pode ser baixado desta URL: http://code.google.com/p/gerador-de-desculpas-furadas/downloads/detail?name=FileProject.zip, ou ento clicando no QR code abaixo:

Pgina 72 de 84

Notas sobre desenvolvimento JavaScript

Desenvolver em JavaScript , no mnimo "nojento" =( ... Sem um plugin para JavaScript, voc no tem sintax hi-light, nem code completion no "eclipse". E o pior de tudo: no d para depurar cdigo JavaScript de maneira fcil no Android. Mas vamos mostrar como melhorar isso depois. Montando um projeto Se baixou o nosso projeto, voc pode utiliz-lo sem problemas. Mas, se quiser criar outro projeto do zero, recomendamos ver a primeira lio do curso, mas vamos repetir aqui as principais tarefas para preparar um projeto: 1. Criar uma pasta "www" dentro da pasta "assets". Copiar para ela o "phonegap.xxx.js" e a sua pgina "index.html", alm de qualquer javascript de plugin que voc use; 2. Criar uma pasta "libs" na raiz do projeto, e copiar para ela o arquivo "phonegap.xxx.jar"; 3. Adicionar o jar que voc acabou de copiar ao Build path do projeto; 4. Adicionar as permisses necessrias ao arquivo "AndroidManifest.xml"; 5. Modificar sua "activity" para exibir sua pgina "index.html"; As permisses bsicas devem ser acrescentadas ao tag "<manifest>" do arquivo "AndroidManifest.xml":
1. <uses-permission android:name="android.permission.INTERNET" /> 2. <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

Porm, existe uma permisso adicional, caso deseje gravar arquivos no "sdcard":
1. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Finalmente, modifique sua classe de "activity":


1. package org.thecodebakers.phonegap.filesample; 2. 3. import android.os.Bundle; 4. import com.phonegap.DroidGap; 5. 6. public class Principal extends DroidGap { 7. /** Called when the activity is first created. */ 8. @Override 9. public void onCreate(Bundle savedInstanceState) { 10. super.onCreate(savedInstanceState); 11. super.loadUrl("file:///android_asset/www/index.html"); 12. } 13. }

Pgina 73 de 84
Listando diretrio A API "File" possui alguns objetos interessantes, entre eles o DirectoryEntry, que representa uma entrada no diretrio do File System. Toda a API "File" do PhoneGap baseada na proposta de "File API", do W3C, uma proposta livre de protocolo e API de acesso a arquivos e diretrios em pginas Web. Vamos mostrar como obter a entrada de diretrio do "sdcard":
1. function gerar() { 2. window.requestFileSystem(LocalFileSystem.PERSISTENT, 3. 0, 4. function() {}, 5. function() { 6. alert('Erro ao tentar acessar o file system'); 7. } 8. ); 9. window.resolveLocalFileSystemURI("file:///sdcard", 10. ok, 11. function () { 12. alert('Erro ao tentar acessar o sdcard'); 13. } 14. ); 15. } 16. 17. function ok(diretorio) { 18. var txtListagem = diretorio.fullPath; 19. var leitor = diretorio.createReader(); 20. leitor.readEntries( 21. function(entries) { 22. var i; 23. for (i=0; i<entries.length; i++) { 24. console.log(entries[i].name); 25. txtListagem = txtListagem + "</br>"; 26. if (entries[i].isDirectory) { 27. txtListagem = txtListagem + "Diretrio: "; 28. } 29. else { 30. txtListagem = txtListagem + "Arquivo: "; 31. } 32. txtListagem = txtListagem + entries[i].name; 33. } 34. document.getElementById('output').innerHTML = txtListagem; 35. }, 36. function(erro) { 37. alert("Problema ao ler diretorio: " + erro.code); 38. } 39. ); 40. 41. }

Calma! Lembre-se de fazer uma meditao! Alis, recomendamos que voc acompanhe o cdigo-fonte pelo "eclipse", porque, mesmo usando o sintax hilight, as listagens de cdigo-fonte costumam ficar meio bagunadas. Mas simples. Primeiramente, usamos o mtodo "requestFileSystem" para obter acesso ao FS do Android, se tudo der certo, ns usamos o mtodo "resolveLocalFileSystemURI" para obter o diretrio "/sdcard/". Note que passamos a funo "ok" como "callback" de sucesso para este mtodo. Isto significa que, caso ele consiga obter o diretrio "/sdcard" ele dever chamar a nossa funo "ok", caso contrrio, dever mostrar um alerta de erro. A maioria das funes da API "File" recebe dois "callbacks" como argumentos: um para sucesso, que pode receber como argumento o objeto solicitado, e outro para falha, que recebe como argumento um objeto de erro, cuja propriedade "code" nos permite saber qual foi o problema, bastando verificar nesta lista do

Pgina 74 de 84
W3C: http://www.w3.org/TR/file-system-api/#error-code-descriptions. Em nossa funo "ok", ns pegamos o nome do diretrio e criamos um Reader para ler as entradas, com o mtodo "createReader": var leitor = diretorio.createReader(); Talvez o que fique meio estranho a linha seguinte: leitor.readEntries( function(entries) { O que estamos fazendo aqui? A sintaxe do mtodo "readEntries", do Objeto "DirectoryReader" : directoryReader.readEntries(callBackSucsso, callBackFalha); o que fazemos no resto do mtodo "ok", escrevemos os dois "callbacks" de maneira implcita. Os elementos que o DirectoryReader recebe podem ser "FileEntry" ou "DirectoryEntry", e ns testamos isso com os mtodos "isFile()" e "isDirectory()".

Lendo um arquivo Vamos mostrar o cdigo para ler o contedo de um arquivo e mostrar na pgina. Mas, antes disso, voc tem que aprender a criar um arquivo dentro do "sdcard" do emulador. Para isto, usamos o programa "adb": 1. 2. 3. 4. 5. Inicie o emulador no eclipse; Abra uma janela terminal (ou um prompt de comandos, no Windows); V para a pasta: "android-sdk-.../platform-tools"; Digite "./adb shell" no Linux (ou "adb shell" no Windows); Voc est na console do emulador. Agora s Linux! V para a pasta do "sdcard": "cd /sdcard"; 6. Agora, crie o arquivo com o comando: "cat > teste.txt", digite algumas linhas e, ao final, tecle <CTRL><Z>; Se voc rodar o programa de exemplo, ver que o arquivo "teste.txt" aparece na listagem do diretrio. Veja a figura:

Para ler o arquivo, temos que obter o "FileEntry" do arquivo desejado, o que fazemos com o mtodo "resolveLocalFileSystemURI" para localizar o arquvo ("/sdcard/teste.txt"). Depois, usamos o mtodo "file", do objeto "FileEntry" obtido, para podemos ler o contedo:
1. window.resolveLocalFileSystemURI("file:///sdcard/"+arquivo, 2. function (entradaArquivo) { 3. entradaArquivo.file( 4. function (arquivo) { 5. var leitor = new FileReader();

Pgina 75 de 84
6. leitor.onloadend = function(evt) { 7. document.getElementById('arquivo').innerHTML = 8. "<hr/>" + evt.target.result; 9. }; 10. leitor.readAsText(arquivo); 11. }, 12. function (erro) { 13. alert("Erro ao acessar o arquivo"); 14. } 15. ); 16. }, 17. function () { 18. alert('Erro ao tentar acessar o arquivo'); 19. });

Usamos um objeto "FileReader" para ler o arquivo. Seu funcionamento meio diferente do modelo de "callbacks" das outras funes da API. O mtodo "readAsText" l todo o contedo do arquivo. Porm, precisamos acrescentar um mtodo "onloadend" ao objeto FileReader, que ser chamado quando a leitura terminar. Esse comportamento inconsistente realmente atrapalha o desenvolvimento, no? O mtodo "onloadend" um tipo de "callback", que recebe um "evento" como argumento. A propriedade "evento".target.result contm o texto lido. Ao clicar o boto "ler Arquivo", seu contedo ser mostrado dentro de uma <DIV> que criamos.

Gravando um arquivo Podemos gravar e/ou criar um arquivo com o mtodo "getFile", do objeto DirectoryEntry. A sintaxe deste mtodo :
1. entrada.getFile([path do arquivo], 2. [opes], 3. [callback de sucesso], 4. [callback de falha]);

As opes so informadas atravs de um objeto JSON, e possuem algumas propriedades, como: "create" (se para criar o arquivo) e "exclusive" (se voc deseja acesso exclusivo). Para gravar, temos que obter um FileWriter sobre o arquivo, que nos permite gravar dados. O mtodo "createWriter" faz isto, e sua sintaxe :
1. entrada.createWriter( 2. [callback de sucesso], 3. [callback de falha]);

Laboratrio Sugiro que voc pegue o aplicativo de exemplo e faa as seguintes modificaes: Modifique a listagem do diretrio para colocar links nos arquivos e diretrios; Ao clicar no link, se for um arquivo de texto, mostre o contedo, se for um diretrio, entre nele e liste as entradas; Permita criar e gravar dados em qualquer arquivo;

Pgina 76 de 84

Usando contatos e atualizao para PhoneGap 1.0


Durante este curso, saiu a verso 1.0 do PhoneGap, que traz algumas novidades importantes. Nesta lio, vamos ver como utilizar mais um elemento da API PhoneGap, a parte de contatos, e tambm a atualizao para PhoneGap 1.0. Atualizao do PhoneGap

Antes de comearmos, se voc j tem um projeto criado, deve atualizar alguns arquivos. Baixe a nova verso do PhoneGap, que pode ser encontrada em: http://www.phonegap.com/download. O pacote contm a mesma estrutura dos anteriores. Localize a pasta "Android" e copie: phonegap-1.0.0.js para a pasta "assets/www" do seu projeto; phonegap-1.0.0.jar para a pasta "libs" do seu projeto (se no existir, crie a pasta); Remova os arquivos das verses anteriores; Retire o phonegap-0.9.x.jar do seu Build path; Coloque o phonegap-1.0.0.jar em seu Build path; Examine o cdigo HTML e substitua a verso do arquivo JS que voc est carregando, inclusive dos plugins;

Porm, agora o PhoneGap tem uma novidade: o arquivo "plugins.xml", que serve para registrar os plugins que voc vai usar, incluindo os nativos da API. Este arquivo vem na distribuio, dentro da pasta "Android/xml", e voc deve copi-lo para a pasta "res/xml" do seu projeto (se ela no existir, crie). Plugins antigos Se voc usa um plugin antigo, criado para as verses anteriores, do PhoneGap, pode ser que tome um erro ao tentar utiliz-lo. Isto se deve nova maneira de registrar plugins. Ao invs de usar o "addService()" dentro do "addConstructor()" no arquivo JavaScript do Plugin, temos que adicionar uma entrada no arquivo "plugins.xml". Vamos ver como fica o exemplo no nosso projeto de plugin: PGAndroidString. Baixe o arquivo zip da distribuio e vamos tentar atualizar o projeto de demonstrao para PhoneGap 1.0. Clique neste link: http://pgandroidstring.googlecode.com/files/pgandroidstring.zip e baixe o projeto. Depois, faa o seguinte: Extraia o arquivo "PGAndroidStringSample.jar"; Na workspace do eclipse, selecione: Import / General e "Existing projects into workspace"; Aponte para o arquivo jar;

Depois, atualize o PhoneGap conforme j ensinamos e tente rodar. O projeto no vai funcionar e voc vai tomar um erro de JavaScript. Para consertar isso, faa o seguinte: 1. Edite o arquivo JavaScript do Plugin: "pgandroidstring.js"; 2. Comente a linha que comea com "PluginManager.addService..."; 3. Adicione uma entrada no arquivo "res/xml/plugins.xml", com os mesmos dados da linha que voc comentou: <plugin name="PGAndroidString" value="org.thecodebakers.phonegap.plugins.androidstring.PGAndroidString" />; Agora, o plugin ser registrado automaticamente pelo PhoneGap, porm, voc ainda precisa carregar o JavaScript do plugin dentro de sua pgina "index.html", s que no deve invocar o "PluginManager.addService". Se quiser saber mais detalhes, Simon Mac Donald publicou em seu Blog um post sobre a atualizao para PhoneGap 1.0.

Pgina 77 de 84
API de contatos Ns criamos um projeto para explicar como funciona a API de contatos, pelo menos a parte bsica, que recuperar contatos do dispositivo Android. Voc pode baixar este projeto clicando neste link: http://geradorde-desculpas-furadas.googlecode.com/files/ProjectAula5.zip, ou clicando no QR Code abaixo.

A descrio completa da API de contatos pode ser encontrada na documentao do PhoneGap: http://docs.phonegap.com/phonegap_contacts_contacts.md.html. O elemento principal a classe "Contact", cujas principais propriedades so: id: Identificador. (string); displayName: Nome que exibido na lista. (string); phoneNumbers: Um vetor de telefones do usurios. (ContactField[]); emails: Um vetor de endereos de email do usurio. (ContactField[]);

O elemento "ContactField" uma classe que contm as propriedades:

type: Informa que tipo de dado ("casa", "comercial" etc). (string) value: Valor do campo. (string) pref: Se o valor preferido pelo usurio (telefone preferido, email preferido etc). (boolean)

Podemos obter contatos utilizando a funo assncrona "contacts.find()", criada pelo PhoneGap. Sua sintaxe : navigator.contacts.find([[colunas]],[[sucesso]],[[falha]],[[opes]]); Os argumentos desta funo: Colunas um vetor contendo os campos do contato desejados ("displayName", "emails", ...); Sucesso um objeto "function", ou o endereo de uma funo, chamada caso a busca tenha sido ok. Ela receber um vetor contendo os contatos encontrados; Falha um objeto "function", ou o endereo de uma funo, chamada caso tenha havido algum erro. Ela recebe o cdigo do erro como argumento; Opes uma instncia de "ContactFindOptions", uma classe que estabelece os critrios de busca;

Vamos ver como funciona isso dentro do arquivo "index.html", do projeto que criamos:
view plaincopy to clipboardprint?

1. function procurar() { 2. var opcoes = new ContactFindOptions(); 3. opcoes.filter = document.getElementById("nome").innerText; 4. opcoes.multiple = true; 5. var colunas = ["displayName", "emails"]; 6. navigator.contacts.find(colunas, 7. function(lista) { 8. var local = document.getElementById("output"); 9. local.innerHTML = " 10. Encontrados: " + lista.length; 11. for (var ix = 0; ix < lista.length; ix++) { 12. local.innerHTML += " 13. <b>" + lista[ix].displayName + "</b>";

Pgina 78 de 84
14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. } if (lista[ix].emails.length > 0) { local.innerHTML += "<ul>"; for (var iy = 0; iy < lista[ix].emails.length; iy++) { local.innerHTML += "<li>" + lista[ix].emails[iy].value; local.innerHTML += "</li>"; } local.innerHTML += "</ul>"; } } }, function(erro) { alert("Erro ao acessar os dados: " + erro); }, opcoes);

Antes de mais nada, criamos uma instncia de "ContactFindOptions", passando o valor digitado no elemento "nome" e a opo true, para retornar mltiplos resultados. Depois, na funo Callback de sucesso, ns simplesmente navegamos no vetor de contatos recebidos e, se houver email, no vetor de emails de cada contato, adicionando tudo ao HTML da div de sada. O projeto funciona e o resultado est na imagem a seguir:

Laboratrio Agora a sua vez! Lembra do plugin "WebIntent", que mostramos na lio 3? Bem, altere o programa desta lio, de modo que ele envie uma mensagem para o contato selecionado. s usar o WebIntent e o ACTION_SEND! Se voc preencher o campo EXTRA_EMAIL e use o mime type "text/plain".

Criando um plugin para PhoneGap


Esta a ltima lio do curso de PhoneGap, e chegou a hora de vermos como so criados os plugins. No vamos ficar "enrolando" vendo cada item da API, que j muito bem documentada no site do PhoneGap. Mostramos aqui o uso das principais funes e alguns exemplos de aplicaes prontas. Nesta lio, vamos trabalhar com o projeto "pgandroidstring", um plugin para PhoneGap que criamos recentemente.

Pgina 79 de 84
Extenses Apesar do PhoneGap possuir uma grande API, da qual j vimos algumas funes, as vezes necessrio acessar recursos do aparelho, e isto feito com o auxlio de plugins.

Um plugin composto por uma camada JavaScript que expe um Objeto nativo, criado e instanciado pelo framework do PhoneGap.

Primeiramente, temos que saber exatamente qual funcionalidade vamos expor... Por exemplo: acessar os recursos (resources) string de uma aplicao Android! Sim, e isto ajuda na "L10n" (Localization) da aplicao PhoneGap. A classe do Plugin Para comear, voc deve montar um projeto Android-Phonegap, como j ensinamos neste curso. Sua classe deve estender "com.phonegap.api.Plugin". e voc deve implementar o mtodo: public PluginResult execute(String action, JSONArray dados, String callBackId) Os argumentos so: "action": nome da ao que o plugin deve executar. Isto um acoplamento de lgica, o que ruim, mas assim que funciona; "dados": um vetor JSON contendo os argumentos passados para o plugin; "callBackId": quando seu plugin invoca cdigo JavaScript da aplicao;

O tipo JSONArray vem dentro da plataforma Android ("android.jar") e serve para encapsular um vetor JSON. Ns j falamos sobre ele aqui, lembra? Vamos ver o cdigo-fonte da nossa classe de Plugin:
1. package org.thecodebakers.phonegap.plugins.androidstring; 2. 3. import org.json.JSONArray; 4. import org.json.JSONException; 5. import org.json.JSONObject; 6. 7. import android.content.Context; 8. import android.content.res.Resources; 9. import android.util.Log; 10. 11. import com.phonegap.api.Plugin; 12. import com.phonegap.api.PluginResult; 13. import com.phonegap.api.PluginResult.Status; 14. 15. public class PGAndroidString extends Plugin { 16. 17. private static final String TAG = "PGAndroidString"; 18. @Override 19. public PluginResult execute(String action, 20. JSONArray dados, String arg2) { 21. Log.d(TAG, "Entrou no execute"); 22. 23. PluginResult result = null; 24. JSONObject resString = new JSONObject();

Pgina 80 de 84
25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. } 61. } if (action.equalsIgnoreCase("getResourceString")) { try { <B>Context ctx = PGAndroidStringSingleton.context;</B> Resources res = ctx.getResources(); <B>String packageName = ctx.getPackageName();</B> <B>JSONObject pesquisa = dados.getJSONObject(0);</B> <B>int resourceID = res.getIdentifier( pesquisa.getString("nome"), "string", packageName);</B> String texto = res.getString(resourceID); Log.d(TAG, "Retornando: " + texto); resString.put("value", texto); result = new PluginResult(Status.OK, resString); } catch (JSONException jsonEx) { Log.d(TAG, "JSON Exception "+ jsonEx.getMessage()); result = new PluginResult(Status.JSON_EXCEPTION); } catch (Resources.NotFoundException rex) { Log.e(TAG, "No achou o recurso"); try { resString.put("value", "No achou o recurso"); } catch (JSONException e) { e.printStackTrace(); } result = new PluginResult(Status.JSON_EXCEPTION, resString); } } else { result = new PluginResult(Status.INVALID_ACTION); Log.d(TAG, "acao invalida : "+action); } return result;

Calma que temos algumas coisas para comentar aqui! Para comear, temos um Singleton: Context ctx = PGAndroidStringSingleton.context; Para obter um Resource, ns normalmente usamos o mtodo Activity.getResources(), ou ento Context.getResources(). S que nossa classe no um componente nativo do Android, logo, no temos acesso ao contexto. Ento, criamos um Singleton s para armazenar o contexto da aplicao, que o usurio do plugin deve fazer em sua DroidGap:
1. public class Principal extends DroidGap { 2. @Override 3. public void onCreate(Bundle savedInstanceState) { 4. <B>PGAndroidStringSingleton.context = this.getApplicationContext();</B> 5. super.onCreate(savedInstanceState); 6. super.loadUrl("file:///android_asset/www/index.html"); 7. } 8. }

Desta forma, nosso cdigo consegue acessar o contexto e pegar os recursos necessrios. A segunda coisa "sinistra" a maneira como pegamos os argumentos. Note que o JSONArray contm um conjunto de JSONObjects. Pegamos o primeiro deles (ndice zero) e depois usamos a propriedade "nome" para encontrar o recurso. E como carregamos o recurso, se no temos acesso classe "R"? a que entra o mtodo "getIdentifier()", da classe Resources:

Pgina 81 de 84
Resources.getIdentifier([nome do recurso], [classe de recurso], [nome do pacote]); Em nosso caso, pegamos o nome do pacote do contexto, e o nome do recurso de dentro do JSONArray, s falta informarmos a classe do recurso, que "string". Ns devemos retornar uma instncia de PluginResult, cujo construtor permite passar o Status (constantes) e um JSONObject. Se tudo correr bem, ns criamos um JSONObject contendo a propriedade "value" e retornamos um PluginResult desta forma:
1. resString.put("value", texto); 2. result = new PluginResult(Status.OK, resString);

O arquivo JavaScript Para facilitar a vida do desenvolvedor, temos que criar um arquivo JavaScript que "encapsule" o acesso sua classe de plugin. A primeira coisa que temos que fazer criar uma instncia de um Objeto JavaScript:
1. var PGAndroidString = function() {}; 2. PGAndroidString.prototype.getstring = function(name,successCallback, failureCallbac k) { 3. return PhoneGap.exec( 4. successCallback, 5. failureCallback, 6. 'PGAndroidString', 7. 'getResourceString', 8. [name]); 9. };

O objeto JavaScript PGAndroidString recebeu uma funo chamada "getstring", que recebe: Um objeto JSON ("name"); Um objeto Function para o caso de sucesso; Um objeto Function para o caso de falha;

Ela repassa a chamada para a interface PhoneGap, que recebe tambm o nome da instncia de Objeto nativo a ser invocada. Note que o nome da ao "getResourceString" e o JSONArray ("[name]") so definidos nesta chamada. Porm, falta adicionar a nossa funo JavaScript coleo de plugins da interface JavaScript da aplicao. Isto feito adicionado ao construtor da interface PhoneGap o seguinte cdigo:
1. PhoneGap.addConstructor(function () { 2. PhoneGap.addPlugin('pgandroidstring', new PGAndroidString()); 3. PluginManager.addService('PGAndroidString', 'org.thecodebakers.phonegap.plugins.a ndroidstring.PGAndroidString'); 4. });

A primeira linha cria a instncia da classe "PGAndroidString" e a associa ao plugin "pgandroidstring". A segunda linha informa onde encontrar a classe "PGAndroidString". Note que se voc estiver utilizando PhoneGap 1.0 (ou superior) ter que comentar a segunda linha (PluginManager.addService...) e ter que criar um arquivo "res/xml/plugins.xml" contendo: <plugin name="PGAndroidString" value="org.thecodebakers.phonegap.plugins.androidstring.PGAndroidString" /> Conforme ensinamos na lio passada. Acessando o plugin Para usar o plugin, voc deve acrecentar em sua pgina HTML a carga do arquivo JavaScript que criamos.

Pgina 82 de 84
Isto feito logo aps carga do prprio PhoneGap: <script type="text/javascript" charset="utf-8" src="phonegap.0.9.6.js" /> <script type="text/javascript" charset="utf-8" src="pgandroidstring.js" /> Isto vale para PhoneGap 1.0 tambm! Para usar seu plugin, voc deve invocar a funo JavaScript que criou:
1. function pegar() { 2. window.plugins.pgandroidstring.getstring( 3. {nome: 'teste'}, 4. function(r){ 5. document.getElementById('output').innerHTML = r.value; 6. }, 7. function(e) { 8. alert(e.value); 9. document.getElementById('output').innerHTML = e.value; 10. }); 11. }

Concluindo Neste curso, ns cobrimos o bsico da programao PhoneGap e um pouco de recursos avanados tambm, como a criao de plugins. Esperamos que seja til para voc. Assim que pudermos, mostraremos como utilizar o PhoneGap no MAC.

Desenvolvendo diretamente no dispositivo Android


Este artigo se refere ao original em ingls: Using Hardware Devices. Voc sabe como executar uma aplicao no seu dispositivo? Ns j falamos sobre isso, mas o artigo ficou meio "escondido" dentro do Google Code.

Preparao do computador

Pgina 83 de 84
Windows Se voc usa Windows ento tem que instalar um driver USB para o seu dispositivo. Dependendo do tipo de dispositivo, voc tem um driver especfico. Se for Android Developer Phone (ADP), Nexus One, or Nexus S, ento acesse o link: http://developer.android.com/sdk/win-usb.html. Se seu dispositivo de outro fabricante, voc tem que procurar o driver correspondente. Por exemplo, se seu aparelho for um Sony Ericsson (o meu ), ento o site : http://developer.sonyericsson.com/wportal/devworld/search-downloads/android Se for outro aparelho, acesse o link abaixo e procure o link para seu driver: http://developer.android.com/sdk/oem-usb.html

Linux Ubuntu (o nosso caso) O Linux j tem o driver necessrio, porm, algumas configuraes so necessrias. Para comear, assumindo que seu Ubuntu verso 8 ou superior, crie um arquivo chamado: 51android.rules, dentro da pasta: /etc/udev/rules.d (ter que se logar como root ou usar sudo gedit...). Nesse arquivo, insira a seguinte linha: SUBSYSTEM=="usb", SYSFS{idVendor}=="0bb4", MODE="0666" O valor para SYSFS{idVendor} deve ser obtido de acordo com o seu fabricante:
Company USB Vendor ID 0502 413c 0489 091E 18d1 0bb4 12d1 0482 1004 22b8 0955 10A9 04e8 04dd 0fce 19D2 Acer Dell Foxconn Garmin-Asus Google HTC Huawei Kyocera LG Motorola Nvidia Pantech Samsung Sharp Sony Ericsson ZTE

O meu : SYSFS{idVendor}=="0fce", pois um Sony Ericsson. Digite o seguinte comando: chmod a+r /etc/udev/rules.d/51-android.rules E mate o processo "daemon" do ADB, re-executando-o como sudo:

Pgina 84 de 84
1. V para o diretrio platform-tools do seu Android SDK; 2. Execute: ./adb kill-server 3. Execute: sudo ./adb start-server Mantenha essa janela terminal aberta! Executando no eclipse Primeiramente, conecte o seu dispositivo. Abra o menu: Configuraes, depois Aplicativos e depois Desenvolvimento, Marque a opo Depurao USB. No eclipse, abra as configuraes de execuo (Run configurations) e desmarque os targets que estejam marcados. Isto far com que o eclipse selecione o seu celular. Agora, conecte o seu dispositivo e, na janela Terminal, digite: ./adb devices. Voc deve ver o seu dispositivo listado. Se estiver com interrogaes, porque voc no deu as permisses ou no est executando o daemon do ADB como root. Voc pode executar, depurar etc.

You might also like