apostila android

96
Treinamento Android Pág.: 1 de 96

Upload: andre-nascimento

Post on 18-Dec-2014

1.288 views

Category:

Technology


22 download

DESCRIPTION

Apostila de Android

TRANSCRIPT

Treinamento Android Pág.: 1 de 96

Treinamento Android Pág.: 2 de 96

Projeto Introdutório Android

Passo 01Execute a IDE do Eclipse para início do primeiro projeto Android. Ver Figura 01.

Figura 01

Passo 02Acessando o menu File | New | Project, ao se abrir a caixa de dialogo New no nó Android escolha Android Project conforme Figura 02, clicando em Next para prosseguir.

Conforme Figura 03, defina em Project Name um nome para o projeto. Aqui adotaremos ProjetoAula.

Ainda neta interface, Figura 03, desmarque a opção Use default location, clicando em seguida no botão Browser para escolhe um diretório de seu domínio para armazenar os fontes do projeto.

Figura 02 Figura 03

Treinamento Android Pág.: 3 de 96

Após definir o diretório do projeto, conforme Figura 05 demonstra, clique no botão Next para avançar.

Figura 04

Figura 05

Passo 03Selecione a versão do Framework Android desejável, aqui, estamos trabalhando com a API Android 4.0.3 (Figura 06) mas naturalmente, se instalado previamente poderíamos adotar uma outra versão.

Conforme demonstrado na caixa de dialogo representada pela Figura 07, no campo Package Name defina um nome para a NameSpace do projeto. Aqui adotamos Android.Aula por questões didáticas.

Repare ainda que devemos definir um nome para a primeira Activity (página ou tela se preferir) do projeto. Clique no botão Finish para encerrar. Por hora basta.

Figura 06 Figura 07

Treinamento Android Pág.: 4 de 96

Analisando a Estrutura de Arquivos de um Projeto Android

Primeiro observe a caixa de dialogo Project Explore com a estrutura de diretórios do projeto (Figura 01). Na sequência, definirmos alguns aspectos importantes sobre alguns arquivos nestes diretórios.

Figura 01

Item 01 - Arquivo main.xml – diretório ProjetoAula | res | layout

Selecionando este arquivo no diretório indicado, temos duas visões do mesmo no projeto no projeto. A primeira, que pode ser observada na Listagem 01, corresponde a implementação em XML dos controles existente na página. O comentário de cada instrução está na Tabela 01.

Listagem 01

1. <?xml version="1.0" encoding="utf-8"?>2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"3. android:layout_width="fill_parent"4. android:layout_height="fill_parent"5. android:orientation="vertical" >6.7. <TextView8. android:layout_width="fill_parent"9. android:layout_height="wrap_content"10. android:text="@string/hello" />11.12. </LinearLayout>

Treinamento Android Pág.: 5 de 96

Tabela 01

Linha Comentário

2 Abertura Tag LinearLayout, definindo o tipo de layout da página.

3 Propriedade que define a largura útil da página igual a totalidade da largura da device.

4 Propriedade que define a altura útil da página igual a totalidade da altura da device.

5Propriedade que define que os componentes dentro da Tag LinearLayout serão acomodados na vertical. Assim, controles aplicados a esta Tag, serão apresentados na ordem em que são colocados neste arquivo.

7 Abertura da Tag que representa um controle de texto, semelhante ao controle Label de outras tenologias.

8 Propriedade que define que o controle utilizará toda a área do Device no tocante a largura.

9 Propriedade que define que a altura do controle vai acompanhar a quantidade de texto atribuído a ele, havendo quebra de linha quantas vezes for necessário para acomodar tal texto.

10Define o texto apresentado pela Tag TextView. Ná prática, é atribuído a propriedade texto do controle, uma referência a uma variável de escopo de projeto constante no arquivo strings.XML que apresentaremos na sequência.

A segunda visão que temos do arquivo main.xml, é no modo gráfico, conforme Figura 02. Nela podemos aplicar visualmente controles no bom e velho conceito de “clicar e arrastar”.

Repara na parte inferior da tela as abas Graphical Layout e main.xml, onde alternamos entre o modo gráfico e texto, e ainda, no lado esquerdo e direito, respectivamente lista de controles e área de design.

Figura 02

Treinamento Android Pág.: 6 de 96

Para efeito de teste, observe a Figura 03 e Listagem 02 após aplicação de um controle Button a página main no modo gráfico. Procedendo ao contrário, ou seja, digitar o código de qualquer Tag dentro da Tag LinearLayout (no modo texto), promove também a apresentação do mesmo no modo gráfico.

Promova alguns teste e vamos em frente.

Figura 03

Listagem 02

1. <?xml version="1.0" encoding="utf-8"?>2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"3. android:layout_width="fill_parent"4. android:layout_height="fill_parent"5. android:orientation="vertical" >6.7. <TextView8. android:layout_width="fill_parent"9. android:layout_height="wrap_content"10. android:text="@string/hello" />11.12. <Button13. android:id="@+id/button1"14. android:layout_width="130dp"15. android:layout_height="wrap_content"16. android:text = "Button" />17.18. </LinearLayout>

Treinamento Android Pág.: 7 de 96

Item 02 - Arquivo strings.xml – diretório ProjetoAula | res | values

Neste arquivo do projeto mantemos as constantes do projeto. Na forma de Tag String dentro da Tag Resource, onde existe um elemento com um nome e um conteúdo, estes valores são utilizados nas Views, na verdade, atribuído normalmente a propriedade Text de controles. Por padrão, O Android reconhece que referência a constantes dentro do código XML de uma View sempre estão presente neste arquivo.

O seguinte exemplo define uma constante com nome “msg_bateria_esgotada”, que quando atribuído a propriedade Text de um controle, exibe o texto “A bateria do aparelho está se esgotando.”

<string name="msg_bateria_esgotada">A bateria do aparelho está se esgotando.</string>

Um exemplo de uso desta constante pode ser observado no trecho de código a seguir, extraído da página main.xml do nosso projeto de exemplo. Neste código, é atribuído a propriedade Text do controle (Tag) TextView não nomeado, uma referência ao tipo String (@string) e a qual constante de strings.xml deve ser recuperado o valor (texto).

android:text="@string/hello"

Neste exemplo, o texto que será exibido pelo controle é “Hello World, ProjetoAulaActivity!”, mas claro, podemos alterar este valor para a língua portuguesa por questões de comunicação. Confira esta instrução na linha 10 da Listagem 02, conferindo a definição da constante na linha 04 da Listagem 03 que se segue.

Listagem 03

1. <?xml version="1.0" encoding="utf-8"?>2. <resources>3. <string name="hello">Hello World, ProjetoAulaActivity!</string>4. <string name="app_name">ProjetoAula</string>5. </resources>

Além da visão texto do arquivo strings.xml, podemos, conforme Figura 04, visualizar e manter (adicionar, alterar e remover) constantes deste arquivo utilizando a interface visual. Confira!

Figura 04

Treinamento Android Pág.: 8 de 96

Item 03 - Diretórios drawable – diretório ProjetoAula | res | drawables-hdpi (ver outros)

Nestes diretório são armazenados as imagens utilizadas na interface das páginas do projeto. Como exemplo, vamos digitar instrução que se segue na Tag Button nomeado como button1:

android:background="@drawable/ic_launcher"

Confira o código final no arquivo consultando a Listagem 04 (arquivo main.xml) e o efeito imediato na visão Graphial Layout, demonstrado pela Figura 05.

Listagem 04

1. <?xml version="1.0" encoding="utf-8"?>2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"3. android:layout_width="fill_parent"4. android:layout_height="fill_parent"5. android:orientation="vertical" >6.7. <TextView8. // Código omitido aqui9.10. <Button11. android:id="@+id/button1"12. android:layout_width="138dp"13. android:layout_height="wrap_content"14. android:background="@drawable/ic_launcher" />15.16. </LinearLayout>

Figura 05

Treinamento Android Pág.: 9 de 96

Item 04 - Arquivo ProjetoAulaActivity.java – Diretório ProjetoAula | src | Android.Aula

O arquivo (classe) ProjetoAulaActivity.java é a Controller da View main.xml no melhor do padrão MVC. Naturalmente, toda lógica associado a View main.xml, para seu funcionamento fica implementado ai em código Java.

Confira o código na Listagem 05 e os comentários de cada linha na Tabela 02.

Listagem 05

1. package Android.Aula;2.3. import android.app.Activity;4. import android.os.Bundle;5.6. public class ProjetoAulaActivity extends Activity {7. /** Called when the activity is first created. */8. @Override9. public void onCreate(Bundle savedInstanceState) {10. super.onCreate(savedInstanceState);11. setContentView(R.layout.main);12. }13. }

Tabela 02

Linha Comentário

1 Referencia a que pacote (namespace) a classe pertence.

3 Import que referencia a classe Activity, que implementa métodos de uma Activity (atividade).

4 Import que referencia a classe Bundle (pacote) que permite referenciar objetos da View main.xml.

6 Define a classe como púlica extendendo-a com Activity.

8 Assinala que o método que segue a instrução será substituirá o método padrão da classe.

9 Assinatura do método onCreate da classe ProjetoAulaActivity.

10 Invoca o método onCreate da superclasse passando o mesmo Bundle como parâmetro.

11 Renderiza a View main.xml, referenciada a partir da classe “R”. Abordaremos a classe “R” na sequência.

Treinamento Android Pág.: 10 de 96

Item 05 - Classe R – Diretório ProjetoAula | gen | Android.Aula | R.java

É importante notar que a classe R é manipulada pelo plugin ADT. Quando se coloca qualquer arquivo no diretório res o plugin altera a classe R. java no diretório gen adicionando o ID do recurso à classe. Se você remover ou alterar qualquer recurso o R.java é automaticamente atualizado.

A lista a seguir representa as constantes de cada recurso conforme definido. A Figura 06 exibe esta estrutura, e, a Listagem 06 apresenta o código que expressa tais constantes.

R.drawable.nome_imagem

R.layout.nome_layout

R.string.nome_string

R.color.red

R.dimen.espaco

R.array.nome_array

R.style.nome_estilo

Figura 06

Listagem 06

1. package Android.Aula;

2. public final class R {3. public static final class attr {4. }5. public static final class drawable {6. public static final int ic_launcher=0x7f020000;7. }8. public static final class id {9. public static final int button1=0x7f050000;10. }11. public static final class layout {12. public static final int main=0x7f030000;13. }14. public static final class string {15. public static final int app_name=0x7f040001;16. public static final int hello=0x7f040000;17. }18. }

Treinamento Android Pág.: 11 de 96

Item 06 - Arquivo AndroidManifest.xml – Diretório ProjetoAula

O arquivo AndroidManifest.xml é o arquivo principal do projeto e centraliza as configurações da aplicação. Ele obrigatoriamente deve ficar na pasta raiz do projeto, contendo todas as configurações necessárias para executar a aplicação, como o nome do pacote utilizado, o nome das classes de cada activity e várias outras configurações. Podemos comparar o arquivo AndroidManifest.xml com o arquivo web.xml utilizado nas aplicações web em java. Em um aplicação web cada classe de servlet deve ser declarada no arquivo web.xml e, da mesma forma, no Android cata activity deve ser declarada no arquivo AndroidManifest.xml.

É importante que o encode do XML seja UTF-8.

Dentro da tag <manifest> é necessário declarar o pacote principal do projeto, utilizando a tag <package>. É obrigatório que cada activity do projeto esteja declarada no arquivo AndroidManifest.xml, caso contrario não é possível utiliza-la. Para declarar a activity é utilizada a tag <activity>, que recebe o nome da classe, e é sempre relativa ao pacote principal. Por exemplo, em nossa aplicação o nome do pacote é Android.Aula. Assim, o nome da activity ficou sendo .ProjetoAulaActivity. O ponto indica que a classe ProjetoAulaActivity.java esta no pacote principal do projeto. Caso activity ficasse em outro pacote, por exemplo, Android.Aula.Exemplo, o nome da activity deveria ser .pacote.ProjetoAulaActivity.

O projeto pode conter apenas uma, várias ou nenhuma activity, mas o importante é que ser for necessário exibir um ícone na tela principal do Android, para que a aplicação possa ser iniciada pelo usuário, é necessário pelo menos uma activity, e esta deve ser configurada como sendo o ponto de partida da aplicação. Para isso é necessário declarar uma tag <intent-filter> com as ações android.intent.action.MAIN e a categoria android.intent.category.LAUNCHER dentro da tag <activity>, conforme o seguinte código.

A tag <intent-filter> é necessária para customizar a forma como a activity será iniciada. A ação MAIN significa que essa activity ProjetoAulaActivity pode ser iniciada isoladamente, como ponto inicial da aplicação. A categoria LAUNCHER indica que a activity estará disponível para o usuário na tela inicial junto com as outras aplicações que o usuário tem. Dessa forma, um ícone da aplicação pode ser visualizado na tela das aplicações instaladas, e ao clicar no ícone a activity configurada como principal é iniciada. Em aplicações reais geralmente existirá apenas um activity com essa configurações.

Confira na Listagem 07 o conteúdo do arquivo XML AndroidManifest do nosso projeto de exemplo.

Listagem 07

1. <?xml version="1.0" encoding="utf-8"?>2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"3. package="Android.Aula"4. android:versionCode="1"5. android:versionName="1.0" >6. <uses-sdk android:minSdkVersion="15" />7. <application8. android:icon="@drawable/ic_launcher"9. android:label="@string/app_name" >10. <activity11. android:name=".ProjetoAulaActivity"12. android:label="@string/app_name" >13. <intent-filter>14. <action android:name="android.intent.action.MAIN" />15. <category android:name="android.intent.category.LAUNCHER" />16. </intent-filter>17. </activity>18. </application>19. </manifest>

Treinamento Android Pág.: 12 de 96

Android Virtual DeviceUm AVD, ou Android™ Virtual Device, é uma emulação de características de smartphones usando aquela versão do Android™ escolhida (seja a 2.1, 2.2, 4.0.3 ou qualquer outra). Com ele, são carregados a imagem do sistema e características deste num emulador, onde você poderá ver se corre tudo bem com o seu projeto.

O conceito de AVD foi criado a partir do SDK 1.5 para auxiliar no desenvolvimento de aplicações Android, para que o emulador possa simular exatamente uma configuração de um celular real, que podem estar com diferentes versões do SDK instaladas.

Passo 01Vamos definir um dispositivo virtual, conhecido como AVD (Android Virtual Device), onde nossas aplicações daqui para frente serão executadas. Para isso, vá no menu “Windows” / “Android SDK and AVD Manager”, conforme mostra a Figura 01. Procedendo assim, a interface da Figura 02 será exibida.

Figura 01

Passo 02Se orientando pela Figura 02, interface Android Virtual Device Manager, clique no botão New para adição de um AVD.

Figura 02

Treinamento Android Pág.: 13 de 96

Passo 03Conforme interface da Figura 03 (Edit Android Virtual Device Manager), preencha as propriedades conforme Tabela 01, clicando no botão Edit AVD em seguida observando o resultado na Figura 04.

Campo Valor

Name AVDAula

Sise 128

Built-in HVGA

Figura 03

Figura 04

Treinamento Android Pág.: 14 de 96

