cadastro de alunos - facom.ufu.brbacala/android/appalunos.pdf · começando pelo cadastro ......

134
App Alunos

Upload: ngokhuong

Post on 01-Dec-2018

216 views

Category:

Documents


0 download

TRANSCRIPT

App Alunos

•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 ;

Definições de Projeto

Funcionalidade da App

CADASTRO DE ALUNOS

• 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

Começando pelo Cadastro

• 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

Tela Inicial: Listagem dos alunos

Listaalunoslayout.xml

Campo de Texto

id=edNomeListagem

Listaalunoslayout.xml

Componente Botão

id=brAddListagem

Listaalunoslayout.xml

Componente Lista

para exibir alunos

id=lvListagem

• Observe:

Componentes EditText e Button estão visíveis

No entanto, a ListView não aparece

Isso ocorre porque nossa lista ainda está vazia

Tela Inicial: Listagem dos alunos

Texto nome do

aluno e o botão

estão visíveis

Lista alunos ainda

vazia

• 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

Controladores a as regras de negócio

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)

Associa componentes

da View a atributos da

Activity

Captura o click no

botão

Inicialização dos Atributos

Implementação anônima do

OnClickListener

• É 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.

Observações com relação ao ListView

ListView com Layouts diferentes

Novos atributos

Declaração dos novos

atributos

Converte listas e

vetores em View

Define o layout que o

Adapter usará

• 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

Passo a Passo

Inicialização da ListView

• 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

Passo a passo

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

• 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?

Conferindo o Resultado

• 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()

Evento de click no ListView

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;

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

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

onCreate(),

onSaveInstanceState() e

onRestoreInstanceState()

• Podemos utilizar o Map empacotado no Bundle para armazenar o estado da nossa App

Persistindo o estado da Activity

• 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

Passo a Passo

• Incluir novas constantes:

Salvar estado da Activity

• Incluir o novo método para salvar:

Salvar estado da Activity

• Após salvar, incluir o método para restaurar:

Restaurar estado da Activity

Agora quando giramos o dispositivo...

Depois do giro,

lista continua

preenchida

• Pelas mensagens de log, verificamos a lista de alunos sendo salva e recuperada do objeto Bundle

Resultado exibido no LogCat

MELHORANDO A APP

• 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.

Incrementando o cadastro

• 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

Tela de Cadastro de Alunos

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

Tela formulário

Seta formulário como página inicial

• Torne novamente a ListaAlunosActivity a tela inicial da nossa aplicação:

Antes de prosseguir...

Tela de listagem

• 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

Navegação entre telas

• Apesar da possibilidade de definição de Menus no código Java, é mais comum o uso de arquivos XML:

• O método Activity.onCreateOptionsMenu retorna true para indicar que o menu deve ser exibido na tela

Estratégia para definição de Menus

<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 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

Estratégia para definição de Menus

• Altere o nome da App no arquivo strings.xml

Menu principal

•Crie o arquivo XML: res/menu/menu_principal:

Menu principal

É comum que apenas

dois Itens do Menu

fiquem visíveis e os

demais, ocultos

Menu principal (cont...)

•Altere o método onCreateOptionsMenu(Menu menu) da classe ListaAlunosActivity:

Menu Principal

Executando a App...

• 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:

Eventos de click

Executando

•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)

Navegação entre telas da nossa App

•No método de clique da ListaAlunosActivity:

Abrir formulário

Fechar o Formulário

ARMAZENANDO DO DADOS EM BD

MVC em Android

Exibir tela

Entrada

de dados

modelo.getEstado()

modelo.atualizaEstado()

Notificação de

mudanças

Tela.atualizarVisao()

• 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

Persistência com SQLite

• Não se esqueça dos métodos get/set

Criar um bean Aluno

•no método onCreate() da Activity, temos de povoar um bean Aluno com dados da tela:

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

Ainda, pensando na arquitetura

O Helper

Atributos que representam os dados da tela

Atributo que armazena a referência a um Aluno

• Método construtor que recebe um FormularioActivity

O Helper (cont.) O construtor recebe um FormularioActivity

Associa atributos do Helper a componentes da tela

Criação do objeto Aluno

O Helper (final) Retorna Aluno com dados vindos da tela

Seta os atributos do aluno nos campos da tela

