Micro Edition Marco Antonio – Julho/2009. CLDC Connected Limited Device Configuration Parte...
Transcript of Micro Edition Marco Antonio – Julho/2009. CLDC Connected Limited Device Configuration Parte...
Micro EditionMarco Antonio – Julho/2009
CLDC• Connected Limited Device Configuration• Parte fundamental da arquitetura J2ME• Requisitos:
– Pode ser utilizada em dispositivos de 16 e 32 bits com clock mínimo de 16MHz
– 160 KB de memória não volátil para as bibliotecas CLDC e máquina virtual
– 192 KB de memória total para a instalação do Java
• Conectividade com alguns tipos de rede, geralmente wireless, mesmo intermitente e com limitação de banda.
MIDP• Mobile Information Device Profile• Perfil padrão para dispositivos móveis de
processamento limitado.• Trabalha em conjunto com a CLDC.
Estrutura JME• A mobile edition é uma versão
simplificada da JVM.• Tem a maioria das classes,
praticamente a mesma funcionalidade.
• Existem bibliotecas de terceiros específicas (ex. OpenGL ES, M3G, Midia, etc).
Plataforma Java
Instalação• WTK
– Wireless Toolkit, atualmente na versão 3.0
– http://java.sun.com/javame
• Eclipse– Versão atual: Galileo– http://www.eclipse.org
• EclipseME– Versão atual: 1.7.9– http://www.eclipseme.org
Install EclipseME• Help → Install New Software.
Adicione o link• Esta é a maneira de instalar plugins no
novo Eclipse.
Plugin do EclipseME• Dados do plugin.
EclipseME Configuration• Informe o diretório raíz do wtk.• No windows é WTK2.5.2_01.
Device Configuration• Clique no botão Import.
Devices• Indique o diretório raíz do wtk e depois
Refresh.
Projeto de Exemplo
• Selecione o tipo de projeto correspondente.
DiagnosticoMedicoME
• Informe o nome do projeto.
Dispositivos Suportados
• Utilize o perfil mais genérico possível para ampliar o número de aparelhos suportados pela aplicação, a menos, claro, que esteja desenvolvendo para um modelo específico.
Diretórios
• Os diretórios src (fontes) e res (recursos) serão criados.
Formulário
• As classes de apresentação devem ser Midlets.
FormularioCadastroDePacientepackage com.diagnostico.apresentacao;
import java.io.*;import java.util.*;
import javax.microedition.lcdui.*;import javax.microedition.midlet.*;
public class FormularioCadastroDePaciente extends MIDlet { //Componentes Gauge gauge; Spacer espacador; ImageItem foto; TextField txtNome; DateField txtDataDeNascimento; StringItem lblIdentificador; ChoiceGroup chcAgrupador; //Tela Display display;
FormularioCadastroDePaciente protected void destroyApp(boolean flag) {
notifyDestroyed();
}
protected void pauseApp() {
}
protected void startApp() throws MIDletStateChangeException {
display = Display.getDisplay(this);
display.setCurrent(getFormCadastro());
}
FormularioCadastroDePaciente private Form getFormCadastro() {
//Formulario
Form formCadastro = new Form("Dados do Paciente");
lblIdentificador = new StringItem("Identificador:", "00001");
formCadastro.append(lblIdentificador);
//
txtNome = new TextField("Nome:", null, 25, TextField.ANY);
formCadastro.append(txtNome);
//
txtDataDeNascimento = new DateField("Nascimento:", DateField.DATE);
formCadastro.append(txtDataDeNascimento);
//
gauge = new Gauge("Passo 1", true, 4, 1);
formCadastro.append(gauge);
//
espacador = new Spacer(30, 10);
formCadastro.append(espacador);
//
String[] valores = {"Diego", "Mariana"};
chcAgrupador = new ChoiceGroup("Filhos", Choice.MULTIPLE, valores, null);
formCadastro.append(chcAgrupador);
//Imagem
try {
Image imagem = Image.createImage("/Diego.jpg");
foto = new ImageItem("Foto:", imagem, ImageItem.LAYOUT_CENTER, "foto");
formCadastro.append(foto);
} catch (IOException e) {
e.printStackTrace();
}
//Comandos
Command menuSalvar = new Command("Salvar", Command.OK, 1);
Command menuFechar = new Command("Sair", Command.EXIT, 1);
//
formCadastro.addCommand(menuSalvar);
formCadastro.addCommand(menuFechar);
formCadastro.setCommandListener(this);
return formCadastro;
}
}
Listener• Faça o midlet implementar CommandListener.
{...}
public class FormularioCadastroDePaciente extends MIDlet implements
CommandListener {
{…}
• Em seguida será necessário implementar o seguinte método:
public void commandAction(Command comando, Displayable tela) {}
• Por fim, adicione o próximo formulário.
FormSucesso private Form getFormSucesso() {
//Calendario
Calendar calendario = Calendar.getInstance();
calendario.setTime(txtDataDeNascimento.getDate());
int dia = calendario.get(Calendar.DAY_OF_MONTH);
int mes = calendario.get(Calendar.MONTH);
int ano = calendario.get(Calendar.YEAR);
//Formulario
Form formSucesso = new Form("Informação");
formSucesso.append("Dados Gravados com Sucesso.");
StringItem nome = new StringItem("Nome:", txtNome.getString());
StringItem data = new StringItem("Nascimento:", dia + "/" + mes + "/" + ano);
formSucesso.append(nome);
formSucesso.append(data);
//Comandos
formSucesso.addCommand(new Command("Voltar", Command.BACK, 0));
formSucesso.setCommandListener(this);
//
return formSucesso;
}
commandAction• Atualize o método de comando.
public void commandAction(Command comando, Displayable tela) {
if (comando.getLabel().equals("Salvar")) {
display.setCurrent(getFormSucesso());
} else if (comando.getLabel().equals("Sair")) {
destroyApp(true);
} else if (comando.getLabel().equals("Voltar")) {
display.setCurrent(getFormCadastro());
}
}
Menu Principal• A seguir uma possível solução para o
menu principal da aplicação.
DiagosticoMedicopackage com.diagnostico.apresentacao;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
public class DiagnosticoMedico extends MIDlet implements CommandListener {
private Display display;
protected void destroyApp(boolean flag) throws MIDletStateChangeException {
notifyDestroyed();
}
protected void pauseApp() {
}
protected void startApp() throws MIDletStateChangeException {
display = Display.getDisplay(this);
display.setCurrent(getMenu());
}
DiagosticoMedico private List getMenu() {
List menu = new List("Diagnóstico Médico", List.IMPLICIT);
menu.append("Paciente", null);
menu.append("Consulta", null);
menu.append("Exame", null);
menu.append("Histórico", null);
menu.addCommand(new Command("Selecionar", Command.ITEM, 0));
menu.setCommandListener(this);
return menu;
}
DiagosticoMedico public void commandAction(Command comando, Displayable conteudo) {
List menu = (List) conteudo;
String opcao = menu.getString(menu.getSelectedIndex());
String mensagem = "";
if (opcao.equals("Paciente")) {
mensagem = "Voce selecionou 'Paciente'";
} else if (opcao.equals("Consulta")) {
}
Alert alerta = new Alert(mensagem);
alerta.setTimeout(5000);
display.setCurrent(alerta);
}
Otimização do Código• Separe os formulários para uma melhor
manutenção.• Assim, teremos melhor controle sobre a
evolução da aplicação.
FormPacientepackage com.diagnostico.apresentacao;
import javax.microedition.lcdui.*;
public class FormPaciente extends Form {
public TextField txtNome = new TextField("Nome:", "", 30, TextField.ANY);
public DateField txtNascimento = new DateField("Nascimento:", DateField.DATE);
public FormPaciente(CommandListener listener) {
super("Paciente");
append(txtNome);
append(txtNascimento);
append(new Spacer(30, 30));
addCommand(new Command("Gravar", Command.OK, 0));
addCommand(new Command("Cancelar", Command.CANCEL, 1));
setCommandListener(listener);
}
}
RMS• A solução fornecido pelo JME para
persistência é o Record Management System.
• Trabalha com arrays de bytes, exigindo conversões para recuperar as informações.
CalendarioUtilpackage com.diagnostico.util;
import java.util.*;
public class CalendarioUtil {
public static String getDataInvertida(Date data) {
Calendar calendario = Calendar.getInstance();
calendario.setTime(data);
int dia = calendario.get(Calendar.DAY_OF_MONTH);
int mes = calendario.get(Calendar.MONTH);
int ano = calendario.get(Calendar.YEAR);
return ano + "-" + mes + "-" + dia;
}
public static Date getData(String nascimento) {
//TODO Terminar
Calendar calendario = Calendar.getInstance();
calendario.set(Calendar.DAY_OF_MONTH, 1);
calendario.set(Calendar.MONTH, 1);
calendario.set(Calendar.YEAR, 2001);
return calendario.getTime();
}
}
DAOPacientepackage com.diagnostico.persistencia;
import java.io.*;import java.util.*;
import javax.microedition.rms.*;
import com.diagnostico.apresentacao.*;import com.diagnostico.util.*;
public class DAOPaciente { public static String NOME_DA_RECORDSTORE = "RSPaciente";
public int inserir(FormPaciente form) { try { // ByteArrayOutputStream out = new ByteArrayOutputStream(); DataOutputStream dados = new DataOutputStream(out); // String nome = form.txtNome.getString(); Date nascimento = form.txtNascimento.getDate(); dados.writeUTF(nome); dados.writeUTF(CalendarioUtil.getDataInvertida(nascimento)); // RecordStore rs = RecordStore.openRecordStore(NOME_DA_RECORDSTORE, true); byte[] bytes = out.toByteArray(); int id = rs.addRecord(bytes, 0, bytes.length); // out.close(); dados.close(); rs.closeRecordStore(); return id; } catch (Exception e) { e.printStackTrace(); } return 0; }}
commandAction public void commandAction(Command comando, Displayable conteudo) {
if (conteudo instanceof List) {
//Menu Principal
List menu = (List) conteudo;
String opcao = menu.getString(menu.getSelectedIndex());
//Opcoes do menu
if (opcao.equals("Paciente")) {
display.setCurrent(new FormPaciente(this));
} else if (opcao.equals("Consulta")) {
//
} else if (opcao.equals("ListarPacientes")) {
//
FormListarPacientes form = new FormListarPacientes(this);
display.setCurrent(form);
}
} else if (conteudo instanceof FormPaciente) {
//FormPaciente
if (comando.getLabel().equals("Gravar")) {
FormPaciente form = (FormPaciente) conteudo;
DAOPaciente dao = new DAOPaciente();
int id = dao.inserir(form);
System.out.println("Id Gravado:" + id);
} else if (comando.getLabel().equals("Cancelar")) {
display.setCurrent(getMenu());
}
}
Dica• Separar os comandos em classes
específicas para facilitar a leitura e manutenção do código.
Dica• Criar VO's e utilizá-los como parâmetro,
ao invés de acessar os componentes diretamente.
Consulta• Atenção especial para as conversões
de dados. • Tudo deve ser tratado como byte[],
para isso temos as classes específicas.
DAOPaciente public Vector consultaRegistros() {
try {
RecordStore rs = RecordStore.openRecordStore(DAOPaciente.NOME_DA_RECORDSTORE, false);
RecordEnumeration registros = rs.enumerateRecords(null, null, false);
Vector objetos = new Vector();
while (registros.hasNextElement()) {
int id = registros.nextRecordId();
byte[] dados = rs.getRecord(id);
ByteArrayInputStream input = new ByteArrayInputStream(dados);
DataInputStream dataInput = new DataInputStream(input);
StringBuffer s = new StringBuffer();
s.append(id + "-");
s.append(dataInput.readUTF() + "-");
s.append(dataInput.readUTF());
objetos.addElement(s.toString());
}
return objetos;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
FormListarPacientespackage com.diagnostico.apresentacao;
import java.util.*;
import javax.microedition.lcdui.*;
import com.diagnostico.persistencia.*;
public class FormListarPacientes extends Form { // public FormListarPacientes(CommandListener listener) { super("Listar Pacientes"); carregaListaDePacientes(); setCommandListener(listener); addCommand(new Command("Editar", Command.OK, 1)); addCommand(new Command("Voltar", Command.CANCEL, 1)); }
private void carregaListaDePacientes() { try { DAOPaciente dao = new DAOPaciente(); Vector v = dao.consultaRegistros(); String[] valores = new String[v.size()]; v.copyInto(valores); ChoiceGroup pacientes = new ChoiceGroup("Pacientes", Choice.EXCLUSIVE, valores, null); append(pacientes); } catch (Exception e) { e.printStackTrace(); append(new StringItem("Erro:", "Listar Pacientes")); } }}
Atividade• Criar os métodos atualizar e
consultarPeloId.• Dica: pesquise por
RecordStore.setRecord e RecordStore.getRecord.
• Em seguida temos uma possível solução.
DAOPaciente public DataInputStream consultaPeloId(int id) {
try {
RecordStore rs = RecordStore.openRecordStore(NOME_DA_RECORDSTORE, true);
byte[] bytes = rs.getRecord(id);
ByteArrayInputStream in = new ByteArrayInputStream(bytes);
DataInputStream dados = new DataInputStream(in);
return dados;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
DiagnosticoMedico } else if (conteudo instanceof FormListarPacientes) {
//FormListarPacientes
if (comando.getLabel().equals("Voltar")) {
display.setCurrent(getMenu());
} else if (comando.getLabel().equals("Editar")) {
//
FormListarPacientes origem = (FormListarPacientes) conteudo;
int indice = origem.pacientes.getSelectedIndex();
String valor = origem.pacientes.getString(indice);
StringTokenizer token = new StringTokenizer(valor, "-");
int id = Integer.parseInt(token.nextToken());
//
FormPaciente destino = new FormPaciente(this);
destino.setId(id);
destino.carregarDados();
//
display.setCurrent(destino);
}
}
FormPaciente public void carregarDados() {
try {
DAOPaciente dao = new DAOPaciente();
DataInputStream dados = dao.consultaPeloId(getId());
txtNome.setString(dados.readUTF());
Date data = CalendarioUtil.getData(dados.readUTF());
txtNascimento.setDate(data);
} catch (IOException e) {
e.printStackTrace();
}
}
RecordComparator• Interface usada para comparar dois
registros. • Os possíveis resultados são:
– EQUIVALENT– FOLLOWS– PRECEDES
RecordComparatorpackage com.diagnostico.persistencia;
import java.io.*;
import javax.microedition.rms.*;
public class PacienteComparator implements RecordComparator { public int compare(byte[] registroAnterior, byte[] proximoRegistro) { try { ByteArrayInputStream inputAnterior = new ByteArrayInputStream(registroAnterior); DataInputStream dataInputAnterior = new DataInputStream(inputAnterior); String anterior = dataInputAnterior.readUTF().toLowerCase(); // ByteArrayInputStream proximoInput = new ByteArrayInputStream(proximoRegistro); DataInputStream proximoDataInput = new DataInputStream(proximoInput); String proximo = proximoDataInput.readUTF().toLowerCase(); // int resultado = anterior.compareTo(proximo); if (resultado < 0) { return PRECEDES; } else if (resultado > 0) { return FOLLOWS; } } catch (IOException e) { e.printStackTrace(); } return EQUIVALENT; }}
RecordFilter• Interface utilizada para filtrar o
resultado de uma consulta.• Retorna somente os registros que
aceitem a condição do método matches().
PacienteFiltropackage com.diagnostico.persistencia;import java.io.*;import javax.microedition.rms.*;public class PacienteFiltro implements RecordFilter { private String nomeFiltrado;
public PacienteFiltro(String nomeFiltrado) { this.nomeFiltrado = nomeFiltrado; }
public boolean matches(byte[] candidato) { try { // ByteArrayInputStream input = new ByteArrayInputStream(candidato); DataInputStream dataInput = new DataInputStream(input); String nomeLido = dataInput.readUTF(); // int resultado = nomeLido.indexOf(nomeFiltrado); if (resultado >= 0) { return true; } } catch (IOException e) { e.printStackTrace(); } return false; }}
Juntando tudo...• Utilizando todos os recursos no
DAOPaciente temos um módulo completo para consulta.
• Dica: vários blocos de código estão repetidos. É um bom momento de criar classes utilitárias para evitar esse problema.
DAOPaciente• Atualize o código da consulta conforme
o exemplo.
public Vector consultaRegistros() {
try {
//
RecordStore rs = RecordStore.openRecordStore(DAOPaciente.NOME_DA_RECORDSTORE, false);
//
PacienteComparator comparador = new PacienteComparator();
RecordEnumeration registros = rs.enumerateRecords(null, comparador, false);
Vector objetos = new Vector();
while (registros.hasNextElement()) {
{…}
DAOPaciente public Vector consultaPeloNome(String nomeFiltrado) {
try {
//
RecordStore rs = RecordStore.openRecordStore(DAOPaciente.NOME_DA_RECORDSTORE, false);
//
PacienteComparator comparador = new PacienteComparator();
//
PacienteFiltro filtro = new PacienteFiltro(nomeFiltrado);
RecordEnumeration registros = rs.enumerateRecords(filtro, comparador, false);
//
Vector objetos = new Vector();
while (registros.hasNextElement()) {
int id = registros.nextRecordId();
byte[] dados = rs.getRecord(id);
ByteArrayInputStream input = new ByteArrayInputStream(dados);
DataInputStream dataInput = new DataInputStream(input);
StringBuffer s = new StringBuffer();
s.append(id + "-");
s.append(dataInput.readUTF() + "-");
s.append(dataInput.readUTF());
objetos.addElement(s.toString());
}
return objetos;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
Atividade• Pesquisar e implementar uma classe
que faça monitoração (RecordListener) do DAOPaciente.
• Imprima os dados de cada operação.