Passo 04Operando a caixa de dialogo Android Virtual Device Manager, Figura 04, clique no botão Start para iniciar o emulador. Será exibido a interface Launch Options para qual devemos ajustar conforme Figura 05.

Figura 05

Treinamento Android Pág.: 15 de 96

Passo 05Ainda com relação a interface da Figura 05, clique no botão Launch para termos a tela do Emulador em execução.

Conforme observado na tela do Emulador, a saber, Figuras 06, o mesmo está carregando. A Figura 07 exibe a interface final padrão do um aparelho Android em execução.

Pronto o teste de execução do emulador está encerrado com sucesso. Agora podemos voltar para a aplicação introdutória e executá-la, clicar no botão Menu e ver o resultado sendo exibido no Emulador conforme Figura 08.

Figura 06

Figura 07

Figura 08

Treinamento Android Pág.: 16 de 96

Banco de Dados SQLite

SQLite é um banco de dados Open Source, que é incorporado (embarcado) em Android. SQLite suporta recursos padrão banco de dados relacional como sintaxe SQL, operações e instruções armazenadas. Além disso, requer pouca memória em tempo de execução (aprox. 250 Kbyte).

SQLite suporta tipo de dados texto (tipos semelhante ao de String da Java), INTEGER(semelhante ao long da Java) e Real (similar ao dobuble em Java). Todos os outros tipos devem ser convertidos em um desses campos antes de serem mantidos no banco de dados. O SQLite em si não valida se os tipos enviados para as colunas são, na verdade, do tipo definido. Por exemplo você pode escrever um número inteiro em uma coluna tipo String e vice-versa.

SQLite está disponível em todos os dispositivos Android. Usando um banco de dados SQLite no Android não requer qualquer configuração de banco de dados ou administração.

Você só tem que definir as instruções SQL para criar e atualizar o banco de dados. Depois disso, o banco de dados é gerenciado automaticamente para você pela plataforma Android.

O acesso a um banco de dados SQLite envolve acessar o sistema de arquivos. Isto pode ser lento. Portanto, recomenda-se para executar operações de banco de dados de forma assíncrona, por exemplo através da classe AsyncTask.

Se seu aplicativo cria um banco de dados, este banco de dados é salvo no diretório / DATA / APP_NAME / bancos de dados / FILENAME.

As partes do diretório acima são construídos com base nas seguintes regras. Dados é o caminho que o Environment.getDataDirectory() retorna. APP_NAME é o nome do aplicativo. FILENAME é o nome que você especificar no código do aplicativo para o banco de dados.

Na sequência, a título de cooperar com seu aprendizado sobre este banco de dados, apresentamos uma colaboração na forma de tutorial para criarmos um banco de dados e a tabela do nosso exemplo de aplicação com banco de dados embarcado no Android.

Execute o utilitário SQLite Expert Personal conforme Figura 01, e siga os passos na sequência.

Figura 01

Treinamento Android Pág.: 17 de 96

Passo 01Clique na opção de menu File | New Database, preenchendo os campos da caixa de dialogo Database Creation Properties com forme apresentado na sequência das Figuras 02, 03, 04 e 05. Encerrando, clique no botão OK.

Figura 02

Figura 03

Figura 04

Figura 05

Passo 02Clique com o botão direito do mouse sobre o nó BancoCursoAndroid (Figura 05) escolhendo a opção New Table do menu de contexto. Conforme Figura 06, digite no campo Table name “Cliente”.

Figura 06

Treinamento Android Pág.: 18 de 96

Passo 03Adicione colunas a tabela, com a aba Fields selecionada, clicando com o botão direito do mouse e selecionado a opção Add. Preencha o campo Name como “ID” e selecione no campo Type “BIGINT” clicando no botão OK para definitivamente criar a coluna. Proceda novamente desta maneira para criar as outras colunas da tabela, orientando-se pelas Figuras 07, 008, 09, 10 e 11.

Ao final, clique no botão Applay (Figura 12) e teremos a tabela criada.

Figura 07 Figura 08

Figura 09 Figura 010

Figura 11

Treinamento Android Pág.: 19 de 96

Figura 12

Passo 04Crie também outra tabela, nomeando-a como Visita, tomando por base as informações expostas na aba Fields da Figura 13. Ao final clique no botão applay e pronto.

Figura 13

Passo 05Selecionando a aba Design | Index conforme Figura 14, clicando com o botão direito do mouse, selecione a opção Add do menu de contexto para adicionar índices.

Na sequência representada pelas Figuras 15 e 16, são apresentado os detalhes para criarmos alguns índices.

Treinamento Android Pág.: 20 de 96

Figura 14

Figura 15

Figura 16

Treinamento Android Pág.: 21 de 96

Passo 06Selecione a tabela cliente no nó do Banco de Dados no lado esquerdo da IDE, em seguida, selecione a aba Data e adicione alguns clientes conforme ilustrado na Figura 17.

Figura 17

Treinamento Android Pág.: 22 de 96

Projeto Android e Banco de Dados SQLite Embarcado

Criando o Projeto Android

Passo 01Com a IDE do Eclipse em execução, crie um projeto Android acionando a opção de menu File | New | Android Project. Repare as Figuras 01 e 02 exemplificando este passo.

Figura 01

Figura 02

Passo 02Continuando, se orientando pela imagem das Figuras 03 e 04, selecione o diretório onde ficará armazenado os fontes do projeto (Figura 03) e escolha a versão do Android para o projeto em questão (Figura 04).

Figura 03 Figura 04

Passo 03Clicando no botão Next, Figura 04, teremos a caixa de dialogo final, representada pela Figura 05. Nesta, preencha o campo Application Name com ExercicioBancoDados, o campo Package Name com android.curso. Também mantenha a opção Create Activity ativa, definindo o nome da Ativity como MainActivity clicando o Finish para encerrar.

Treinamento Android Pág.: 23 de 96

Figura 05

Passo 04Iniciaremos agora alguns ajustes no código donte do projeto, iniciando pelo arquivo Strings.xml conforme Listagem 01.

Listagem 01

1. <?xml version="1.0" encoding="utf-8"?>2. <resources>3. <string name="hello">Menu de Opções</string>4. <string name="app_name">AppBancoDados</string>5. </resources>

Passo 05Alteraremos agora o arquivo main.xml, interface que representa a tela principal do projeto, aplicando nesta alguns controles conforme exibido na Figura 06. Recorra também a Listagem 02 e Tabela 01 para cumprir esta etapa.

Figura 06

Treinamento Android Pág.: 24 de 96

Listagem 02 – Arquivo main.xml

1. <?xml version="1.0" encoding="utf-8"?>2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"3. android:layout_width="fill_parent" 4. android:layout_height="fill_parent"5. android:orientation="vertical" >6. 7. <TextView8. android:layout_width="fill_parent" 9. android:layout_height="wrap_content"10. android:layout_marginLeft="25dip" 11. android:layout_marginTop="20dip" 12. android:layout_marginBottom="15dip" 13. android:textColor="#FFFF00"14. android:textSize="20dip" 15. android:textStyle="bold"16. android:text="@string/hello" 17. />18.19. <Button20. android:id="@+id/main_buttonConsultarCliente"21. android:layout_width="match_parent" 22. android:layout_height="70sp" 23. android:textColor="#ffffff" 24. android:drawableRight="@drawable/ic_btlupa" 25. android:layout_margin="1dip" 26. android:text="Consultar Cliente" 27. android:background="@drawable/ic_degradeazulescuro" 28. />29.30. <Button31. android:id="@+id/main_buttonIncluirCliente"32. android:layout_width="match_parent" 33. android:layout_height="70sp"34. android:background="@drawable/ic_degradeazulescuro"35. android:textColor="#ffffff"36. android:drawableRight="@drawable/ic_btincluir"37. android:layout_margin="1dip" 38. android:text="Incluir Novo Cliente" />39.40. <Button41. android:id="@+id/main_buttonAtualizaBancoLocal"42. android:layout_width="match_parent" 43. android:layout_height="70sp"44. android:background="@drawable/ic_degradeazulescuro"45. android:textColor="#ffffff"46. android:drawableRight="@drawable/ic_databasedown" 47. android:layout_margin="1dip" 48. android:text="Atualizar Banco Local" />49.50. <Button51. android:id="@+id/main_buttonAtualizarBancoServidor"52. android:layout_width="match_parent" 53. android:layout_height="70sp"54. android:background="@drawable/ic_degradeazulescuro"55. android:textColor="#ffffff"56. android:drawableRight="@drawable/ic_databaseup" 57. android:layout_margin="1dip" 58. android:text="Atualizar Banco Servidor" />59. 60.

Treinamento Android Pág.: 25 de 96

61. <Button62. android:id="@+id/main_buttonBrowser"63. android:layout_width="match_parent" 64. android:layout_height="70sp"65. android:background="@drawable/ic_degradeazulescuro"66. android:textColor="#ffffff"67. android:drawableRight="@drawable/ic_databaseup" 68. android:layout_margin="1dip" 69. android:text="Usar Browser" />70.

71. </LinearLayout>

Tabela 01

Linha Explicação

2 Define o tipo do Layout como LayoutLinear.

3 Define que a largura do Lauout ocupará toda extenção da largura definida pelo Device.

4 Define que a altura do Lauout ocupará toda extenção da altura definida pelo Device.

5 Determina que os controles serão distribuídos na Vertical, uma abaixo do outro na área de Layout.

7 Define um controle TextView

8 Define que o controle ocupará a largura total da área de Layout.

9 Define que o texto será quebrado (em linhas) para acomodar o texto atribuído ao controle.

10Define a margem que o controle guardará no lado esquerdo com relação a área de Layout ou controle a seu lado esquerdo.Obs.: Confira na Tabela 02 os tipos de unidade de medida em Android.

11 Idem item 10, mas para a margem superior (Top).

12 Idem item 10, mas para a margem inferior (Botton).

13 Define cor do texto que o controle exibirá. Este valor equivale a algo como amarelo dourado.

14 Tamanho do fonte de texto.

15 Define estilo (style) bold para o texto.

16Atribui como valor para a propriedade Text do controle, o valor definido para constante string hello, na Tag Resources, no arquivo Strings.xml. Confira a alteração que já promovemos no Passo 04, Listagem 01, refletindo o novo valor da constante hello.

17 Fechamento da Tag Textview.

19 Abre a Tag Button.

20

Define o nome (id) do controle. Repare que o nome definido, é a composição do nome da View com o nome que se deseja para o controle. Isto é importante, pois todos os controles de todas as Views do projeto são acessados em código fazendo referência a classe “R” e subclasse “id”, conforme exemplo que se segue: R.id.main_buttonBrowser

24 Define a imagem que será exibido sobre o controle em seu lado direito.

27 Define a imagem que server de pano de fundo para o controle.

28 Fecha a Tag Button.

Treinamento Android Pág.: 26 de 96

Passo 06Adicione arquivos de imagem ao diretório res | drawable-hdpi do projeto (Figura 07), para que possam apoós compilação se tornarem reurso da classe “R” subclasse “drawable”

Figura 07

Tabela 02 - Unidades de Medida

Sigla Explicação

px Pixels - corresponde a pixels reais na tela.

in Polegadas - baseado no tamanho físico da tela.

mm Milímetros - com base no tamanho físico da tela.

pt Pontos - 1/72 de polegada com base no tamanho físico da tela.

dp

Density-independent Pixels - uma unidade resumo que é baseada na densidade física da tela. Estas unidades são relativos a uma tela de dpi 160, de modo uma dp é um pixel numa tela dpi 160. A proporção de DP-a-pixel irá mudar com a densidade de tela, mas não necessariamente em proporção directa. Nota: O compilador aceita tanto "dip" e "DP", embora "DP" é mais consistente com "sp".

sp

Scale-independent Pixels - este é como a unidade de DP, mas também é dimensionado pelo utilizador de preferência de tamanho da fonte. É recomendável utilizar esta unidade ao especificar tamanhos de fonte, então eles vão ser ajustado tanto para a tela de densidade e da preferência do usuário.

Treinamento Android Pág.: 27 de 96

Passo 07Repare o código da classe MainActivity na Listagem 03 e os comentários da linhas de código na Tabela 03.

Listagem 03 – Arquivo de classe MainActivity.java

1. package android.curso;2.

3. import android.app.Activity;4. import android.os.Bundle;5. import android.view.View;6.

7. public class MainActivity extends Activity {8. @Override9. public void onCreate(Bundle savedInstanceState) {10. super.onCreate(savedInstanceState);11. setContentView(R.layout.main); 12. }13. }

Tabela 03

Linha Comentário

1 Define que a classe está presente na namespace do pacote android.curso

3 Import para que a classe presente possa estender a classe Activity, e assim usar seus métodos e estender outros (@Override).

4 Import da classe View. Classe responsável pela renderização da View main neste exemplo.

8 Indica que o método assinado na linha posterior subscreverá o mesmo método da classe extendida Activity.

9 Método associado ao momento em que uma instância da classe é criada.

10 Invoca o método onCreate da classe Super.

11 Método que recebe como parâmetro o recurso que representa o arquivo xml que servirá de template para exibição da página.

Execute o projeto, assumindo que já criamos um AVD para tanto. Então, acesse o munu Run | Run executando o teste reparando a Figura 08 exibindo a interface principal do aplicativo em execução.

Figura 08

Treinamento Android Pág.: 28 de 96

Implantando o Arquivo de Banco de Dados no Servidor SQLite Embarcado

Passo ÚnicoNa IDE do Eclipse, acione o menu Window na opção Show View | Other..., em seguida, com a caixa de dialogo Show View em exibição (Figura 09) escolha File Explore e clique no botão OK.

A janela File Explore (Figura 10), resultante da ação anterior, prover acesso a estrutura de arquivos do Device (no caso do Emulador) a partir da pasta data onde podemos encontrar o caminho final para armazenamento do arquivo de banco de dados. Assim sendo, para finalizar esta etapa, na janela File Explore, vá expandido os nós até chegar no caminho data\data adicionando uma pasta denominada database.

Por padrão, e isso é realmente um grande facilitador, no que diz respeito a distribuição e localização de banco de dados em aplicativos Android, arquivos de banco de dados para todas as aplicações residem neste caminho, a saber, data\data\database.

Colocando em prática, se oriente pelas imagens da Figuras 11 e 12, usando um artifício elementar, faça uma cópia (Ctrl + C) do arquivo de banco de dados do projeto, transferindo esta cópia que agora está em memória, com outro recurso elementar, Ctrl V. Pronto observe agora a imagem da Figura 12, caixa de dialogo File Explore, agora contendo uma cópia do arquivo do banco de dados pronto para acesso pela aplicação.

Figura 09

Figura 10

Treinamento Android Pág.: 29 de 96

Figura 11

Figura 12

Treinamento Android Pág.: 30 de 96

Criando as Views do Projeto - Camada View - MVCComo exemplo do processo para adicionar uma nova View ao projeto, siga os passos abaixo repetindo-o na sequência das outras Views.

Passo 01

Clique com o botão direito do mouse sobre o nó layout na janela Project Explore (Figura 01), selecionando a opção New do menu de contexto. Em seguida escolha a opção Other, tendo como resposta a caixa de dialogo representada pela Figura 02. Escolha a opção Android | Android XML Layout File, passando para próximo passo.