Retorna referência para um objeto Aluno

•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

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

• 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

Hora de persistir os dados

• Crie a classe para persistir dados do Aluno:

AlunoDAO

Classe DAO para persistir dados de Aluno

Filha da classe de

persistência

SQLiteOpenHelper

• Controle de versão do BD

Usando o SQLite

• Em AlunoDAO, crie o método onCreate():

Criação da Tabela

• Na classe AlunoDAO, crie o método onUpdate():

Atualização da Tabela

AlunoDAO.cadastrar()

• 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

Atualização da FormularioActivity

Botão Salvar

• 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()

Para ver o que foi salvo...

• Início no método para recuperar um Alunos do BD:

AlunoDAO.listar()

AlunoDAO.listar() (final)

Criar método Aluno.toString()

• Alterar o arquivo: /res/layout/listaalunoslayout.xml

• Deixar apenas a ListView

Atualização da Tela inicial

•No método onCreate() da ListaAlunosActivity, deixar apenas a associação da ListView

Atualizar camada de controle

•Nossa coleção de Alunos deve deixar de ser List<String> e se tornar List<Aluno>

•Alterar, também, o tipo do ArrayAdapter

Mudança de tipos

• Na ListaAlunosActivity, criar o método carregarLista() para acesso ao DAO e carregar a coleção de Alunos

Carga dos dados

• Na classe ListaAlunosActivity, criar o método onResume()

• Nesse método, fazer a chamada a carregarLista()

Carga no OnResume()

Executando App

•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

Completando o sistema

EXCLUSÃO DE CLIENTE

• 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...

Menu de Contexto

• Incluir novas chaves em /res/values/strings.xml

Atualização das Strings

• Na pasta /res/menu, criar um Android XML File

• Informe o nome do novo arquivo: menu_contexto

Criando o Menu de Contexto

AlunoDAO.deletar()

•Na classe ListaAlunosActivity, incluir um atributo para marcar o aluno selecionado no Click Longo da ListView

Novo Atributo

• Atualize o método ListaAlunosActivity.onCreate():

Atualização do 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

• 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

Edição dos dados do aluno

•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;

Passo a passo

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

• Na ListaAlunosActivity, atualize o click da ListView:

Transição de telas

Intenção de navegar

de ListaAlunosActivity

para FormularioActivity

Recupera o

aluno

selecionado

Compartilha o objeto

Aluno com a nova tela Inicia a tela de

Formulário

• Adicione o método setAluno(Aluno) em FormularioHelper

Atualizar formulário

• Atualize o método FormularioActivity.onCreate():

Dados na tela

Recupera o objeto

Aluno enviado pela

ListaAlunosActivity

• Atualize o click do botão salvar da FormularioActivity

Alterar ou Cadastrar?

Execute a App

• 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:

Permissões de Acesso

• 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

Intents implícitas

• 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●

Ações do ContextMenu

Padrão para

Busca em mapa

Item que Navega

no site do Aluno

• Altere o método onContextItemSelected da ListaAlunos:

• Última opção: Enviar e-mail para aluno.

Ações do ContextMenu

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

•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.

Completando a App

• 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

Recordando...

•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 2a alternativa é mais simples.

Usando a Câmera

• Crie o método FormularioHelper.carregarFoto()

Carregar jpeg com a foto

Converte um

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

• 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

• 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 :-(

Chamando a câmera (cont.)

• Na classe FormularioActivity, inclua novos atributos para lidar com a câmera:

Novas mudanças no formulário

• No método FormularioActivity.onCreate(), implemente o click da foto:

Click da Imagem

• No método FormularioActivity.onCreate(), implemente o click da foto:

Click da Imagem

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

• No método FormularioActivity.onCreate(), implemente o click da foto:

Click da Imagem

Chamando a

Câmera

Parâmetro: local de

armazenamento

Inicia a Activity da

Câmera. A resposta é

lançada no método de

Callback

onActivityResult()

Parâmetro: local de

armazenamento

• Na ForumlarioActivity, crie o método onActivityResult(), para verificar o resultado retornado pela Intent da Câmera:

Verificação do resultado

Tratamento

da resposta

da Intent da

câmera

Testando... Click na

ImageView

Capture a

imagem

Salve a

imagem

• 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.

Desafio...