App Alunos
Definições de Projeto Implementação de uma app para Manipulação de Dados de Alunos Em linhas gerais, a app consiste em: Manter dados de alunos; Entrar em contato com alunos; Trocar dados com um servidor WEB; e Compartilhar conteúdo em mídias ;
Funcionalidade da App
CADASTRO DE ALUNOS
Começando pelo Cadastro Neste requisito da nossa App, precisamos de: Uma tela para listar Alunos Outra para cadastrar ou alterar dados de Alunos A exclusão deve ocorrer com a seleção de um aluno na tela de listagem
Tela Inicial: Listagem dos alunos Componentes: Nome do aluno que se deseja incluir na listagem EditText Botão para adicionar o nome do aluno à lista. Button Lista com nomes dos alunos. ListView, que recebe uma coleção de Objetos e lista seus dados
Listaalunoslayout.xml Campo de Texto id=ednomelistagem
Listaalunoslayout.xml Componente Botão id=braddlistagem
Listaalunoslayout.xml Componente Lista para exibir alunos id=lvlistagem
Tela Inicial: Listagem dos alunos Texto nome do aluno e o botão estão visíveis Observe: Componentes EditText e Button estão visíveis No entanto, a ListView não aparece Isso ocorre porque nossa lista ainda está vazia Lista alunos ainda vazia
Controladores a as regras de negócio Os layouts xml (telas) estão associadas a classes Java (controladores), responsáveis pela implementação de suas regras de negócio listaalunoslayou.xml é controlada pela classe ListaAlunosActivity.java A classe de controle deve capturar os eventos e componentes da tela e implementar as regras de negócio necessárias às funcionalidades da App
Atributos Componentes da tela acessados pela classe de controle Coleção de alunos Método para inicializar os atributos
Inicialização dos Atributos Associa a tela (layout) ao controlador (java) Captura o click no botão Associa componentes da View a atributos da Activity
Inicialização dos Atributos Implementação anônima do OnClickListener
Observações com relação ao ListView É preciso inicializar a coleção de alunos e exibir os nomes na ListView Porém, ListView pode assumir diversos formatos de visualização ListView precisa da ajuda de alguém que saiba como organizar os dados na tela ListView precisa do apoio de um Adaptador, que saiba converter objetos Java para componentes de Tela: Adapter.
ListView com Layouts diferentes
Novos atributos Declaração dos novos atributos Converte listas e vetores em View Define o layout que o Adapter usará
Passo a Passo Associar objetos java a componentes de tela Criar o adaptador que exibe List<Strings> Inicializar: A coleção de nomes de Alunos(List<Strings>); O adaptador (ArrayAdapter<String>); e A ListView que vai exibir os nomes na tela; Por fim, associar o adaptador à ListView
Inicialização da ListView
Passo a passo Atualizar o evento de clique do botão Adicionar Aluno; Adicionar o nome digitado no campo ednome à coleção listaalunos; Limpar o conteúdo do campo ednome; e Atualizar o conteúdo da ListView
Evento de click no botão Implementação do Evento de clique Adiciona o nome informado em ednome na coleção Limpa conteúdo de ednome Atualiza o conteúdo do ListView
Conferindo o Resultado Inclua alguns nomes É possível agregar mais alguma funcionalidade? Que tal exibir um alerta com o nome do aluno, quando do clique em um nome da lista?
Evento de click no ListView Assim como Button, a ListView possui o evento de click. Porém, são dois tipos de click: Click curto, quando o usuário clica em um item da ListView; e Click Longo, quando o usuário clica e segura um item da ListView ; Vamos implementar os eventos de clique Longo e Simples no final do método oncreate()
Cliques da ListView Implementação do Evento de clique simples Implementação do Evento de clique longo true: não executa o click simples false: executa o click simples
E quando giramos o dispositivo? Depois do giro: Lista Vazia! Quando giramos o dispositivo, o Android invoca novamente o método oncreate() da Activity Todos os componentes retornam ao estado inicial
Podemos armazenar o estado da app antes dela ser pausada, parada ou destruída Utilizamos Métodos de Callback, que são métodos usados quando o cliente requer um retorno do servidor, mas não quer ficar bloqueado, esperando. onsaveinstancestate(): chamado quando o Android vai destruir a Activity, mas sabe que vai restaurá-la depois; Persistindo o estado da Activity Não é chamado quando usuário clica em Back onrestoreinstancestate(): Chamado antes da Activity destruída ser chamada pelo usuário
Persistindo o estado da Activity
Para salvar o estado da Activity, usamos o objeto Bundle, gerenciado pelo Android O Bundle empacota um java.util.map O Objeto Bundle é passado pelo Android aos métodos Persistindo o estado da Activity oncreate(), onsaveinstancestate() e onrestoreinstancestate() Podemos utilizar o Map empacotado no Bundle para armazenar o estado da nossa App
Passo a Passo Na classe ListaAlunosActivity, defina rduas constantes: String TAG = "CADASTRO_ALUNO" Usada para registro de mensagens de LOG no Logcat String ALUNOS_KEY = "LISTA" Usada como Chave para o Map do Objeto Bundle; Implementar os métodos onsaveinstancestate() e onrestoreinstancestate() Atualizar o método oncreate(), para tentar recuperar a chave ALUNOS_KEY do Bundle
Salvar estado da Activity Incluir novas constantes:
Salvar estado da Activity Incluir o novo método para salvar:
Restaurar estado da Activity Após salvar, incluir o método para restaurar:
Agora quando giramos o dispositivo... Depois do giro, lista continua preenchida
Resultado exibido no LogCat Pelas mensagens de log, verificamos a lista de alunos sendo salva e recuperada do objeto Bundle
MELHORANDO A APP
Incrementando o cadastro Precisamos Cadastrar e Alterar os dados do aluno Dados: Foto, Nome, Fone, Endereço, Site, E-mail e Nota Como o dispositivo possui uma tela limitada, criaremos uma nova Activity (tela) para edição dos dados dos alunos.
Tela de Cadastro de Alunos Formulário para cadastro de alunos Novos componentes: ImageView: para exibir a foto o usuário, armazenada no próprio device; SeekBar: para que o usuário escolha uma nota, dentro de um intervalo
formulario.xml
AndroidManifest.xml
AndroidManifest.xml Nossa app
AndroidManifest.xml Tela de listagem
AndroidManifest.xml Define ListaAlunoActivity como tela inicial da app
AndroidManifest.xml Tela formulário
Alterando a tela inicial para formulário Seta formulário como página inicial Tela formulário
Antes de prosseguir... Torne novamente a ListaAlunosActivity a tela inicial da nossa aplicação: Tela de listagem
Navegação entre telas Com duas telas na App, é necessário algum mecanismo para navegar entre elas Para isso, é comum o uso menus. Toda Activity sabe tratar menus, basta sobrescrever o método: oncreateoptionsmenu(menu menu), que recebe do Android um menu vazio O próprio Android se encarrega de encaixar o menu na tela Para exibir o menu da App: Basta clicar no Botão Menu do device
Estratégia para definição de Menus Apesar da possibilidade de definição de Menus no código Java, é mais comum o uso de arquivos XML: <item android:id="@+id/menu_novo" android:icon="@drawable/ic_novo" android:showasaction="always" android:title="novo"/> <item android:id="@+id/menu_mapa" android:icon="@drawable/ic_mapa" android:showasaction="always" android:title="mapa"/> O método Activity.onCreateOptionsMenu retorna true para indicar que o menu deve ser exibido na tela
Estratégia para definição de Menus O Android precisa ler o XML com itens do menu e criar objetos do tipo View, a partir das tags Essa é a especialidades dos Inflaters O MenuInflater é especialista em carregar XML de menu O método Activity.onCreateOptionsMenu(Menu menu) nos oferece um objeto Menu vazio, que pode ser utilizado pelo MenuInflater para carregar um XML com itens do menu O método Activity.getMenuInflater() nos devolve um MenuInflater Inflater.inflate(): lê um XML e carrega um Menu
Menu principal Altere o nome da App no arquivo strings.xml
Menu principal Crie o arquivo XML: res/menu/menu_principal: É comum que apenas dois Itens do Menu fiquem visíveis e os demais, ocultos
Menu principal (cont...)
Menu Principal Altere o método oncreateoptionsmenu(menu menu) da classe ListaAlunosActivity:
Executando a App...
Eventos de click Para monitorar o click, precisaremos implementar o método onoptionsitemselected da ListaAlunosActivity Por enquanto, exibiremos apenas uma mensagem num Toast, quando o usuário clicar no item NOVO:
Executando
Navegação entre telas da nossa App Configurada a ActionBar, podemos incrementar ainda mais nossa App. Vamos fazer com que o clique no menu NOVO faça surgir a tela de Formulário Usamos objetos do tipo Intent, que recebem um contexto e uma Activity que deve ser exibida Depois de configurada nossa Intenção, podemos iniciar a nova tela (startactivity)
Abrir formulário No método de clique da ListaAlunosActivity:
Fechar o Formulário
ARMAZENANDO DO DADOS EM BD
MVC em Android Entrada de dados Exibir tela Tela.atualizarVisao() modelo.atualizaestado() modelo.getestado() Notificação de mudanças
Persistência com SQLite A tela de Listagem da App permite o cadastro do nome dos alunos e os exibe em uma ListView Porém, surgem alguns problemas nessa abordagem: Os dados são perdidos quando a App é destruída Precisamos de outros dados para o Aluno Como resposta, poderíamos: Persistir os dados em um Bando de Dados Usar a tela de Formulário para cadastro e alteração de dados do Aluno
Criar um bean Aluno Não se esqueça dos métodos get/set
Pensando na arquitetura... no método oncreate() da Activity, temos de povoar um bean Aluno com dados da tela:
Ainda, pensando na arquitetura A complexidade da Activity aumenta, à medida que novas funcionalidades vão sendo implementadas É uma boa prática de programação isolar pequenas responsabilidades em outras classes. Assim, a Activity passa a realizar o seu trabalho interagindo com pequenos especialistas Neste cenário, é possível implementar o padrão de projeto View Helper, que define a criação de classes especialistas em ext rair e tratar dados das telas
O Helper Atributos que representam os dados da tela Atributo que armazena a referência a um Aluno
O Helper (cont.) O construtor recebe um Método construtor que recebe um FormularioActivity FormularioActivity Criação do objeto Aluno Associa atributos do Helper a componentes da tela
O Helper (final) Retorna Aluno com dados vindos da tela Retorna referência para um objeto Aluno Seta os atributos do aluno nos campos da tela
Usando o Helper Agora que aclasse FormularioHelper está pronta, podemos utilizá-la na classe de controle FormularioActivity Para isso, é preciso: criar um atributo FormularioHelper criar um objeto Helper no método oncreate() utilizar os dados do Aluno em qualquer método que necessite desse objeto (reuso) Nessa App, vamos usar o click do botão para exibir o nome do aluno
Usando o Helper na View Definição do novo atributo FormularioHelper Inicialização do helper, passando uma referência para o objeto atual(this) Pedindo do Helper uma referência a Aluno Usando o novo objeto Aluno
Hora de persistir os dados O ViewHelper extrai os dados de Aluno da tela Vamos armazenar esses dados em um Banco de Dados relacional SQLite Para converter Objetos Java em Relações do banco de dados, vamos utilizar o padrão de projeto DAO DAO (Data Access Object) define que, para cada tabela do banco, criamos uma classe de persitência Ex: para a tabela Aluno, teremos uma classe AlunoDAO, responsável pelo CRUD do aluno
AlunoDAO Crie a classe para persistir dados do Aluno: Classe DAO para persistir dados de Aluno Filha da classe de persistência SQLiteOpenHelper
Usando o SQLite Controle de versão do BD
Criação da Tabela Em AlunoDAO, crie o método oncreate():
Atualização da Tabela Na classe AlunoDAO, crie o método onupdate():
AlunoDAO.cadastrar()
Atualização da FormularioActivity Agora que a camada de modelo está preparada para o cadastro do aluno, podemos atualizar nossa tela de formulário; No click do botão de Salvar, vamos: Pedir um objeto Aluno do Helper; Abrir uma conexão com BD, criando AlunoDAO; Cadastrar o novo Aluno no BD; e Fechar a conexão com o banco de dados
Botão Salvar
Para ver o que foi salvo... Para visualizar os dados do BD, precisamos atualizar as camadas de visão, controle e modelo Na camada de modelo, criar o método listar() Nas camadas de visão e controle: Remover o EditText e Button Na camada de controle, alterar o método oncreate() da ListaAlunosActivity para chamar o método listar() da camada de modelo e apagar os métodos: onsaveinstancestate() e onrestoreinstancestate()
AlunoDAO.listar() Início no método para recuperar um Alunos do BD:
AlunoDAO.listar() (final)
Criar método Aluno.toString()
Atualização da Tela inicial Alterar o arquivo: /res/layout/listaalunoslayout.xml Deixar apenas a ListView
Atualizar camada de controle No método oncreate() da ListaAlunosActivity, deixar apenas a associação da ListView
Mudança de tipos Nossa coleção de Alunos deve deixar de ser List<String> e se tornar List<Aluno> Alterar, também, o tipo do ArrayAdapter
Carga dos dados Na ListaAlunosActivity, criar o método carregarlista() para acesso ao DAO e carregar a coleção de Alunos
Carga no OnResume() Na classe ListaAlunosActivity, criar o método onresume() Nesse método, fazer a chamada a carregarlista()
Executando App
Completando o sistema Para completar o cadastro de alunos, falta implementar as rotinas de: Alterar; e Excluir Alunos Para alterar um registro, é comum o uso de um click curto, indicando sua seleção Na exclusão, é comum um click longo, que abre um pequeno menu, para selecionar uma ação
EXCLUSÃO DE CLIENTE
Menu de Contexto No Android, há o ContextMenu, que abre um menu exclusivo para um item da lista Para avisar ao Android que a ListView possui um menu de contexto, é preciso marcá-la: registerforcontextmenu() Criar um arquivo.xml para descrever os itens que devem ser exibidos no ContextMenu No método oncreatecontextmenu() da Activity, usar um Inflater para inflar as opções do menu: Opções: Ligar, Enviar SMS, Achar no Mapa, Navegar no site, Enviar E-mail e Deletar, etc...
Atualização das Strings Incluir novas chaves em /res/values/strings.xml
Criando o Menu de Contexto Na pasta /res/menu, criar um Android XML File Informe o nome do novo arquivo: menu_contexto
AlunoDAO.deletar()
Novo Atributo Na classe ListaAlunosActivity, incluir um atributo para marcar o aluno selecionado no Click Longo da ListView
Atualização do oncreate Atualize o método ListaAlunosActivity.onCreate(): Não consome o Click Curto, para que o ContextMenu seja exibido
Confirmação de exclusão
ContextMenu da Activity
Executando a App
Executando a App
Resultado...
EDITANDO DADOS DO ALUNO
Edição dos dados do aluno Criar a funcionalidade para alterar os dados de um aluno Ao acionar o click longo da ListView, a App exibe um menu de contexto, com possíveis ações para o Aluno No click curto, chamar a tela de formulário, carregada com os dados do aluno selecionado Como enviar o aluno selecionado na ListaAlunosActivity para FormularioActivity? Vamos usar Intents para enviar objetos Serializáveis de uma Activity para outra
Passo a passo Para realizar a edição de dados do Aluno, precisamos: Tornar o bean Aluno Serializável Implementar o método AlunoDAO.alterar(Aluno); Enviar um objeto Aluno da ListaAlunosActivity para FormularioActivity; Carregar o formulário com os dados do Aluno; e Verificar se é necessário cadastrar ou alterar os dados do Aluno;
Aluno Serializável
AlunoDAO.alterar() Valores que serão enviados para o BD Valores dos parâmetros da cláusula WHERE Atualização dos dados do Aluno
Transição de telas Na ListaAlunosActivity, atualize o click da ListView: Intenção de navegar de ListaAlunosActivity para FormularioActivity Recupera o aluno selecionado Inicia a tela de Formulário Compartilha o objeto Aluno com a nova tela
Atualizar formulário Adicione o método setaluno(aluno) em FormularioHelper
Dados na tela Atualize o método FormularioActivity.onCreate(): Recupera o objeto Aluno enviado pela ListaAlunosActivity
Alterar ou Cadastrar? Atualize o click do botão salvar da FormularioActivity
Execute a App
Permissões de Acesso Vez por outra, pode ser necessário que nossa App acesse recursos do próprio device, como: Câmera, Arquivos, Internet etc Para que o acesso seja autorizado, precisamos registrar esses interesses no AndroidManifest.xml Incluir a tag uses-permission e informar o valor para sua propriedade android:name Exemplo para solicitação de acesso à câmera: <uses-permission android:name="android.permission.camera"/>
Permissões de Acesso Inclua as solicitações de Acesso entre as tags: <uses-sdk /> e <application>
Permissões de Acesso Inclua as seguintes permissões no AndroidManifest.xml:
Intents implícitas Em nossa aplicação, precisamos realizar uma chamada telefônica para um aluno; O Android nos oferece duas estratégias para isso: acessar o telefone em baixo nível e controlar todo o ciclo de vida da chamada (pode não ser uma boa ideia) usar uma Intent que já sabe fazer ligações telefônicas: Intent.ACTION_CALL O Android oferece várias Activities prontas para acesso a funcionalidades do device
Ações do ContextMenu Altere o método oncontextitemselected da ListaAlunos:
Ações do ContextMenu Altere o método oncontextitemselected da ListaAlunos: Inclua opções para ver Aluno no Mapa e Navegar no site Padrão para Busca em mapa Item que Navega no site do Aluno
Ações do ContextMenu Altere o método oncontextitemselected da ListaAlunos: Última opção: Enviar e-mail para aluno.
Teste do envio de e-mail Click LONGO
Teste do envio de e-mail Selecione o item Enviar E-mail
Teste do envio de e-mail Escolha a Forma de Envio Escolha a Forma de Envio
Completando a App Para completar o cadastro do aluno, queremos usar a câmera para capturar sua foto; O arquivo.jpeg da foto ficará armazenado no device No SQLite, guardaremos apenas o caminho para o arquivo físico Na hora de carregar a foto, recupera-se o caminho armazenado no SQLite, acessa o device e faz-se a carga a imagem na tela.
Recordando... No Android, também existem as classes tradicionais de arquivos: FileInputStream e FileOutputStream; A Activity tem métodos para gerar esses objetos: FileInputStream stream = openfileinput("arquivo.txt"); E se você precisar trabalhar com memória externa? File diretorio = Enviroment.getExternalStorageDirectory() Devolve um diretório externo, provavelmente, um sdcard
Usando a Câmera O android nos oferece duas formas de manipular câmera, assim como ocorreu com a Chamada Telefônica usar e controlar todo o ciclo de vida e opções do uso da câmera, como, por exemplo, habilita flash e controlar a entrada de luz chamar uma Activity especialista no tratamento da câmera. Essa Activity recebe como parâmetro, o local para salvar a foto capturada. Parece que a 2 a alternativa é mais simples.
Carregar jpeg com a foto Converte um Crie o método FormularioHelper.carregarFoto() Arquivo em um Objeto JAVA Definição de uma Imagem reduzida Atualiza o atributo foto do Aluno Atualiza a imagem na Tela
Alterar o FormularioHelper para contemplar a foto
Chamando a câmera Para acessar a câmera, vamos seguir a estratégia de chamar uma Intent implícita, especialista em câmera: Intent irparacamera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); Podemos informar o local para salvar a foto: irparacamera.putextra(mediastore.extra_output, localfoto); E esperar o retorno, com nome do arquivo gerado. Para isso, informamos um código para a requisição (requestcode), comumente associado a uma constante: startactivityforresult(irparacamera, FAZER_FOTO);
Chamando a câmera (cont.) O retorno do método startactivityforresult() vem no callback method onactivityresult() @Override protected void onactivityresult( int requestcode, int resultcode, Intent data) { } O requestcode == FAZER_FOTO Já o resultcode pode ser: RESULT_OK: ocorreu tudo bem. :-) RESULT_CANCELED: em caso de problemas ou cancelamento :-(
Novas mudanças no formulário Na classe FormularioActivity, inclua novos atributos para lidar com a câmera:
Click da Imagem No método FormularioActivity.onCreate(), implemente o click da foto:
Click da Imagem No método FormularioActivity.onCreate(), implemente o click da foto: Local em que a Foto será armazenada Referência para o Local de armazenamento Intent Implícita para uso da câmera Chamando a Câmera
Click da Imagem No método FormularioActivity.onCreate(), implemente o click da foto: Inicia a Activity da Câmera. A resposta é lançada no método de Callback onactivityresult() Parâmetro: local de armazenamento Parâmetro: local de armazenamento Chamando a Câmera
Verificação do resultado Na ForumlarioActivity, crie o método onactivityresult(), para verificar o resultado retornado pela Intent da Câmera: Tratamento da resposta da Intent da câmera
Click na ImageView Testando... Capture a imagem Salve a imagem
Desafio... Quando cadastramos um aluno, o formulário está vazio; Se clicar na foto, a câmera é chamada; A foto é, então, salva no dispositivo; Assim, é exibida na tela de formulário; Porém, se girarmos a tela, o que acontece? Isso mesmo, a foto é perdida. Como Resolver esse problema, recorrente em Android Apps? Ideia fantástica: tente usar o Bundle.