Figura 01

Figura 02

Passo 02

Na caixa de dialogo New Android Layout XML File, Figura 03, define um nome para o arquivo no campo File e clique no botão Next..

Treinamento Android Pág.: 31 de 96

Figura 03

Passo 03

Não é necessário nesta etapa selecionar alguma configuração em especial, bastando apenas clicar novamente no botão Next na caixa de dialogo representada aqui pela Figura 04. Por fim, clique no botão Finish para encerrar o processo.

Figura 04

Prossiga o processo acompanhando na sequência as instruções para todos as outras Views do projeto.

Treinamento Android Pág.: 32 de 96

View listaclientes.xmlEsta View tem como finalidade expor a lista de registros da tabela Cliente, precisamente as colunas ID, NOME e TELEFONE. Na prática esta View servirá somente de template contendo um controle para cada coluna mencionada. Naturalmente, os aspectos relativos a configuração visual de cada controle da View, prevalecerão os aplicados aqui, ficando por conta da rotina que renderizará a View final, atribuir valore as colunas. Considere a imagem da Figura 01, o código da Listagem 01 e os comentários desta listagem na Tabela 01 para construir e entender a proposta da View.

Figura 01

Listagem 01

1. <?xml version="1.0" encoding="utf-8"?>2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"3. android:layout_width="match_parent"4. android:layout_height="match_parent" 5. android:orientation="horizontal"6. android:id="@+id/layout">7. 8. <TextView 9. android:layout_height="30dip" 10. android:layout_width="40sp" 11. android:layout_marginLeft="05dip"12. android:layout_marginTop="05dip"13. android:id="@+id/listaclientes_consultarCliente_id"/> 14. 15. <TextView 16. android:layout_height="40dip" 17. android:layout_width="190sp" 18. android:layout_marginRight="05dip"19. android:layout_marginTop="05dip"20. android:id="@+id/listaclientes_consultarCliente_nome"/> 21. 22. <TextView 23. android:layout_height="30dip" 24. android:layout_width="90sp" 25. android:layout_marginTop="05dip"26. android:id="@+id/listaclientes_consultarCliente_telefone"/>27.28. </LinearLayout>

Treinamento Android Pág.: 33 de 96

Tabela 01

Linha Comentários

1 Define que a estrutura do arquivo é XML com padrão de teto UTF 8.

2 Define que o lay-out adotado para página é LinearLayout. Na sequência estudaremos outros tipos de layout de página.

3 Define que a área útil lay-out ocupará toda a largura do device onde for executado.

4 Define que a área útil lay-out ocupará toda a altura do device onde for executado.

5 Define que o controles adicionados a página serão organizados na horizontal. Na prática os controles serão acomodados um abaixo do outro, respeitando possíveis configurações de distância atribuída, por intermédio de propriedades tipo margem.

6 Define o identificador do arquivo de lay-out indicando que está na pasta layout.

8 Abre a tag para um controle TextView.

9 Define a altura do controle em 30 dip. Ver Tabela 02 com tipos de dimensões.

10 Define a largura do controle em 40 sp.

11 Define a medida da margem esquerda do controle com relação a área do lay-out.

12 Define a medida da margem superior do controle com relação ao objeto acima dele.

13 Define o identificador (nome) do controle. Repare que é salutar definir um nome para o controle que tenha como prefixo o nome da View. Isso porque, todos os controles de todas as Views são registrados na classe R, logo, fica mais fácil identificar um controle específico.

15 a 20 e

22 a 26

Define as propriedades para os controles listaclientes_consultarCliente_nome e listaclientes_consultarCliente_telefone. As definições são as mesmas encontradas entre as linhas 8 a 13.

28 Tag de encerramento da tag LinerLayout.

Tabela 02 - Tipos de Dimensões em Android

Sigla Descrição

Px (pixels) Correspondente ao número de pixels da tela.

in(polegadas) Baseado no tamanho físico da tela.

mm(milímetros) Baseado no tamanho físico da tela.

Pt (pontos) 1/72 de uma polegada, baseado no tamanho físico da tela

Dp ou dip (Density-independent Pixels) Essa unidade é relativa à resolução da tela. Por exemplo, se a resolução da tela é de 160 dpi, significa que um dp representa 1 pixel em 160 dpi.

sp (Scale-independent Pixels) Idem ao dp, mas também considera o tamanho da fonte que o usuário está utilizando. É recomendado que use essa unidade quando especificar o tamanho de uma fonte, para que esta seja automaticamente ajustada conforme as

Treinamento Android Pág.: 34 de 96

preferências da tela do usuário.

View editarcliente.xml

O lay-out desta View (Figura 01) implementa quatro controles TextView para funcionar como título dos campos e mais quatro controles EditText que servirão coma caixa de texto para entrada de dados. Também são aplicados a página três controles Button na parte inferior.

Confira o código necessário na Listagem 01, com os comentários na Tabela 01. Não comentaremos linhas já comentadas em listagens anteriores, sendo isso uma regra na sequência deste material.

Figura 01

Listagem 01

1. <?xml version="1.0" encoding="utf-8"?>2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"3. android:layout_width="match_parent"4. android:layout_height="match_parent"5. android:layout_marginLeft="10dip"6. android:layout_marginRight="10dip"7. android:orientation="vertical" >8.9. <TextView10. android:id="@+id/editarcliente_textViewId"11. android:layout_width="wrap_content"12. android:layout_height="wrap_content"13. android:layout_marginTop="15dip"14. android:text = "Código" 15. android:textSize="15sp"16. android:textStyle="bold" />17.18. < EditText 19. android:id="@+id/editarcliente_editTextId"20. android:layout_width="match_parent"

Treinamento Android Pág.: 35 de 96

21. android:layout_height="35dip"22. android:textSize = "13px" />23.24. <TextView25. android:id="@+id/editarcliente_textViewNome"26. android:layout_width="wrap_content"27. android:layout_height="wrap_content"28. android:layout_marginTop="10dip"29. android:text = "Nome Completo" 30. android:textSize="15sp"31. android:textStyle="bold" />32.33. < EditText 34. android:id="@+id/editarcliente_editTextNome"35. android:layout_width="match_parent"36. android:layout_height="32dip"37. android:textSize = "13px" >38.39. <requestFocus />40. </EditText>41.42. <TextView43. android:id="@+id/editarcliente_textViewCidade"44. android:layout_width="wrap_content"45. android:layout_height="wrap_content"46. android:layout_marginTop="10dip"47. android:text = "Cidade" 48. android:textSize="15sp"49. android:textStyle="bold" />50.51. < EditText 52. android:id="@+id/editarcliente_editTextCidade"53. android:layout_width="match_parent"54. android:layout_height="32dip"55. android:textSize = "13px" />56.57. <TextView58. android:id="@+id/editarcliente_textViewEstado"59. android:layout_width="wrap_content"60. android:layout_height="wrap_content"61. android:layout_marginTop="10dip"62. android:text = "Estado" 63. android:textSize="15sp"64. android:textStyle="bold" />65.66. < EditText 67. android:id="@+id/editarcliente_editTextEstado"68. android:layout_width="match_parent"69. android:layout_height="32dip"70. android:textSize = "13px" />71.72. <TextView73. android:id="@+id/editarcliente_textViewTelefone"74. android:layout_width="wrap_content"75. android:layout_height="wrap_content"76. android:layout_marginTop="10dip"77. android:text = "Telefone" 78. android:textSize="15sp"79. android:textStyle="bold" />80.81. < EditText 82. android:id="@+id/editarcliente_editTextTelefone"

Treinamento Android Pág.: 36 de 96

83. android:layout_width="match_parent"84. android:layout_height="32dip"85. android:layout_marginBottom="20dip"86. android:textSize = "13px" />87.88. <TableRow89. android:id="@+id/editarcliente_tableRowBotoes"90. android:layout_width="match_parent"91. android:layout_height="wrap_content"92. android:gravity="center" >93.94. <Button95. android:id="@+id/editarcliente_buttonAlterar"96. android:layout_width="90dip"97. android:layout_height="wrap_content"98. android:drawableTop="@drawable/ic_bteditar"99. android:text = "Alterar" />100.101. <Button102. android:id="@+id/editarcliente_buttonExcluir"103. android:layout_width="90dip"104. android:layout_height="wrap_content"105. android:drawableTop="@drawable/ic_btexcluir"106. android:text = "Excluir" />107.108. <Button109. android:id="@+id/editarcliente_buttonVoltar"110. android:layout_width="90dip"111. android:layout_height="wrap_content"112. android:drawableTop="@drawable/ic_btvoltar"113. android:text = "Voltar" />114. </TableRow>115.116. </LinearLayout>

Tabela 01

Linha Comentário

12 Define que o texto atribuído a propriedade text do controle será quebrado em linhas, se necessário, obedecendo a largura do controle como limite.

14 Define o código que será exibido pelo controle.

15 Define o tamanho da fonte de texto para o controle.

16 Define o peso para a fonte de texto indicado anteriormente.

20 Define o comportamento do controle quanto a expansão ou no do texto do controle. Veja a Tabela 02 com a definição para as possíveis formas.

39 Tag interna a tag TextView que coloca o foco neste controle.

88 Define uma tag TableRow (Linha de Tabela) dentro da página (aqui um LinearLayout), possibilitando acomodar controles dentro de células nas linhas desta Table.

Considerando que o lay-out da página aqui é linearLayout, logo, acomomdando os controles um abaixo do outro, usando a Tag Table podemos acomodar controles lado a lado, simplesmente definindo uma estrutura tabular com linhas e colunas. É o caso, neste layout, dos botões que estão

Treinamento Android Pág.: 37 de 96

colocados na parte inferior do formulário.

92 Define que o controle (aqui a Table) vai gravitar pelo centro da área restante, tendo com base o topo, o fundo, o lado esquerdo e direito.

98 Define qual imagem irá ser exibida no topo do controle. Esta e outras figuras (arquivos de imagens) para serem utilizadas em layout, devem ser antes acomodadas no sub-diretório drawable do diretório res do projeto.

Nota: Repare que o texto atribuído ao controle, neste caso um Button, fica abaixo da imagem.

114 Fecha a Tag TableRow.

116 Fecha a Tag LinearLayout.

Tabela 02

Descrição

fill_parent Configurando o layout de um widget para fill_parent vai forçá-lo a se expandir para ocupar tanto espaço quanto está disponível dentro do elemento de layout que ele foi colocado.

wrap_content Definir o tamanho de uma View para wrap_content vai forçá-lo a expandir apenas o suficiente para conter os valores (ou controles filho) que ele contém. Para controles,como caixas de texto (TextView) ou imagens (ImageView) - isso irá quebrar o texto ou imagem que está sendo mostrado. Para os elementos de layout que vão redimensionar o layout para ajustar os controles / layouts adicionados como seus filhos.

Treinamento Android Pág.: 38 de 96

View buscaclientepornome.xml

Este layout servirá para capturar o parâmetro (parte do nome do cliente) para pesquisa de Clientes pelas iniciais de um nome.

Para desenhar este formulário, se oriente pela Figura 01, conferindo a configuração de cada controle na Listagem 01.

Figura 01

Listagem 01

1. <?xml version="1.0" encoding="utf-8"?>2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"3. android:layout_width="match_parent"4. android:layout_height="match_parent"5. android:orientation="vertical" >6.7. <TextView8. android:id="@+id/buscaclientepornome_TextviewParteNome"9. android:layout_width="300sp"10. android:layout_height="20dip"11. android:layout_marginLeft="10dip"12. android:layout_marginTop="30dip"13. android:layout_marginBottom="10dip"14. android:text = "Digite parte do nome:" />15.16. <EditText17. android:id="@+id/buscaclientepornome_EditTextNome"18. android:layout_width="290sp"19. android:layout_height="35dip"20. android:textSize = "15px"

Treinamento Android Pág.: 39 de 96

21. android:layout_marginLeft="10dip"22. android:hint = "Digite as iniciais de um nome." 23. android:singleLine="true" >24.25. <requestFocus />26. </EditText>27.28. <Button29. android:id="@+id/buscaclientepornome_ButtonPesquisar"30. android:layout_width="300sp"31. android:layout_height="wrap_content"32. android:layout_marginLeft="10dip"33. android:layout_marginTop="20dip"34. android:drawableLeft="@drawable/ic_btlupa"35. android:text = "Pesquisar por Nome" />36.37. <Button38. android:id="@+id/buscaclientepornome_ButtonCancelar"39. android:layout_width="300sp"40. android:layout_height="wrap_content"41. android:layout_marginLeft="10dip"42. android:layout_marginTop="10dip"43. android:drawableLeft="@drawable/ic_btvoltar"44. android:text = "Voltar " />45. 46. </LinearLayout>

Treinamento Android Pág.: 40 de 96

View incluircliente.xml

Este layout servirá para capturar valores para inserção nos campos de um registro na tabela Cliente.

Figura 01

Listagem 01

1. <?xml version="1.0" encoding="utf-8"?>2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"3. android:layout_width="match_parent"4. android:layout_height="match_parent"5. android:layout_marginLeft="10dip"6. android:layout_marginRight="10dip" 7. android:orientation="vertical">8. 9. <TextView10. android:id="@+id/incluircliente_textViewId"11. android:layout_width="wrap_content"12. android:layout_height="wrap_content"13. android:layout_marginTop="20dip"14. android:text = "Código" 15. android:textAppearance="?android:attr/textAppearanceMedium" 16. android:textSize="15sp"17. android:textStyle="bold" /> 18.19. < EditText 20. android:id="@+id/incluircliente_editTextId"21. android:layout_width="match_parent"22. android:layout_height="32dip"23. android:textSize="13sp" /> 24.25. <TextView26. android:id="@+id/incluircliente_textViewNome"27. android:layout_width="wrap_content"28. android:layout_height="wrap_content"29. android:layout_marginTop="10dip"

Treinamento Android Pág.: 41 de 96

30. android:text = "Nome Completo" 31. android:textAppearance="?android:attr/textAppearanceMedium"32. android:textSize="15sp"33. android:textStyle="bold" />34.35. < EditText 36. android:id="@+id/incluircliente_editTextNome"37. android:layout_width="match_parent"38. android:layout_height="32dip"39. android:textSize="13sp" >40. <requestFocus />41. </EditText>42.43. <TextView44. android:id="@+id/incluircliente_textViewCidade"45. android:layout_width="wrap_content"46. android:layout_height="wrap_content"47. android:layout_marginTop="10dip"48. android:text = "Cidade" 49. android:textAppearance="?android:attr/textAppearanceMedium"50. android:textSize="15sp"51. android:textStyle="bold" />52.53. < EditText 54. android:id="@+id/incluircliente_editTextCidade"55. android:layout_width="match_parent"56. android:layout_height="32dip"57. android:textSize="13sp" />58. 59. <TextView60. android:layout_width="wrap_content"61. android:id="@+id/incluircliente_textViewEstado"62. android:layout_height="wrap_content"63. android:layout_marginTop="10dip"64. android:text = "Estado" 65. android:textAppearance="?android:attr/textAppearanceMedium"66. android:textSize="15sp"67. android:textStyle="bold" />68.69. < EditText 70. android:id="@+id/incluircliente_editTextEstado"71. android:layout_width="match_parent"72. android:layout_height="32dip"73. android:textSize="13sp" />74. 75. <TextView76. android:id="@+id/incluircliente_textViewTelefone"77. android:layout_width="wrap_content"78. android:layout_height="wrap_content"79. android:layout_marginTop="10dip"80. android:text = "Telefone" 81. android:textAppearance="?android:attr/textAppearanceMedium"82. android:textSize="15sp"83. android:textStyle="bold" />84.85. < EditText 86. android:id="@+id/incluircliente_editTextTelefone"87. android:layout_width="match_parent"88. android:layout_height="32dip"89. android:layout_marginBottom="20dip"90. android:textSize="13sp" />91.

Treinamento Android Pág.: 42 de 96

92. <TableRow93. android:id="@+id/incluircliente_tableRowBotoes"94. android:layout_width="match_parent"95. android:layout_height="wrap_content" >96. <Button97. android:id="@+id/incluircliente_buttonIncluir"98. android:layout_width="150dip"99. android:layout_height="wrap_content"100. android:drawableTop="@drawable/ic_btconfirmar"101. android:text = "Incluir" />102. <Button103. android:id="@+id/incluircliente_buttonVoltar"104. android:layout_width="150dip"105. android:layout_height="wrap_content"106. android:drawableTop="@drawable/ic_btvoltar"107. android:text = "Voltar" /> 108. </TableRow>109.110. </LinearLayout>

Tabela 01

Linha Comentário

49 Define a aparência do texto do controle com tamanho médio. Consideramos melhor definir as propriedades size, style entre outras explicitamente.

Treinamento Android Pág.: 43 de 96

View executarbrowser.xml

Este layout servirá para capturar uma URL digitada e executar o browser do dispositivo neste endereço http. Confira a Listagem 01 com todo o código das tags utilizadas.

Figura 01

Listagem 01

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginTop="20dip" android:layout_marginBottom="0dip" android:layout_marginLeft="02dip" android:layout_marginRight="02dip" android:textColor="#FFFF00" android:textSize="12dip" android:textStyle="bold" android:text = "Digite um Endereço Web" />

Treinamento Android Pág.: 44 de 96

< EditText android:id="@+id/browser_editTextURL" android:layout_width="match_parent" android:layout_height="35sp" android:layout_marginTop="5dip" android:layout_marginBottom="15dip" android:layout_marginLeft="02dip" android:layout_marginRight="02dip" android:textSize="12dip" android:text = "http://www.google.com.br" /> <Button android:id="@+id/browser_buttonExecutar" android:layout_width="match_parent" android:layout_height="40dp" android:layout_marginLeft="02dip" android:layout_marginRight="02dip" android:background="@drawable/ic_degradeazulescuro" android:text = "Abrir no Browser" android:textColor="#FFFF00" android:textSize="15dip" android:textStyle="bold" />

</LinearLayout>

Treinamento Android Pág.: 45 de 96

Criando as Classes da Camada Model - MVCCriando a Classe ClientePara servir de modelo para as classes que lidarão com a entidade Cliente, na sequência, implementamos a Classe Cliente. Confira todo o código na Listagem 01 e e os comentários na Tabela 01.

Listagem 01

1. package android.curso;2.3. import android.provider.BaseColumns;4.5. public class Cliente {6.7. public long ID;8. public String NOME;9. public String CIDADE;10. public String ESTADO;11. public String TELEFONE;12.13. public String NOME_Old;14. public String CIDADE_Old;15. public String ESTADO_Old;16. public String TELEFONE_Old;17.18. public Cliente() {19.20. }21.22. public static final class ClienteColunas implements BaseColumns {23.24. public ClienteColunas() {25.26. }27.28. public static final String ID = "id";29. public static final String NOME = "nome";30. public static final String CIDADE = "cidade";31. public static final String ESTADO = "estado";32. public static final String TELEFONE = "telefone";33.34. public static String[] colunas = new String[] {35. ClienteColunas.ID,36. ClienteColunas.NOME,37. ClienteColunas.CIDADE,38. ClienteColunas.ESTADO,39. ClienteColunas.TELEFONE40. };41.42. }43.44. }

Treinamento Android Pág.: 46 de 96

Tabela 01

Linha Comentário

5 Define a assinatura da classe Cliente

7 a 11 Definem os atributos públicos que representam no Modelo Objeto Relacional as colunas da tabela Cliente do Banco de Dados. Este atributos serão utilizadas nas instruções Insert, Update e Delete, além claro de modelar um objeto Cliente.

13 a 16 Atributos extras que armazenarão valores originais de um objeto Cliente, retendo os valores originais dos atributos de Cliente, para serem usados como argumento de comparação (cláusula Where) nas instruções Update e Delete em seus respectivos métodos. Esta prática diz respeito ao conceito de Concorrência Otimista, que trata da questão relativo a concorrência nos processos de Update e Delete.

18 a 20 Método construtor da classe. Dito método vazio já que não inicializa nenhum objeto.

22 Define uma subclasse denominada ClienteColunas, implementando a interface Basecolumms.

24 a 26 Define o método construtor da subclasse ClienteColunas.

28 32 Define os atributos da classe ClienteColunas com seus valores finais. Tais valores representam os nomes das colunas da tabela Cliente, utilizados no atributo “colunas” desta classe.

34 a 40 Cria um atributo público do tipo Array de String denominado colunas, na sub classe ClienteColunas, definindo uma estrutura contendo os nome de colunas da subclasse ClienteColunas. Isto será útil em várias circunstâncias no desenvolvimento das rotinas que usam a classe Cliente.

42 Encerra o bloco de código da subclasse ClienteColunas.

44 Encerra o bloco de código da classe Cliente.

Treinamento Android Pág.: 47 de 96

Criando a Classe ClienteModel

Para servir de CRUD para as classes que lidarão com a entidade Cliente, na sequência, implementamos a Classe ClienteModel contendo os métodos de negócio. Confira todo o código na Listagem 01 e e os comentários na Tabela 01.

Listagem 01

1. package android.curso;2.3. import java.util.ArrayList;4. import java.util.List;5. import android.content.ContentValues;6. import android.content.Context;7. import android.curso.Cliente.ClienteColunas;8. import android.database.Cursor;9. import android.database.sqlite.SQLiteDatabase;10. import android.util.Log;11.12. public class ClienteModel {13.14. private static final String NomeBanco = "BancoCursoAndroid";15. private static final String NomeTabela = "Cliente";16. protected SQLiteDatabase DataBase;17.18. protected ClienteModel() {19.20. }21.22. public ClienteModel(Context context) {23. DataBase = context.openOrCreateDatabase(NomeBanco, Context.MODE_PRIVATE, null);24. }25.26. public Cliente buscarCliente(long id) {27. Cursor cursor = DataBase.query(true, NomeTabela, Cliente.ClienteColunas.colunas, 28. Cliente.ClienteColunas.ID + " = " + id, 29. null, null, null, null, null);30. if (cursor.moveToFirst()) {31. Cliente cliente = new Cliente();32. cliente.ID = cursor.getLong(0);33. cliente.NOME = cursor.getString(1);34. cliente.CIDADE = cursor.getString(2);35. cliente.ESTADO = cursor.getString(3);36. cliente.TELEFONE = cursor.getString(4);37. cliente.NOME_Old = cursor.getString(1);38. cliente.CIDADE_Old = cursor.getString(2);39. cliente.ESTADO_Old = cursor.getString(3);40. cliente.TELEFONE_Old = cursor.getString(4);41. return cliente;42. }43. return null;44. }45.46. public List<Cliente> listaClientes() {47. Cursor cursor = DataBase.query(48. true, 49. NomeTabela, 50. null, 51. null, 52. null, 53. null, 54. null,

Treinamento Android Pág.: 48 de 96

55. null, 56. null);57. List<Cliente> ListaClientes = new ArrayList<Cliente>();58. if (cursor.moveToFirst()) {59. do {60. Cliente Cliente = new Cliente();61. ListaClientes.add(Cliente);62. Cliente.ID = cursor.getLong(0);63. Cliente.NOME = cursor.getString(1);64. Cliente.CIDADE = cursor.getString(2);65. Cliente.ESTADO = cursor.getString(3);66. Cliente.TELEFONE = cursor.getString(4);67. } while (cursor.moveToNext());68. }69. return ListaClientes;70. }71.72. public List<Cliente> listaClientesPorNome(String partenome) {73. Cursor cursor = DataBase.query(true, NomeTabela, 74. Cliente.ClienteColunas.colunas, 75. Cliente.ClienteColunas.NOME + " Like " + "'" + partenome + "%'", 76. null, null, null, Cliente.ClienteColunas.NOME, null);77. List<Cliente> ListaClientes = new ArrayList<Cliente>();78. if (cursor.moveToFirst()) {79. do {80. Cliente Cliente = new Cliente();81. ListaClientes.add(Cliente);82. Cliente.ID = cursor.getLong(0);83. Cliente.NOME = cursor.getString(1);84. Cliente.CIDADE = cursor.getString(2);85. Cliente.ESTADO = cursor.getString(3);86. Cliente.TELEFONE = cursor.getString(4);87. } while (cursor.moveToNext());88.89. }90. return ListaClientes;91. }92.93. public List<Cliente> listaClientesPorNomeSQL(String partenome) {94. String ComandoSelect = " Select Cliente.ID, Cliente.NOME, Cliente.CIDADE, " +95. " Cliente.ESTADO, Cliente.TELEFONE " +96. " From Cliente Where Cliente.NOME Like ? Order By Cliente.NOME ";97. String[] Argumentos = {partenome + "%"};98. Cursor cursor = DataBase.rawQuery(ComandoSelect, Argumentos);99. List<Cliente> ListaClientes = new ArrayList<Cliente>();100. if (cursor.moveToFirst()) {101. do {102. Cliente Cliente = new Cliente();103. ListaClientes.add(Cliente);104. Cliente.ID = cursor.getLong(0);105. Cliente.NOME = cursor.getString(1);106. Cliente.CIDADE = cursor.getString(2);107. Cliente.ESTADO = cursor.getString(3);108. Cliente.TELEFONE = cursor.getString(4);109. } while (cursor.moveToNext());110.111. }112. return ListaClientes;113. }114.115. private long inserir(ContentValues valores) {116. long id = DataBase.insert(NomeTabela, "", valores);

Treinamento Android Pág.: 49 de 96

117. return id;118. }119.120. public long inserir(Cliente cliente) {121. ContentValues valores = new ContentValues();122. valores.put(Cliente.ClienteColunas.ID, cliente.ID);123. valores.put(Cliente.ClienteColunas.NOME, cliente.NOME);124. valores.put(Cliente.ClienteColunas.CIDADE, cliente.CIDADE);125. valores.put(Cliente.ClienteColunas.ESTADO, cliente.ESTADO);126. valores.put(ClienteColunas.TELEFONE, cliente.TELEFONE);127. long id = inserir(valores);128. return id;129. }130.131. private int alterar(ContentValues valores, String where, String[] whereArgs) {132. int count = DataBase.update(NomeTabela, valores, where, whereArgs);133. Log.i("Atualização na Tabela Clientes", "Atualizou [" + count + "] registros");134. return count;135. }136. 137. public int alterar(Cliente cliente) {138. ContentValues valores = new ContentValues();139. valores.put(Cliente.ClienteColunas.NOME, cliente.NOME);140. valores.put(Cliente.ClienteColunas.CIDADE, cliente.CIDADE);141. valores.put(Cliente.ClienteColunas.ESTADO, cliente.ESTADO);142. valores.put(Cliente.ClienteColunas.TELEFONE, cliente.TELEFONE);143. String _id = String.valueOf(cliente.ID);144. String where = Cliente.ClienteColunas.ID + " = ?";145. String[] whereArgs = new String[] { _id };146. int count = alterar(valores, where, whereArgs);147. return count;148. }149. 150. public int alterarConcorrenciaOtimista(Cliente cliente) {151. ContentValues valores = new ContentValues();152. valores.put(Cliente.ClienteColunas.NOME, cliente.NOME);153. valores.put(Cliente.ClienteColunas.CIDADE, cliente.CIDADE);154. valores.put(Cliente.ClienteColunas.ESTADO, cliente.ESTADO);155. valores.put(Cliente.ClienteColunas.TELEFONE, cliente.TELEFONE);156. String where = Cliente.ClienteColunas.ID + " = ? " + " AND " +157. Cliente.ClienteColunas.NOME + " = ? " + " AND " +158. Cliente.ClienteColunas.CIDADE + " = ? " + " AND " +159. Cliente.ClienteColunas.ESTADO + " = ? " + " AND " +160. Cliente.ClienteColunas.TELEFONE + " = ? ";161. String[] whereArgs = new String[] 162. {163. String.valueOf(cliente.ID),164. cliente.NOME_Old,165. cliente.CIDADE_Old,166. cliente.ESTADO_Old,167. cliente.TELEFONE_Old168. };169. int count = alterar(valores, where, whereArgs);170. return count;171. }172.173. private int excluir(String where, String[] whereArgs) {174. int count = DataBase.delete(NomeTabela, where, whereArgs);175. Log.i("Exclusão na Tabela Clientes", "Deletou [" + count + "] registros");176. return count;177. }178.

Treinamento Android Pág.: 50 de 96

179. public int excluir(Cliente cliente) {180. String where = Cliente.ClienteColunas.ID + " = ?";181. String _id = String.valueOf(cliente.ID);182. String[] whereArgs = new String[] { _id };183. int count = excluir(where, whereArgs);184. return count;185. }186.187. public int excluirConcorrenciaOtimista(Cliente cliente) {188. String where = Cliente.ClienteColunas.ID + " = ? " + " AND " +189. Cliente.ClienteColunas.NOME + " = ? " + " AND " +190. Cliente.ClienteColunas.CIDADE + " = ? " + " AND " +191. Cliente.ClienteColunas.ESTADO + " = ? " + " AND " +192. Cliente.ClienteColunas.TELEFONE + " = ? ";193. String[] whereArgs = new String[] 194. {195. String.valueOf(cliente.ID),196. cliente.NOME_Old,197. cliente.CIDADE_Old,198. cliente.ESTADO_Old,199. cliente.TELEFONE_Old200. };201. int count = excluir(where, whereArgs);202. return count;203. }204.205. public void fechar() {206. if (DataBase != null) {207. DataBase.close();208. }209. }210.211. }

Treinamento Android Pág.: 51 de 96

Tabela 01

Linha Comentário

14 Cria variável que define o nome do banco de dados a ser conectado.

15 Define a variável que recebe o nome da tabela a ser manipulada pelos métodos CRUD da classe.

16 Define um objeto do tipo SQLIteDataBase para acesso ao banco de dados SQLIte.

19 a 21 Método construtor da classe. Inicia o objeto DataBase, criando uma instância para o contexto passado como parâmetro.

22 a 24 Cria um método construtor vazio.

26 Define o método buscarCliente, que retorna uma instância de Cliente tendo como parâmetro de entrada o ID do Cliente.

27 Cria um Cursor contendo registros da tabela cliente, retornados pelo método query do objeto Database (SQLIteDatabase). Abaixo uma lista com o significado de cada um dos nove parâmetros do método query.

Parâmetro Nome Significado

1 Distinct Tipo booleano, define se a consulta usará Distinct ou não na instrução Select.

2 Table Tipo String com nome da tabela que será executado a instrução Select.

3 Columms Array de String (String[]) com os nomes das colunas que retornarão pela instrução Select. Caso seja null, todas as colunas serão retornadas.

4 Where Tipo String. Define a sentença de filtro na cláusua Where da instrução Select. Como exemplo temos “Nome Like ? AND Estado = ?”, onde cada caracter “?” será substituído por valores passados no parâmetro que se segue.

5 WhereArgs Tipo Array de String contendo os argumentos para completar a sentença do parâmetro 4 (Where), substituindo os argumentos “?” nas sentenças desta cláusula. Para o exemplo dado no parâmetro anterior, seria por exemplo, “Mar%” e “MG” respetivamente.

6 GroupBy Tipo string. Define os campos para efeito Group By da instrução Select. Caso seja nula não passará a instrução campos para agrupamento.

7 Having Tipo string. Clásula de restrição aos dados agrupados. Se passado null, não definirá sentença.

8 OrderBy Tipo string. Define a uma String com o nome dos campos (separados por virgula) que definirão a ordem que os registros serão retornados.

9 Limit Tipo string. Define um número limite de linhas que o Cursor retornará. Se null, não impõe limite.

30 Move o cursor para a primeira linha, testando o sucesso. Caso o cursou não tenha registro a condição If é igual a False, logo, não executando as instrução que se seguem.

31 Cria um objeto do tipo Cliente.

32 a 36 Atribui pra cada membro da classe Cliente, o valor correspondente a coluna da linha do Cursor retornado.

Treinamento Android Pág.: 52 de 96

37 a 40 Atribui valor para os atributos (_Old) da classe cliente.

41 Retorna pelo método o objeto Cliente obtido com os atributos devidamente valorados.

46 Define um método que retorna um List (Collection) de objetos Cliente.

47 a 56 Instruções devidamente explanadas nos comentários do método anterior. Em especial, este método retorna todos os registros da tabela Cliente.

57 Cria um objeto do tipo List de Cliente.

58 Move o cursor para a primeira linha, testando o sucesso. Caso o cursou não tenha registro a condição If é igual a False, logo, não executando as instrução que se seguem.

59 Inicia o laço “do while”.

60 Cria um objeto tipo Cliente.

61 Adiciona o objeto Cliente (ainda sem valores atribuídos aos atributos) para o objeto ListaClientes do tipo List de Cliente.

62 a 66 Atribui valor aos atributos públicos da instância de Cliente recém adicionado ao List.

67 Encerra ou continua a varredura do laço “do while”. Para tanto, utiliza o método MoveNext do cursor, forçando o avanço para a próxima linha do mesmo. Caso não exista mais linhas o laço “do while” é encerrado.

68 Encerra o bloco de código da estrutura “If”.

69 Retorna a lista de clientes obtidos do cursor.

70 Encerra o bloco de código do método.

72 a 91 Mesmo que definido para o método explicando nas linhas anteriores, exceto que no método query, responsável por obter os registro junto ao banco de dados, é aplicado um filtro para trazer somente os registros cujo o campo Nome sejam iniciados com o valor (String) passado como parâmetro para o método.

93 a 113 Método igual ao definido entre as linhas 93 e 113, difere semente porque é utilizado o método “rawquery” no lugar de “query”que utiliza uma instrução SQL explicita para obtenção dos registros junto a tabela Cliente no banco de dados.

115 Define o método privado inserir que exige um parâmetro de entrada do tipo cliente, retornando um valor inteiro.

116 Invoca o método insert do objeto DataBase, passando como parâmetros o objeto que contem o nome da tabela a ser afetada, um valor string vazio (não definindo uma condição para inserção) e por último o parâmetro de entrada do método corrente contendo os valores de ContentValues que representa a lista de campos e seus valores a serem atribuídos aos campos da tabela.

O método insert é uma abstração da classe DataBase, que implementa a instrução Insert em código SQL junto a base de dados do SQLIte. O mesmo ocorrerá para as instruções Update e Delete.

117 Retorna pelo método 0 ou 1 conforme definido na explicação para a linha 116.

118 Encerra o bloco de código do método.

Treinamento Android Pág.: 53 de 96

120 Cria o método público inserir, que recebe um objeto Cliente, retornando um valor inteiro.

121 Define um objeto do tipo ContentValues que recebera a lista de valores para os campos da tabela Cliente a ser inserido pelo método privado insert.

122 a 126 Usa o método put do objeto ContentValues para adicionar valores a lista (nome do campo e valor para o campo).

127 Invoca o método privado insert, passando como parâmetro o objeto “valores” do tipo ContentValues. Retorna para o objeto id o valor 0 ou 1 dependendo do sucesso ou não.

128 Retorna pelo método o valor do objeto id.

129 Encerra o bloco de código do método.

131 Define o método privado alterar, tendo como parâmetros de entrada o seguinte:

Parâmetro Tipo Definição

valores ContentValues Lista de valores na forma de par nome do campo e valor a ser atribuído ao campo na instrução Update.

where String String contendo as sentenças para a cláusula Where da instrução Update.

whereArgs String Valores a serem atribuídos a cada lacuna (?) nas sentenças da cláusula Where na instrução Updadte.

132 Executa o método Update do objeto SQLIteDatabase que exige os parâmetros tratados no item anteior. Retorna um valor igual ou maior a um para os registros afetados pelo método Update, ou zero caso nenhum registro seja afetado.

133 Usa o objeto Log para incluir uma linha de informação no arquivo de log do android.

Obs.: Este recurso é válido, em linhas gerais, para podemos acompanhar o processo na fase de teste por exmplo.

134 Retorna pelo método a quantidade de registrso afetados pelo método Update.

135 Encerra o bloco de código do método.

137 Define o método público alterar, que implementa um parâmetro de entrada tipo Cliente; Retorna um valor inteiro equivalente ao total de registros afetados pelo método.

138 a 142 Já explanado em métodos anteriores

143 Converte o valor do atributo ID do objeto Cliente para String e atribui ao objeto _id.

144 Define uma String contendo a condição da cláusula Where para o método Update.

145 Define um objeto do tipo Array de String para receber os valores a serem atribuídos as lacunas (?) da cláusula Where.

146 Invoca o método privado alterar, passando como parâmetro necessários.

147 Retorna pelo método, o valor retornado pelo método privado alterar, representando a quantidade de registros afetados pelo método Update.

Treinamento Android Pág.: 54 de 96

148 Encerra o bloco de código do método.

150 a 171 O mesmo que o método anterior (método público alterar), mas adicionando a cláusula Where do método Update além do valor da chave primária da tabela Cliente (ID = ?), os valores iniciais obtidos para o registro a ser alterado. Dar-se a esta prática o nome de Concorrência Otimista, já que conforme sugere o nome, trata da concorrência entre possíveis processos que estejam tentando alterar o registro ao mesmo tempo. Imaginemos o seguinte cenário como exemplo, demonstrando o processo na linha do tempo para a concorrência entre dois processos que tentam alterar um registro.

Linha do Tempo Processo Instrução SQL Efeito

Tempo 1.01 Usuário A Select * From Tabela Where ID = 100

Retorna: Col1 = 100, Col2 = Juca e Col3 = 12

Tempo 1.17 Usuário B Select * From Tabela Where ID = 100

Retorna: Col1 = 100, Col2 = Juca e Col3 = 12

Tempo 2.04 Usuário B Update Tabela Set Col2 = Alice, Col3 = 12 Where Col1 = 100 AND Col2 = Juca AND Col3 = 12

O Update ocorre com sucesso, com o campo Col1 sendo alterado de Juca para Alice, pois no memento da execução da instrução Update os valores dos campos do registro eram o mesmo quando da obtenção do registro.

Tempo 2.91 Usuário A Update Tabela Set Col2 = Alice, Col3 = 123 Where Col1 = 100 AND Col2 = Juca AND Col3 = 99

A instrução Update falha, pois, no tempo 2.91, o registro não era mais idêntico ao obtido no tempo 1.01 do processo do Usuário A.

173 a 177 Idêntico ao explicado para o método privado alterar, só que neste caso, utiliza o método delete do objeto SQLIteDataBase.

179 a 185 Idêntico ao explicado ao código do método público alterar, exceto que o objetivo é a exclusão.

187 a 203 O mesmo comentário válido para o método alterarConcorrenciaOtimista, exceto que para operação de exclusão.

205 Define o método fechar sem retorno (void).

206 Verifica se o valor do objeto DataBase, instanciado anteriormente é diferente de null. Ou seja, está conectado.

207 Caso seja diferente de nulo (a condição if), invoca o método close do objeto DataBase, uma instância de SQLIteDatabase, fechando a conexão estabelecida, logo, liberando recursos.

208 Encerra o bloco de instruções da condição if.

209 Encerro o bloco de código do método.

211 Encerro o bloco de código da classe.

Treinamento Android Pág.: 55 de 96

Implementando a classe ClienteListAdapter

Complementando as funcionalidades relativo a classe Cliente que implementa a estrutura do melo Cliente, e a classe ClienteModel, que implementa os métodos de negócio e os métodos CRUD para a tabela Cliente, criaremos agora uma classe especial que se junta a classe Cliente e ClienteModel completando as funcionalidades inerente a camada Model (no tocante ao padrão MVC) do projeto.

A especialidade da classe ClienteListAdapter, é a partir de uma View modelada para expor as colunas e linhas de uma collection, em nosso caso uma lista de objetos Cliente, renderizar uma espécie de Grid na View em questão. Vamos agora observar o código da Listagem 01 e os comentários da Tabela 01.

Listagem 01

1. package android.curso;2.3. import java.util.List;4. import android.content.Context;5. import android.view.LayoutInflater;6. import android.view.View;7. import android.view.ViewGroup;8. import android.widget.BaseAdapter;9. import android.widget.TextView;10.11. public class ClienteListAdapter extends BaseAdapter {12. private Context contexto;13. private List<Cliente> lista;14. public ClienteListAdapter(Context ctx, List<Cliente> list) {15. this.contexto = ctx;16. this.lista = list; 17. }18. 19. public int getCount() {20. return lista.size();21. }22. 23. public Object getItem(int posicao) {24. return lista.get(posicao);25. }26. 27. public long getItemId(int posicao) {28. return posicao;29. }30. 31. public View getView(int posicao, View conversaoView, ViewGroup parenteView) { 32. Cliente cliente = lista.get(posicao);33. LayoutInflater inflater = (LayoutInflater)34. contexto.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 35. View view = inflater.inflate(android.curso.R.layout.listaclientes, null);36. view.setScrollContainer(true);37. TextView id = (TextView) view.findViewById(android.curso.R.id.listaclientes_consultarCliente_id);38. id.setText(String.valueOf(cliente.ID)); 39. TextView nome = (TextView)40. view.findViewById(android.curso.R.id.listaclientes_consultarCliente_nome);41. nome.setText(cliente.NOME); 42. TextView telefone = (TextView)43. view.findViewById(android.curso.R.id.listaclientes_consultarCliente_telefone);44. telefone.setText(cliente.TELEFONE); 45. return view;46. } 47. 48. }

Treinamento Android Pág.: 56 de 96

Tabela 01

Linha Comentário

11 Implementa a classe que herda da classe BaseAdapter, que implementa os métodos úteis para gerar um adaptador de lista.

12 Define um objeto privado tipo Context.

13 Define um objeto privado tipo List, neste caso do modelo Cliente.

14 a 17 Método construtor da classe. Quando invocado, exige um parâmetro de contexto e um com um objeto tipo List da classe Cliente com uma coleção de objetos Cliente para gerar a lista.

Repare que os parâmetros passados pelo método são atribuídos aos membros privado da classe.

19 a 21 Implementa o método que retorna a quantidade de elementos presente na lista de Clientes.

23 a 25 Retorna um objeto obtido na lista de objetos Cliente, baseado na posição (índice) passado por parâmetro para o método.

31 Define o método público que retorna uma View que renderiza a coleção passada por parâmetro ao método construtor da classe, neste caso a classe é ClienteListAdapter que herda a classe BaseAdapter. Para esta renderização, é utilizado controles da View listaclientes.xml.

Nota Importante: Este método nunca é chamado em código explícito, ele é executado automaticamente quando é criado uma instância da classe ListAdapter (aqui ClienteListAdapter) realizando a sincronização dos controles da View indicada com as colunas da List passada como parâmetro ao método construtor da classe. Este método é executado para cada item (linha/registro) da lista.

32 Carrega um objeto Cliente, obtendo-o da lista. Neste caso, o parâmetro posicao recebe um valor que vai de 0 a um número que representa a quantidade de linhas da lista meno 1. Na prática, como o método é chamada para cada registro da lista, posicao recebe o valor índice deste elemento na lista.

33 Cria um objeto tipo LayoutInflater. Este objeto toma como entrada um arquivo XML (neste caso listacliente.xml) e constrói os objetos de Visualização a partir dele.

35 Cria um novo objeto View a partir do método inflate do objeto inflater criado na linha 33. Está será a View que será renderizada no lugar do layout listacliente.xml, que serviu aqui apenas como template da View definitiva.

37 Cria na View o objeto TextView para representar o campo ID da lista de clientes.

38 Atribui o valor do campo ID da lista para o controle Id do tipo TextView recém-criado.

39 a 41 Idem linhas 37 e 38, mas para o campo Nome da lista Cliente.

42 a 44 Idem linhas 37 e 38, mas para o campo Telefone da lista Cliente.

45 Retorna a View com uma linha de registro criada.

46 Encerra o bloco de código do método.

47 Encerra o bloco de código da classe.

Treinamento Android Pág.: 57 de 96

Criando as Classes Activity - Camada Controller - MVC

Implementando Lógica a classe MainActivity

Comentaremos aqui a lógica implementada aos controles Button, que por intermédio de evento Click associado a cada um implementam chamadas a outras Ativity. Esta Activity mapeia os controles da View main, acessada aqui pelo método setContentView, tendo como parâmetro Rlayout.main.Confira na Tabela 01 o comentária para as linhas de código relevantes da Listagem 01.

Listagem 01 – Arquivo de classe MainActivity.java - Completo

1. package android.curso;2.3. import android.app.Activity;4. import android.content.Intent;5. import android.os.Bundle;6. import android.view.View;7. import android.widget.Button;8.9. public class MainActivity extends Activity {10.11. @Override12. public void onCreate(Bundle savedInstanceState) {13. super.onCreate(savedInstanceState);14. setContentView(R.layout.main); 15.16. final Intent intentBuscaClientePorNomeActivity = new Intent(this, BuscaClientePorNomeActivity.class);17. final Intent intentIncluirClienteActivity = new Intent(this, IncluirClienteActivity.class);18. final Intent intentSiteGoogleActivity = new Intent(this, ExecutarBrowserActivity.class);19.20. Button buttonConsultarCliente = (Button) findViewById(R.id.main_buttonConsultarCliente); 21. buttonConsultarCliente.setOnClickListener(new View.OnClickListener(){ 22. public void onClick(View view) { 23. startActivity(intentBuscaClientePorNomeActivity); 24. }25. });26. 27. Button buttonIncluirCliente = (Button) findViewById(R.id.main_buttonIncluirCliente); 28. buttonIncluirCliente.setOnClickListener(new View.OnClickListener(){ 29. public void onClick(View view) { 30. startActivity(intentIncluirClienteActivity); 31. }32. });33. 34. Button buttonBrowser = (Button) findViewById(R.id.main_buttonBrowser); 35. buttonBrowser.setOnClickListener(new View.OnClickListener(){ 36. public void onClick(View view) { 37. startActivity(intentSiteGoogleActivity); }38. });39. }40.41. }

Treinamento Android Pág.: 58 de 96

Tabela 01

Linha Comentário

16 Cria um objeto tipo intent (como uma intenção para use subsequente) que representa a classe BuscaClientePorNomeActivity. Repare que o método construtor utilizado aqui solicita um primeiro parâmetro como sendo o owner (proprietário) do objeto, aqui passado a própria classe Activity Main representada pela referência this. O segundo parâmetro é o método class da própria classe BuscaClientePorNomeActivity.

17 O mesmo que o comentário da linha 16, mas para a classe IncluirClienteActivity.

18 O mesmo que o comentário da linha 16, mas para a classe ExecutarBrowserActivity.

20 Atribui um objeto do tipo Button, nomeado buttonConsultarcliente, tendo como referência o objeto retornado pelo método findViewById. Repare que o parâmetro passado para o método findViewById é uma referência ao nome do Button main_buttonConsultarCliente do método id da classe R, ou seja R.id. main_buttonConsultarCliente e nada mais.

Vale ressaltar a conversão (Cast) por intermédio de (Button) compatibilizando o tipo retornado pelo método findViewById com o tipo atribuído ao objeto buttonConsultarcliente.

Repare que a referência a um objeto de uma View, é feito eclusivamente pelo recurso que o representa na classe R.

21 Associa o evento OnClick de Listener ao objeto buttonConsultarCliente recem criado.

22 Implementa o método associado ao evento OnClick para o controle Button em questão.

23 Usa o método startActivity da classe Activity parar executar a intent passada como parâmetro. Neste caso a execução da intent intentBuscaClientePorNomeActivity que representa a classe BuscaClientePorNomeActivity.

24 Encerra o bloco de código do método onClick.

25 Encerra o bloco de código que adiciona o evento OnClick de Listener ao objeto Button buttonConsultarCliente.

27 a 32 O mesmo que explicado para as linhas 21 a 25, mas para o Button main_buttonIncluirCliente.

34 a 38 O mesmo que explicado para as linhas 21 a 25, mas para o Button main_buttonBrowser.

39 Encerra o bloco de código do método onCreate.

41 Encerra o bloco de código da classe.

Treinamento Android Pág.: 59 de 96

Implementando Lógica a Classe BuscaClientePorNomeActivity

Esta classe implementa a lógica para a View BuscaClientePorNome, funcionando como Page Controller da mesma. A ideia básica é pegar o que foi digitado no controle TextView e passar como parâmetro para a classe ListaClientesActivity que será executada na sequência exibindo os registros (tabela Cliente) obtidos junto ao banco de dados.Confira na Tabela 01 os comentários para as linhas de código relevantes da Listagem 01.

Listagem 01

1. package android.curso;2.3. import android.app.Activity;4. import android.content.Intent;5. import android.os.Bundle;6. import android.view.View;7. import android.widget.Button;8. import android.widget.EditText;9.10.11. public class BuscaClientePorNomeActivity extends Activity {12. private Intent intent;13. @Override14. public void onCreate(Bundle savedInstanceState) {15. super.onCreate(savedInstanceState);16. setContentView(R.layout.buscaclientepornome);17. intent = new Intent(this, ListaClientesActivity.class);18. 19. Button ButtonPesquisar = 20. (Button) findViewById(R.id.buscaclientepornome_ButtonPesquisar); 21. ButtonPesquisar.setOnClickListener(new View.OnClickListener(){ 22. public void onClick(View view) { 23. EditText EditTextNome =24. (EditText) findViewById(R.id.buscaclientepornome_EditTextNome);25. String textodigitado = EditTextNome.getText().toString();26. Bundle parametros = new Bundle(); 27. parametros.putString("ParteNome", textodigitado); 28. intent.putExtra("Par teNome", textodigitado);29. startActivity(intent);30. }31. });32. 33. Button ButtonVoltar = 34. (Button) findViewById(R.id.buscaclientepornome_ButtonCancelar); 35. ButtonVoltar.setOnClickListener(new View.OnClickListener(){ 36. public void onClick(View view) { 37. finish();38. }39. }); 40. }41. }

Treinamento Android Pág.: 60 de 96

Tabela 01

Linha Comentário

16 Cria um objeto Intent para a classe ListaClientesActivity.

19 a 20 Cria um objeto Button com base no controle ButtonPesquisar da View buscaclientepornome.

21 Inscreve o controle Button no Listener da View. Caso ocorro o evento Click sobre o controle o procedimento associado a este evento é executado.

22 Define o método para o evento onclick do controle.

23 a 24 Cria um objeto TextView para representar o controle buscaclientepornome_EditTextNome da View buscarclientenome.xml, a partir do identificador (id) da classe R.

25 Recupera o texto digitado no controle EditTextNome para um objeto tipo String.

26 Cria um objeto Bundle para armazenar valores de parâmetros a serem passados para a próxima Intent a ser executada. Assim a próxima Itente pode lançar mão desses valores para processar algo. Neste caso, usar como parâmetro na execução do método de pesquisa que preencherá a lista de clients.

27 Usa o método putExtra para adicionar um parâmetro a ser recuperado pela Intent após ser executada, tendo como nome ParteNome e valor igual ao atribuído ao objeto textodigitado.

28 Executa a Intent, neste caso, ListaClientesActivity.

29 Encerra o bloco de código do método onClick.

30 Encerra o bloco de código do método setOnClickListener.

33 a 36 Define o procedimento para o evento click do objeto buscaclientepornome_ButtonCancelar.

37 Executa o método finish da Activity, retornando o processo para a Activity que partiu a ordem de execução da mesma.

38 Encerra o bloco de código do método onClick.

39 Encerra o bloco de código do método setOnClickListener.

40 Encerra o bloco de código do método onCrate da classe.

41 Encerra o bloco de código da classe.

Treinamento Android Pág.: 61 de 96

Implementando Lógica a classe ListaClientesActivity

Processa a exibição da lista de clentes, utilizando para tanto a classe ClienteListAdapter que constroi uma lista de clientes renderizando o resultado em uma View passada como parâmetro. Neste caso a View listaclientes.xml.

Confira observando o código da Listagem 01 e Tabela 01 com os respectivos comentários.

Listagem 01 – Arquivo de classe ListaClientesActivity.java – Completo

1. package android.curso;2.3. import java.util.List;4. import android.app.ListActivity;5. import android.content.Intent;6. import android.os.Bundle;7. import android.view.Menu;8. import android.view.MenuItem;9. import android.view.View;10. import android.widget.ListView;11.12. public class ListaClientesActivity extends ListActivity {13. private List<Cliente> clientes;14. public static ClienteModel modelocliente;15. protected static final int EDITAR = 1;16. protected static final int VOLTAR = 2;17. private int registroSelecionado = 0;18.19. @Override20. public void onCreate(Bundle savedInstanceState) {21. super.onCreate(savedInstanceState); 22. atualizarLista(); 23. }24. 25. protected void atualizarLista() {26. Bundle parametros = getIntent().getExtras();27. String partenome = parametros.getString("ParteNome"); 28. modelocliente = new ClienteModel(this);29. clientes = modelocliente.listaClientesPorNome(partenome); 30. setListAdapter(new ClienteListAdapter(this, clientes)); 31. }32.33. @Override34. public boolean onCreateOptionsMenu(Menu menu) {35. super.onCreateOptionsMenu(menu);36. menu.add(0, EDITAR, 0, "Editar Cliente").setIcon(R.drawable.ic_bteditar);37. menu.add(0, VOLTAR, 0, "Voltar").setIcon(R.drawable.ic_btvoltar);38. return true;39. }40. 41. @Override42. public boolean onMenuItemSelected(int featureId, MenuItem item) {43. switch (item.getItemId()) {44. case EDITAR:45. Cliente cliente = clientes.get(registroSelecionado);46. Intent itEditarCliente = new Intent(this, EditarClienteActivity.class);47. itEditarCliente.putExtra("idCliente", cliente.ID);48. startActivityForResult(itEditarCliente, EDITAR);49. break;50. case VOLTAR:51. finish();52. break;

Treinamento Android Pág.: 62 de 96

53. }54. return true;55. }56.57. @Override58. protected void onListItemClick(ListView l, View v, int posicao, long id) {59. super.onListItemClick(l, v, posicao, id);60. if (posicao != 0) {61. registroSelecionado = posicao;62. Cliente cliente = clientes.get(registroSelecionado);63. Intent itEditarCliente = new Intent(this, EditarClienteActivity.class);64. itEditarCliente.putExtra("idCliente", cliente.ID);65. startActivityForResult(itEditarCliente, EDITAR);66. }67. }68. 69. @Override70. protected void onActivityResult(int codigo, int codigoRetorno, Intent it) {71. super.onActivityResult(codigo, codigoRetorno, it);72. if (codigoRetorno == RESULT_OK) {73. atualizarLista();74. }75. }76.77. @Override78. protected void onDestroy() {79. super.onDestroy();80. modelocliente.fechar();81. }82.83. }

Tabela 01

Linha Comentário

12 Define a assinatura da classe, estendendo (herança) para o tipo ListActivity, um tipo especial de Activity que implementa métodos específicos para renderização de uma lista de valores em forma tabular, usando os controles da View definida na classe Adapter chamada pelo método setListAdapter da classe ListActivity.

13 Cria um objeto tipo Array de objetos Cliente.

14 Cria uma instância da classe ClienteModel que implementa os métodos de negócio sobre cliente.

15 a 16 Cria dois objetos tipo int com valores 1 e 2, respectivamente Editar e Voltar para servir de flag para execução do processo da Activity.

22 No evento onCreate da classe invoca o método atualizarLista que procede a busca de registros a ser renderizado.

25 Define o método atualizaLista sem parâmetros e sem retorno.

26 Define um objeto tipo Bundle para conter a lista de parâmetros obtido pelo método getExtras, da Intent corrente. Lembrar que na Intent que chamou a atual, foi passado esses parâmetros pelo método putExtras desta mesma Intent.

27 Atribui o valor do parâmetro ParteNome contido no objeto Bundle parametros.

28 Cria uma instância da classe ModeloCliente para o objeto modelocliente definido anteriormente.

Treinamento Android Pág.: 63 de 96

29 Atribui ao objeto clientes, tipo List de Cliente, definido anteriormente, a lista de clientes retornada pelo método listaClientesPorNome da classe ClienteModel, passando como parâmetro o objeto partenome com o valor de parâmetro recuperado pelo método getExtras da Activity corrente..

30 Invoca o método setListAdapter da Activity corrente, que é do tipo LitActivity, passando como parâmetro uma instância da classe ClienteListAdapter, com os parâmetros this (própria classe) e a lista de clientes representada aqui pelo objeto clientes.

O método setLisAdapter pertence a classe estendida ListActivity, e processa a renderização dos registros passado por parâmetro a classe ClienteListAdapter, que conhece qual View utilizar para tanto.

31 Encerra o bloco de código da classe.

33 a 39 Cria um objeto menu, com dois itens de menu, que só será exibido quando acionado o botão Menu do dispositivo. Ele não é necessário em nosso exercíco, servindo apenas de exemplo de como criar um objeto desta natureza.

42 a 55 Implementa o procedimento para o evento onMenuItemSelected, acionado toda vez que uma opção de menu for selecionada.

58 a 59 Define o procedimento para o evento onListItemClick que ocorre quando um item da lista é selecionado.

60 Inicia o bloco de instrução if, caso o valor do parâmetro posicao for difrente de zero. Será diferente de zero caso uma ação de seleção por parte do usuário ocorra sobre a lista de valores.

61 Atribui ao objeto registroselecionado o índice da linha selecionada na lista.

62 Usando o método get do objeto List de cliente, atribui ao objeto Cliente o Cliente da lista baseado no índice passado por parâmetro.

63 Cria um objeto Intent a partir da classe EditarClienteActivity que será ativada no processo que se segue.

64 Atribui a lista de parâmetros (método putExtra) o parâmetro nomeado como idCliente o valor do atributo id do objeto Cliente selecionado.

65 Invoca o método starActivityForResult, passando como parâmetro a Intent recém-criada e o objeto EDITAR como flag.

Este método permite executar uma Intent, mas ao finalizar o processo da mesma, retornando a Intent que chamou tal processo executar algo. Neste caso, como veremos na sequência, no método onActivityResult.

66 Encerra o bloco de código do método.

67 Encerra o bloco de código da classe.

69 a 75 Implementa (reescreve o método na classe pai) onActivityResult, que ocorre quando o processamento retorna da Intent executada a partir desta, verificando o valor do parâmetro codigoRetorno, passado pela Intent que este em execução. Caso o valor seja igual a constante tipo int RESULT_OK atualiza a lista chamando o método atualizarLista da classe corrente.

78 a 81 Implementa (reescreve o método na classe pai) onDestroy, destruindo o objeto em memória com a lista de Cliente.

83 Encerra o bloco de código da classe.

Treinamento Android Pág.: 64 de 96

Implementando Lógica a classe EditarClienteActivity

Permite a edição de um objeto Cliente, procedendo as operações de Alteração e Exclusão. Para tanto faz uso dos métodos de negócio da classe ClienteModel e Cliente.

Confira observando o código da Listagem 01 e Tabela 01 com os respectivos comentários.

Listagem 01 – Arquivo de classe EditarClienteActivity.java

1. package android.curso;2.3. import android.app.Activity;4. import android.os.Bundle;5. import android.view.View;6. import android.widget.Button;7. import android.widget.EditText;8.9. public class EditarClienteActivity extends Activity {10. private ClienteModel modelocliente;11. private Cliente cliente;12. private EditText campoId;13. private EditText campoNome;14. private EditText campoCidade;15. private EditText campoEstado;16. private EditText campoTelefone;17.18. @Override19. public void onCreate(Bundle savedInstanceState) {20. super.onCreate(savedInstanceState);21. setContentView(R.layout.editarcliente);22. campoId = (EditText) findViewById(R.id.editarcliente_editTextId);23. campoNome = (EditText) findViewById(R.id.editarcliente_editTextNome); 24. campoCidade = (EditText) findViewById(R.id.editarcliente_editTextCidade); 25. campoEstado = (EditText) findViewById(R.id.editarcliente_editTextEstado); 26. campoTelefone = (EditText) findViewById(R.id.editarcliente_editTextTelefone);27. cliente = new Cliente(); 28. modelocliente = new ClienteModel(this);29. Bundle parametros = getIntent().getExtras();30. long id = parametros.getLong("idCliente"); 31. cliente = modelocliente.buscarCliente(id); 32. campoId.setText(String.valueOf(id));33. campoNome.setText(cliente.NOME);34. campoCidade.setText(cliente.CIDADE);35. campoEstado.setText(cliente.ESTADO);36. campoTelefone.setText(cliente.TELEFONE);37.38. Button ButtonAlterar = (Button) findViewById(R.id.editarcliente_buttonAlterar); 39. ButtonAlterar.setOnClickListener(new View.OnClickListener(){ 40. public void onClick(View view) { 41. cliente.ID = Long.parseLong(campoId.getText().toString()); 42. cliente.NOME = campoNome.getText().toString();43. cliente.CIDADE = campoCidade.getText().toString();44. cliente.ESTADO = campoEstado.getText().toString();45. cliente.TELEFONE = campoTelefone.getText().toString(); 46. modelocliente.alterar(cliente);47. setResult(RESULT_OK);48. finish();49. }50. }); 51. 52.

Treinamento Android Pág.: 65 de 96

53. Button ButtonExcluir = (Button) findViewById(R.id.editarcliente_buttonExcluir); 54. ButtonExcluir.setOnClickListener(new View.OnClickListener(){ 55. public void onClick(View view) { 56. modelocliente.excluir(cliente);57. setResult(RESULT_OK);58. finish();59. }60. }); 61. 62. Button ButtonVoltar = (Button) findViewById(R.id.editarcliente_buttonVoltar); 63. ButtonVoltar.setOnClickListener(new View.OnClickListener(){ 64. public void onClick(View view) {65. setResult(RESULT_CANCELED);66. finish();67. }68. }); 69. 70. }71. }

Treinamento Android Pág.: 66 de 96

Implementando Lógica a classe IncluirClienteActivity

Implementa uma interface exclusiva para a o processo de Inclusão. Faz uso dos métodos de negócio da classe ClienteModel e Cliente.

Confira observando o código da Listagem 01 e Tabela 01 com os respectivos comentários.

Listagem 01 – Arquivo de classe IncluirClienteActivity.java

1. package android.curso;2.3. import android.app.Activity;4. import android.os.Bundle;5. import android.view.View;6. import android.widget.Button;7. import android.widget.EditText;8.9. public class IncluirClienteActivity extends Activity {10. private ClienteModel modelocliente;11. private Cliente cliente;12. private EditText campoId;13. private EditText campoNome;14. private EditText campoCidade;15. private EditText campoEstado;16. private EditText campoTelefone;17.18. @Override19. public void onCreate(Bundle savedInstanceState) {20. super.onCreate(savedInstanceState);21. setContentView(R.layout.incluircliente); 22. modelocliente = new ClienteModel(this);23. cliente = new Cliente();24. Button ButtonIncluir = (Button) findViewById(R.id.incluircliente_buttonIncluir); 25. ButtonIncluir.setOnClickListener(new View.OnClickListener(){ 26. public void onClick(View view) { 27. campoId = (EditText) findViewById(R.id.incluircliente_editTextId);28. campoNome = (EditText) findViewById(R.id.incluircliente_editTextNome); 29. campoCidade = (EditText) findViewById(R.id.incluircliente_editTextCidade); 30. campoEstado = (EditText) findViewById(R.id.incluircliente_editTextEstado); 31. campoTelefone = (EditText) findViewById(R.id.incluircliente_editTextTelefone); 32. cliente.ID = Long.parseLong(campoId.getText().toString());33. cliente.NOME = campoNome.getText().toString();34. cliente.CIDADE = campoCidade.getText().toString();35. cliente.ESTADO = campoEstado.getText().toString();36. cliente.TELEFONE = campoTelefone.getText().toString(); 37. modelocliente.inserir(cliente);38. finish();39. }40. }); 41. 42. Button ButtonVoltar = (Button) findViewById(R.id.incluircliente_buttonVoltar); 43. ButtonVoltar.setOnClickListener(new View.OnClickListener(){ 44. public void onClick(View view) { 45. finish();46. }47. }); 48. }49. }

Treinamento Android Pág.: 67 de 96

Implementando Lógica a classe ExecutarBrowserActivity

Implementa uma interface exclusiva para a o processo de Inclusão. Faz uso dos métodos de negócio da classe ClienteModel e Cliente.

Confira observando o código da Listagem 01 e Tabela 01 com os respectivos comentários.

Listagem 01 – Arquivo de classe ExecutarBrowserActivity.java

package android.curso;

import android.app.Activity;import android.content.Intent;import android.net.Uri;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.EditText;

public class ExecutarBrowserActivity extends Activity implements OnClickListener {@Override

public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.executarbrowser); final Button BTExecutar = (Button) findViewById(R.id.browser_buttonExecutar); BTExecutar.setOnClickListener(this);

}

public void onClick(View view) {final EditText EditUrl = (EditText) findViewById(R.id.browser_editTextURL);Uri uri = Uri.parse(EditUrl.getText().toString());Intent intent = new Intent(Intent.ACTION_VIEW, uri);startActivity(intent);

}}

Treinamento Android Pág.: 68 de 96

Utilizando SMS Content Provider

Para utilizar o ContentProvider da aplicação de mensagens, você deve adicionar as devidas permissões no arquivo AndroidManifest.xml, para ler, escrever e excluir SMS. Veja as instruções abaixo para tanto.

<uses-permission android:name="android.permission.READ_SMS"/> <uses-permission android:name="android.permission.WRITE_SMS"/>

A URI demonstrado a seguir, traz as informações das mensagens, mas sem o corpo da mensagem.

Uri uriSms = Uri.parse("content://sms/inbox");

Na sequência, temos uma URI que traz as informações de uma mensagem específica.

Uri uriSms = Uri.parse("content://sms/1");

Uma vez tendo uma URI, basta implementar um cursor com a mesma. Veja o exemplo a seguir utilizando a URI definida anteriormente.

Cursor c = getContentResolver().query(uriSms, null, null, null, null);

O código abaixo, lista todos os dados de todas as colunas do cursor, aí é só observar chave/valor.

int columns = c.getColumnCount(); while (c.moveToNext()){

for (int i = 0; i < columns; i++) { System.out.println(c.getColumnName(i) +"="+ c.getString(i));

} System.out.println("--");

}

Para apagar uma mensagem, é só usar o código abaixo:

getContentResolver().delete(Uri.parse("content://sms/1"), null, null); getContentResolver().delete(Uri.parse("content://sms/inbox"), "address=88998899", null);

Treinamento Android Pág.: 69 de 96

Criando um Projeto para Listar SMS Recebidos e Enviar o SMS

Passo 01Crie um projeto Android nomeando-o como ProjetoSMS, seguindo a sequência de Figuras de 01 a 04 como orientador para nome do Package e da Activity principal do projeto.

Figura 01 Figura 02

Figura 03 Figura 04

Passo 02

Treinamento Android Pág.: 70 de 96

Criando um WebService em Java no NetBeans

Criando o Projeto

Na prática criaremos um projeto Enterprise Application utilizando o IDE do NetBeans. Este projeto conterá como veremos em seguida, dois aplicativos distintos, sendo o primeiro um Enterprise Java Bean e o segundo um aplicativo War contendo um módulo Web.

Desconsideraremos os segundo aplicativo, utilizando apenas o primeiro construindo no mesmo as classes necessárias para implementar métodos de negócio para um CRUD para uma tabela de banco de dados. Por fim, adicionaremos um WebService que permitirá acesso por intermédio do protocolo Http a qualquer aplicativo com acesso a rede onde reside tal servidor web, ou em nosso caso, a um aparelho com aplicativo Android.

Passo 01 – No IDE do Netbeans, acessando o menu File | New Project, escolha na caixa de dialogo exibida pela Figura 01 a opção Enterprise Application clicando no botão Next.

Figura 01

Passo 02 – Se oriente pela imagem exibida pela Figura 02, definindo um nome para o projeto e um endereço para arquivamento dos fontes do mesmo. Clique no botão Next para prosseguir.

Figura 02

Passo 03 – Conforme demonstrado na caixa de dialogo representada pela Figura 03, define para qual Servidor de Aplicação será feito o deployer do aplicativo e qual API da Java EE será adotado. Repare ainda, que por default, será criado dois aplicativos conforme explicado na introdução. Por fim clique no botão Finish para encerrar, observando na Figura 04 na caixa de dialogo Project a estrutura dos projetos recém criados.

Treinamento Android Pág.: 71 de 96

Figura 03

Figura 04

Passo 04 – Simplesmente para efeito de demonstração de como é fácil criar um Webservice usando o Netbens, façamos um teste acionando o menu de contexto, clicando com o botão direito do mouse sobre o projeto EnterpriseApplicationWS-ejb, na caixa de dialogo Project. No menu que será exibido, escolha New | WebService. Conforme demostrado na Figura 05, defina o nome do WebService como WSTeste. Clique no botão Finish para concretizar observando o novo componente do projeto exibido pela imagem da Figura 06.

Figura 05

Treinamento Android Pág.: 72 de 96

Figura 06

Passo 05 – Repare no código fonte do WebService WSTeste, que na prática este WebService é uma simples classe Java com anotações que a torna acessível (se implantada em um Servidor Web) por intermédio do protocolo Http. Repare as linhas 8, 9 e 11 na Listagem 01, definindo a classe WSTeste como sendo um WebService, sem estado e por fim o definindo o método hello como método possível ser acessado por um Client WebService.

Listagem 01

1. package netbenas.webservice;2.3. import javax.ejb.Stateless;4. import javax.jws.WebMethod;5. import javax.jws.WebParam;6. import javax.jws.WebService;7.8. @WebService(serviceName = "WSTeste")9. @Stateless()10. public class WSTeste {11. @WebMethod(operationName = "hello")12. public String hello(@WebParam(name = "name") String txt) {13. return "Hello " + txt + " !";14. }15. }

Na sequência, interromperemos a tarefa de criação de nosso WebService para providenciarmos uma tabela em um banco de dados para que possa ser criado os métodos de negócio do aplicativo. Adotaremos aqui o Servidor de Banco de Dados Java DB, sendo somente uma opção entre tantas possíveis.

Treinamento Android Pág.: 73 de 96

Criando o Banco de Dados no Servidor Java DB

Passo 01 – Caso a aba Services não esteja sendo exibido em seu IDE, acesse o menu Window | Services para que seja exibido, tendo como resposta a imagem da Figura 01.

Clique com o botão direito do mouse sobre o né Java DB, selecionando a opção Create Database. Na sequência, observe a caixa de dialogo representada pela Figura 02, definindo nome do banco de dados, nome do usuário e password (por questões de didática e para simplificar adotaremos password = 123). Clique no botão Ok para encerrar esta etapa.

Figura 01

Figura 02

Passo 02 – Repare no nó Java DB (Figura 03), na aba Services o banco recém criado. Repare também outro nó indicando o caminho completo como Driver JDBC para o Servidor derby, servidor, porta e nome da base de dados. Com relação a este nó, expandido-o, temos acesso aos objetos de banco de dados (Figura 04). A partir deste ponto criaremos uma tabela que servirá ao nosso projeto.

Figura 03

Treinamento Android Pág.: 74 de 96

Figura 04

Passo 03 – Clicando com o botão direito do mouse sobre o nó Tables (Figura 04), escolha a opção Create Table, tendo como resposta a caixa de dialogo representada pela Figura 05. Observe o campo Table Name, preenchendo-o como Cliente. Repare ainda o botão Add columm. Clique neste botão adicionando os campos conforme definido nas Figuras 06, 07, 08, 09 e 10.

Por fim, observe a Figura 10 com a estrutura final da tabela Cliente.

Figura 05

Figura 06 Figura 07

Treinamento Android Pág.: 75 de 96

Figura 08 Figura 09

Figura 10

Figura 11

Treinamento Android Pág.: 76 de 96

Criando a Classe Cliente Entity

Adotando JPA, criaremos agora uma classe de negócio que representará a Entidade Cliente (Modelo Cliente), promovendo o mapeamento objeto relacional para a tabela Cliente do banco de dados BancoAndroid. A partir desta classe criaremos os métodos de negócio que na sequência do exercício serão expostos pelo WebService.

Passo 01 – Observando a Figura 01, clicando com o botão direito do mouse sobre o nó EnterpriseApplacationWS-ejb, faça a opção ao item New | Entity Classes from Database. Na caixa de dialogo representado pelo Figura 02 escolha no combobox Data Source a opção New, objetivando criar um objeto para conexão ao banco de dados (JNDI).

Figura 01

Figura 02

Passo 02 – Na caixa de dialogo Create Data Source, Figura 03, defina o nome para JNFI Name, escolhendo em seguida a conexão para o banco de dados em Database Connection. Clique no botão Ok passando para a próxima fase.

Figura 03

Treinamento Android Pág.: 77 de 96

Passo 03 – Concluindo o passo anterior, voltemos a atenção a caixa de dialogo New Entity Classes from Databases, Figura 04, agora exibindo as tabelas do banco de dados na caixa Avaliable Tables (aqui somente Cliente).

Selecione a tabela Cliente na lista, clicando em seguida no botão Add observando o resultado na Figura 04. Clique no botão Next observando o resultdo na imagem da Figura 06.

Figura 04

Figura 05

Passo 04 – Aceite as definições apresentadas na Figura 06 definindo somente o Package netbenas.webservices. Clique no botão Next, ainda na Figura 06, e em seguida, agora na Figura 07, clique no botão Finish para encerrar a etapa.

Figura 06

Treinamento Android Pág.: 78 de 96

Figura 07

Repare com atenção a classe Cliente gerada automaticamente pelo processo desta etapa. Na sequência, para encapsular os métodos de negócio para a classe Cliente, criaremos uma classe Session Bean.

Listagem 01

1. package netbenas.webservice;2.3. import java.io.Serializable;4. import javax.persistence.*;5. import javax.validation.constraints.NotNull;6. import javax.validation.constraints.Size;7. import javax.xml.bind.annotation.XmlRootElement;8.9. @Entity10. @Table(name = "CLIENTE")11. @XmlRootElement12. @NamedQueries({13. @NamedQuery(name = "Cliente.findAll", query = "SELECT c FROM Cliente c"),14. @NamedQuery(name = "Cliente.findById", query = "SELECT c FROM Cliente c WHERE c.id = :id"),15. @NamedQuery(name = "Cliente.findByNome", query = "SELECT c FROM Cliente c WHERE c.nome = :nome"),16. @NamedQuery(name = "Cliente.findByCidade", query = "SELECT c FROM Cliente c WHERE c.cidade =

:cidade"),17. @NamedQuery(name = "Cliente.findByEstado", query = "SELECT c FROM Cliente c WHERE c.estado =

:estado"),18. @NamedQuery(name = "Cliente.findByTelefone", query = "SELECT c FROM Cliente c WHERE c.telefone =

:telefone")})19. public class Cliente implements Serializable {20. private static final long serialVersionUID = 1L;21. @Id22. @Basic(optional = false)23. @NotNull24. @Column(name = "ID")25. private Long id;26. @Basic(optional = false)27. @NotNull28. @Size(min = 1, max = 50)29. @Column(name = "NOME")30. private String nome;31. @Size(max = 50)32. @Column(name = "CIDADE")33. private String cidade;34. @Size(max = 2)35. @Column(name = "ESTADO")

Treinamento Android Pág.: 79 de 96

36. private String estado;37. @Size(max = 20)38. @Column(name = "TELEFONE")39. private String telefone;40.41. public Cliente() {42. }43.44. public Cliente(Long id) {45. this.id = id;46. }47.48. public Cliente(Long id, String nome) {49. this.id = id;50. this.nome = nome;51. }52.53. public Long getId() {54. return id;55. }56.57. public void setId(Long id) {58. this.id = id;59. }60.61. public String getNome() {62. return nome;63. }64.65. public void setNome(String nome) {66. this.nome = nome;67. }68.69. public String getCidade() {70. return cidade;71. }72.73. public void setCidade(String cidade) {74. this.cidade = cidade;75. }76.77. public String getEstado() {78. return estado;79. }80.81. public void setEstado(String estado) {82. this.estado = estado;83. }84.85. public String getTelefone() {86. return telefone;87. }88.89. public void setTelefone(String telefone) {90. this.telefone = telefone;91. }92.93. @Override94. public int hashCode() {95. int hash = 0;96. hash += (id != null ? id.hashCode() : 0);97. return hash;

Treinamento Android Pág.: 80 de 96

98. }99.100. @Override101. public boolean equals(Object object) {102. if (!(object instanceof Cliente)) {103. return false;104. }105. Cliente other = (Cliente) object;106. if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {107. return false;108. }109. return true;110. }111.112. @Override113. public String toString() {114. return "netbenas.webservice.Cliente[ id=" + id + " ]";115. }116. 117. }

Treinamento Android Pág.: 81 de 96

Criando a Classe Session BeanEsta classe implementa os métodos de negócio a serem expostos pelo WebService. Na prática teremos aqui os métodos para manipulação de um objeto cliente quanto a inserção, exclusão, alteração, bem como, métos que retornam um objeto cliente ou uma lista desses.

Passo 01 – Com o botão direito do mouse, clique em EnterpriseApplicationWS-ejb na caixa de dialogo Project optando por New | Session Beans For Entity Classes. Confira isto na Figura 01 para tanto, clicando no botão Next finalizando.

Figura 01

Passo 02 – Escolha uma entidade em Avaliable Entity Classes, clicando no botão Add conforme Figura 02. Conforme Figura 03 clique no botão Finish para encerrar o processo.

Figura 02

Figura 03

Treinamento Android Pág.: 82 de 96

Observe a Figura 04 exibindo a classe que acabamos de criar, bem como, as Listagens 01 e 02 com todos os métodos formam o CRUD da classe.

Figura 04

Listagem 01

1. package netbenas.webservice;2.3. import java.util.List;4. import javax.persistence.EntityManager;5.6. public abstract class AbstractFacade<T> {7. private Class<T> entityClass;8.9. public AbstractFacade(Class<T> entityClass) {10. this.entityClass = entityClass;11. }12.13. protected abstract EntityManager getEntityManager();14.15. public void create(T entity) {16. getEntityManager().persist(entity);17. }18.19. public void edit(T entity) {20. getEntityManager().merge(entity);21. }22.23. public void remove(T entity) {24. getEntityManager().remove(getEntityManager().merge(entity));25. }26.27. public T find(Object id) {28. return getEntityManager().find(entityClass, id);29. }30.31. public List<T> findAll() {32. javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();33. cq.select(cq.from(entityClass));34. return getEntityManager().createQuery(cq).getResultList();35. }

Treinamento Android Pág.: 83 de 96

36.37. public List<T> findRange(int[] range) {38. javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();39. cq.select(cq.from(entityClass));40. javax.persistence.Query q = getEntityManager().createQuery(cq);41. q.setMaxResults(range[1] - range[0]);42. q.setFirstResult(range[0]);43. return q.getResultList();44. }45.46. public int count() {47. javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();48. javax.persistence.criteria.Root<T> rt = cq.from(entityClass);49. cq.select(getEntityManager().getCriteriaBuilder().count(rt));50. javax.persistence.Query q = getEntityManager().createQuery(cq);51. return ((Long) q.getSingleResult()).intValue();52. }53. 54. }

Listagem 02

1. package netbenas.webservice;2.3. import javax.ejb.Stateless;4. import javax.persistence.EntityManager;5. import javax.persistence.PersistenceContext;6.7. @Stateless8. public class ClienteFacade extends AbstractFacade<Cliente> {9. @PersistenceContext(unitName = "EnterpriseApplicationWS-ejbPU")10. private EntityManager em;11.12. @Override13. protected EntityManager getEntityManager() {14. return em;15. }16.17. public ClienteFacade() {18. super(Cliente.class);19. }20. 21. }

Treinamento Android Pág.: 84 de 96

Criar o WebService para a Classe Cliente

Figura 01

Figura 02

Figura 03

Treinamento Android Pág.: 85 de 96

Figura 04

Listagem 01

1. package netbenas.webservice;2.3. import java.util.List;4. import javax.ejb.EJB;5. import javax.jws.WebService;6. import javax.ejb.Stateless;7. import javax.jws.Oneway;8. import javax.jws.WebMethod;9. import javax.jws.WebParam;10.11. @WebService(serviceName = "WSCliente")12. @Stateless()13. public class WSCliente {14. @EJB15. private ClienteFacade ejbRef;// Add business logic below. (Right-click in editor and choose16. // "Insert Code > Add Web Service Operation")17.18. @WebMethod(operationName = "create")19. @Oneway20. public void create(@WebParam(name = "entity") Cliente entity) {21. ejbRef.create(entity);22. }23.24. @WebMethod(operationName = "edit")25. @Oneway26. public void edit(@WebParam(name = "entity") Cliente entity) {27. ejbRef.edit(entity);28. }29.30. @WebMethod(operationName = "remove")31. @Oneway32. public void remove(@WebParam(name = "entity") Cliente entity) {33. ejbRef.remove(entity);34. }35.36. @WebMethod(operationName = "find")37. public Cliente find(@WebParam(name = "id") Object id) {

Treinamento Android Pág.: 86 de 96

38. return ejbRef.find(id);39. }40.41. @WebMethod(operationName = "findAll")42. public List<Cliente> findAll() {43. return ejbRef.findAll();44. }45.46. @WebMethod(operationName = "findRange")47. public List<Cliente> findRange(@WebParam(name = "range") int[] range) {48. return ejbRef.findRange(range);49. }50.51. @WebMethod(operationName = "count")52. public int count() {53. return ejbRef.count();54. }55. 56. }

Figura 05

Treinamento Android Pág.: 87 de 96

Configurando o Servidor GlassFish

Figura 01

Figura 02

Figura 03

Figura 04

Treinamento Android Pág.: 88 de 96

Figura 05

Treinamento Android Pág.: 89 de 96

Testando o WebService

Figura 01

Figura 02

Figura 03

Treinamento Android Pág.: 90 de 96

Figura 04

Figura 05

Figura 06

Treinamento Android Pág.: 91 de 96

Criando a Aplicação Android para Consumir o WebService

Listagem 01

1. <?xml version="1.0" encoding="utf-8"?>2. <LinearLayout 3. xmlns:android="http://schemas.android.com/apk/res/android" 4. android:id="@+id/ConsultaCliente_main"5. android:orientation="vertical"6. android:layout_height="fill_parent"7. android:layout_width="fill_parent">8.9. <!-- Header -->10. <LinearLayout 11. android:id="@+id/ConsultaCliente_header"12. android:background="#ff347c12"13. android:layout_height="wrap_content"14. android:layout_width="fill_parent" >15.16. <TextView 17. android:id="@+id/ConsultaCliente_item1"18. android:layout_height="fill_parent"19. android:layout_width="wrap_content"20. android:text="Nome"21. android:width="150dip"22. android:height="25dip"23. android:layout_marginTop="5dip"24. android:layout_marginBottom="5dip"25. android:textStyle="bold"26. android:layout_marginLeft="5dip" />27.28. <TextView 29. android:id="@+id/ConsultaCliente_item2"30. android:layout_height="fill_parent"31. android:layout_width="wrap_content"32. android:text="Telfone"33. android:width="80dip"34. android:height="15dip"35. android:layout_marginTop="5dip"36. android:layout_marginBottom="5dip"37. android:textStyle="bold"38. android:layout_marginLeft="10dip" />39.40. <TextView android:id="@+id/ConsultaCliente_item3"41. android:layout_height="fill_parent"42. android:layout_width="wrap_content"43. android:text="Cidade"44. android:width="115dip"45. android:height="25dip"46. android:layout_marginTop="5dip"47. android:layout_marginBottom="5dip"48. android:textStyle="bold" />49.50. </LinearLayout>51. 52. <!-- List Divider -->53. <View 54. android:layout_width="fill_parent"55. android:layout_height="5dip" />56. 57. <!-- ListView (grid_items) -->

Treinamento Android Pág.: 92 de 96

58. <LinearLayout 59. android:id="@+id/ConsultaCliente_LinearLayout"60. android:layout_width="wrap_content"61. android:layout_height="fill_parent">62. <ListView android:id="@+id/ConsultaCliente_listview"63. android:layout_height="fill_parent"64. android:layout_width="fill_parent" >65. </ListView>66. </LinearLayout>67. 68. </LinearLayout>

Listagem 02

1. <?xml version="1.0" encoding="utf-8"?>2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"3. android:orientation="horizontal"4. android:layout_width="fill_parent"5. android:layout_height="fill_parent">6.7. <TextView android:id="@+id/ConsultaCliente_item1"8. android:layout_height="fill_parent"9. android:layout_width="wrap_content"10. android:width="150dip"11. android:height="40dip"12. android:layout_marginLeft="5dip"13. android:layout_marginTop="10dip"14. android:layout_marginBottom="5dip" />15.16. <TextView android:id="@+id/ConsultaCliente_item2"17. android:layout_height="fill_parent"18. android:layout_width="wrap_content"19. android:width="80dip"20. android:height="40dip"21. android:layout_marginLeft="10dip"22. android:layout_marginTop="10dip"23. android:layout_marginBottom="5dip" />24.25. <TextView android:id="@+id/ConsultaCliente_item3"26. android:layout_height="fill_parent"27. android:layout_width="wrap_content"28. android:width="115dip"29. android:height="40dip"30. android:layout_marginRight="5dip"31. android:layout_marginTop="10dip"32. android:layout_marginBottom="5dip" />33.34. </LinearLayout>

Treinamento Android Pág.: 93 de 96

Listagem 03

1. package android.curso;2.3. import java.io.IOException;4. import org.ksoap2.SoapEnvelope;5. import org.ksoap2.serialization.KvmSerializable;6. import org.ksoap2.serialization.SoapObject;7. import org.ksoap2.serialization.SoapSerializationEnvelope;8. import org.ksoap2.transport.HttpTransportSE;9. import org.xmlpull.v1.XmlPullParserException;10. import android.util.Log;11.12. public class WebServiceCliente {13. 14. private static final String SOAP_ACTION = "http://webservice.netbeans/findAll"; 15. private static final String NAMESPACE = "http://webservice.netbeans/"; 16. private static final String URL = "http://192.168.0.199:14848/WSCliente/WSCliente"; 17. private SoapObject[] Lista;18.19. public WebServiceCliente(String METHOD_NAME) throws IOException, XmlPullParserException 20. try { 21. SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME); 22. SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); 23. envelope.dotNet = true;24. envelope.setOutputSoapObject(request); 25. HttpTransportSE androidHttpTransport = new HttpTransportSE(URL); 26. androidHttpTransport.call(SOAP_ACTION, envelope); 27. KvmSerializable response = null;28. response = (KvmSerializable)envelope.bodyIn; 29. if (METHOD_NAME.equals("findAll")) {30. Lista = new SoapObject[response.getPropertyCount()];31. for (int i = 0; i < response.getPropertyCount(); i++) {32. Lista[i] = (SoapObject) response.getProperty(i);33. } 34. } 35. } catch (Exception e) { 36. e.printStackTrace(); 37. } 38. } 39. 40. public SoapObject[] RetornaTodosclientes() { 41. return Lista;42. } 43. 44. }

Treinamento Android Pág.: 94 de 96

Listagem 04

1. package android.curso;2.3. import java.io.IOException;4. import java.util.ArrayList;5. import java.util.HashMap;6.7. import org.ksoap2.serialization.SoapObject;8. import org.xmlpull.v1.XmlPullParserException;9. import android.app.Activity;10. import android.app.ProgressDialog;11. import android.os.Bundle;12. import android.os.Handler;13. import android.widget.ListView;14. import android.widget.SimpleAdapter;15. import android.widget.Toast;16.17. public class ConsultaClienteActivity extends Activity {18.19. private ListView ListViewClientes;20. private SoapObject[] ListaSoap;21. private ArrayList<HashMap<String, String>> Lista = new ArrayList<HashMap<String,String>>();22. private ProgressDialog Progressdialog;23. private Handler handler = new Handler();24.25. @Override26. public void onCreate(Bundle bundle) {27. super.onCreate(bundle);28. setContentView(R.layout.consultacliente);29. ListViewClientes = (ListView) findViewById(R.id.ConsultaCliente_listview); 30. Pesquisar();31. }32.33. private void Pesquisar() {34. Progressdialog = ProgressDialog.show(ConsultaClienteActivity.this, 35. "Aviso", "Aguardando resposta do WS.");36. new Thread() {37. @Override38. public void run(){39. WebServiceCliente ws;40. try {41. ws = new WebServiceCliente("findAll");42. ListaSoap = ws.RetornaTodosclientes(); 43. Lista.clear();44. for (int i = 0; i < ListaSoap.length; i++) {45. HashMap<String, String> registro = 46. new HashMap<String, String>();47. registro.put("NOME",48. ListaSoap[i].getPropertyAsString(3));49. registro.put("CIDADE",50. ListaSoap[i].getPropertyAsString(4));51. registro.put("TELEFONE",52. ListaSoap[i].getPropertyAsString(0));53. Lista.add(registro);54. }55.56. FinalizarDialogo(false, "Finalizado --> ");57. } catch (IOException e) {58. e.printStackTrace();59. FinalizarDialogo(false, "Erro IOException e --> " + e.toString());60. } catch (XmlPullParserException e) {61. e.printStackTrace();

Treinamento Android Pág.: 95 de 96

62. FinalizarDialogo(false, e.toString());63. } 64. }65. }.start();66. }67. 68. private void FinalizarDialogo(final Boolean OcorreuErro, final String MsgErro) {69. handler.post(new Runnable() {70. public void run() {71. if (OcorreuErro) {72. Toast.makeText(getApplicationContext(), "OcorreuErro: " + 73. MsgErro, Toast.LENGTH_LONG).show();74. }75. else {76. AtualizaTela();77. }78. Progressdialog.dismiss(); 79. }80. });81. }82.83. private void AtualizaTela() {84. String [] Colunas = new String[] {"NOME", "CIDADE", "TELEFONE"};85. int[] Controles = new int[] {R.id.ConsultaCliente_item1, 86. R.id.ConsultaCliente_item2, 87. R.id.ConsultaCliente_item3};88. ListViewClientes.setAdapter(new SimpleAdapter(this, Lista, 89. R.layout.gridconsultacliente, Colunas, Controles));90. }91.92. }

Treinamento Android Pág.: 96 de 96