Java 2 ME Interface Prof. Afonso Ferreira Miguel, MSc Java Micro Edition (J2ME) • Visão Geral: – Plataforma de desenvolvimento voltada para 2 tipos de dispositivos: • High-end consumer devices: – – – – – CDC (Connected Device Configuration) TV interativa, Videofones, dispositivos wireless,... Grande variedade de interfaces com usuário Memória a partir de 2 a 4 Mb. Conexão persistente e de banda larga, normalmente TCP/IP Java Micro Edition (J2ME) • Visão Geral: – Plataforma de desenvolvimento voltada para 2 tipos de dispositivos: • Low-end consumer devices: – – – – CLDC (Connected Limited Device Configuration) Telefones Celulares, pagers bi-direcionais, PDAs,... Memória a partir de 128 kb Conexão lenta, intermitente e normalmente não baseada em TCP/IP. – Utilizam baterias. Java Micro Edition (J2ME) • Objetivos (CLDC): – – – – Carga dinâmica de aplicações Desenvolvimento por terceiros Independência de padrões de rede Compatibilidade com outros padrões wireless Java Micro Edition (J2ME) • Dispositivos alvo (CLDC): – pelo menos 160kb de memória disponível para Java – Processador entre 8 e 32 MHz, 16 ou 32 bit – Alimentado por bateria – Conectividade limitada (9600 bps ou menos) – Produção em alta escala Java Micro Edition (J2ME) Profile(s) Configuration { Bibliotecas JVM Sistema Operacional Java Micro Edition (J2ME) • K Virtual Machine (KVM): – – – – Pequena: núcleo a partir de 60kb Altamente portável modular e customizável Desenvolvida para dispositivos a partir de 128kb de memória Java Micro Edition (J2ME) • MIDlets – Unidade básica de execução do MIDP – Derivada de javax.microedition.MIDlet – 3 métodos abstratos • startApp, pauseApp, destroyApp Java Micro Edition (J2ME) • startApp() – Invocado quando da inicialização e reinicialização do Midlet – Deve obter os recursos necessários para execução (timers, conexões de rede) – É invocado mais do que uma vez – Pode falhar de 2 maneiras: • transient: a falha é temporária (ex. falha de conexão). O MIDlet pode avisar ao sistema para reiniciá-lo mais tarde lançando uma MIDletStateChangeException • non-transient: Erro fatal. Pode ser tratado ou lançado para o sistema que irá invocar o método destroyApp Java Micro Edition (J2ME) • pauseApp() – Invocado toda a vez que o MIDlet é “colocado em pausa” – Quando receber a notificação, o MIDlet deve liberar tantos recursos quanto possível e permanecer em dormência. – Não é obrigatório, porém o sistema pode optar por terminar a execução de MIDlets que não atenderem a requisição. Java Micro Edition (J2ME) • destroyApp(boolean) – Invocado quando o MIDlet está para ser destruído. – O parâmetro indica se a destruição é incondicional. Caso negativo, o MIDlet pode requisitar uma “stay of execution” lançando uma exceção MIDletStateChangeException Java Micro Edition (J2ME) • Transição de Estados new HelloWorld() notifyPaused pauseApp Paused startApp Active resumeRequest destroyApp destroyApp notifyDestroyed notifyDestroyed Destroyed Métodos do MIDlet para forçar mudança de estado Java Micro Edition (J2ME) • Estrutura da UI – Cada MIDlet possui um Display, onde uma instância de Displayable é mostrada de cada vez – A aplicação seta o Displayable corrente de acordo com a evolução do sistema e as interações com o usuário – Dois tipos de Displayable • Canvas: baixo nível • Screen: alto-nível, encapsulamento de componentes de UI Java Micro Edition (J2ME) Alert Display Screen 0..1 Displayable Canvas List StringItem TextBox ImageItem Form TextField DateField 0..n Item Gauge ChoiceGroup Command Java Micro Edition (J2ME) Estrutura básica de um MIDlet 1ª aplicação... ... Hello World Passo 1: Criando projeto no J2ME Wireless Toolkit •Criar projeto com botão New Project... •Pressionar OK 1ª aplicação... ... Hello World Passo 2: Criando projeto no JCreator •Criar um Empty Project no diretório c:\Wtk104\apps\ com o mesmo nome do projeto criado no J2ME Wireless Toolkit (MeuTeste); •Criar um Java File chamado HelloWorld.java no diretório c:\Wtk104\apps\MeuTeste\src\ 1ª aplicação... ... Hello World import javax.microedition.midlet.MIDlet; import javax.microedition.lcdui.*; Passo 3: código Java public class HelloWorld extends MIDlet implements CommandListener { private Form form; •Entrar com o código a seguir: •Salvar public HelloWorld() { form = new Form("Isto é um teste"); form.append("Olá Mundo!"); form.addCommand( new Command( "Sair", Command.EXIT, 1 ) ); form.setCommandListener( this ); } public void startApp() { Display display = Display.getDisplay(this); display.setCurrent( form ); } public void pauseApp() { } public void destroyApp(boolean unconditional) { form = null; } public void commandAction(Command c, Displayable d) { destroyApp(true); notifyDestroyed(); } } 1ª aplicação... ... Hello World Passo 4: compilando e testando... •Voltar ao J2ME Wireless Toolkit compilar o projeto com o botão Build; •Selecionar o device a ser emulado (Motorola_i85s); •Executar através do botão Run; •Selecionar a aplicação e executá-la através do botão Launch. Java Micro Edition (J2ME) Display: é a interface de tela padrão. Para obtê-la, devemos evocá-la no construtor do MIDlet utilizando: Java Micro Edition (J2ME) TextBox: caixa de texto Displayable. Para ser exibida, deve ser: • Definida em uma referência; • Criada utilizando new e com os parâmetros adequados; • Exibida conectando-se ao display padrão (no método start). Java Micro Edition (J2ME) Exercício 1: Crie um novo projeto chamado Midlet1 criando também uma caixa de texto. Compile (corrigindo os erros) e: 1. Verifique o aspecto desta caixa de texto e as formas de digitação nos diferentes tipos de aparelhos (iDEN, PALM, etc.); 2. Substitua o parâmetro constraints e verifique o resultado na digitação. Java Micro Edition (J2ME) List: lista que exibe várias opções. Opções podem ser listadas no construtor ou utilizando o método append. A princípio, colocar null na lista de imagens. Java Micro Edition (J2ME) Exercício 2: modifique o projeto Midlet1 retirando o TextBox e adicionando o List. Compile (corrigindo os erros) e: 1. Verifique o aspecto da lista e as formas de seleção nos diferentes tipos de aparelhos (iDEN, PALM, etc.); 2. Teste as várias opções do parâmetro listType e verifique o resultado na seleção; 3. Modifique o código para utilizar o ouro construtor. Java Micro Edition (J2ME) List com Imagens: As imagens são carregadas a partir do diretório src do projeto. Para criar uma imagem utiliza o método estático Image.createImage(“..."); Java Micro Edition (J2ME) Exercício 3: modifique o projeto Midlet1 adicionando uma mesma imagem a cada opção da lista. Java Micro Edition (J2ME) Form: Formulário é um Displayable que permite a adição de diferentes tipos de controles (chamados de Item). Form StringItem ImageItem TextField DateField 0..n Item Gauge ChoiceGroup Java Micro Edition (J2ME) Form: o processo de criação de um Form é semelhante ao TextBox e List. Java Micro Edition (J2ME) Form: uma vez criado o formulario, podemos adicionar os controles TextField: campo de texto Java Micro Edition (J2ME) Exercício 4: modifique o projeto Midlet1 adicionando um formulário que solicite as informações Nome e Telefone. Testeo nos vários Handsets. Java Micro Edition (J2ME) Form: StringItem: string fixa. Java Micro Edition (J2ME) Exercício 6: modifique o formulário do item anterior adicionando o nome da empresa (“HAL INC”) no início. Java Micro Edition (J2ME) Form: ChoiceGroup: lista com itens permitindo seleção simples e múltipla. Os itens podem ser listados no construtor ou com o comando append. Java Micro Edition (J2ME) Exercício 7: modifique o formulário do item anterior adicionando a seleção do estado civil (Solteiro/Casado). Os itens do controle ChoiceGroup devem ser adicionados com o comando append. Java Micro Edition (J2ME) Form: DateField: seleção de Data e/ou Hora. Java Micro Edition (J2ME) Exercício 8: adicione o controle DateField no formulário anterior e verifique as opções DATE, DATE_TIME e TIME. Java Micro Edition (J2ME) Form: Gauge: barra de progresso com ou sem seleção. Java Micro Edition (J2ME) Exercício 9: retire alguns itens do formulário anterior (para facilitar a visualização) e adicione um Gauge. Teste as opções interactive. Java Micro Edition (J2ME) Form: ImageItem: imagem estática. Java Micro Edition (J2ME) Exercício 10: elimine todos os itens do formulário anterior (para facilitar a visualização) e um ImageField com uma figura e um StringField com o nome da imagem. Visualize em diferentes dispositivos. Java Micro Edition (J2ME) Command Command são controles adicionados ao handset como hotkeys ou menus. Java Micro Edition (J2ME) Command A adição do Command no projeto é feita em um objeto Displayable. Observe que o construtor possui 3 parâmetros. Java Micro Edition (J2ME) Exercício 11: modifique o MIDlet implementado adicionando 3 comandos com prioridades diferentes: “Sair”, “Novo”, “Excluir”. Localize cada um dos comandos nas telas apresentadas. Java Micro Edition (J2ME) Command Tratando eventos do Command: Para tratar os eventos dos botões, uma classe deve implementar a interface CommandListener. Java Micro Edition (J2ME) Command Esta interface obriga a classe a implementar o método commandAction que é evocado quando algum comando do Displayable é solicitado. Java Micro Edition (J2ME) Command A seguir, o Displayable precisa ser informado qual a classe que deverá receber os eventos. Para isto, é utilizado o método setCommandListener. Java Micro Edition (J2ME) Command Por fim, visto que vários botões podem solicitar eventos, é necessário que a função commandAction identifique o comando e execute o código necessário. Comandos necessários para encerrar o programa Java Micro Edition (J2ME) Exercício 12: modifique o MIDlet implementado adicionando a funcionalidade de “Sair”. Adicione também uma mensagem (System.out.println(“...”)) aos comandos “Novo” e “Excluir”. Teste nos Handset padrões e no PALM. Java Micro Edition (J2ME) Trocando a tela Para navegar entre Displayables as telas podem ser comutadas utilizando o comando setCurrent(). Java Micro Edition (J2ME) Exercício 13: modifique o MIDlet do exercício anterior adicionado um novo Displayable do tipo List. Neste último adicione um Command “Volta”. Adicione a funcionalidade necessária para que ao pressionar o botão “Novo”, o List seja exibido, e ao pressionar “Volta”, o formulário volte a ser exibido. Java Micro Edition (J2ME) List ou ChoiceGroup com múltiplas opções CAST Java Micro Edition (J2ME) Exercício 14: modifique o MIDlet do exercício anterior para exibir com o comando System.out.println os valores de estado dos itens do List (modificá-lo para MULTIPLE). Java Micro Edition (J2ME) Exercício 15: implementar um programa que exiba uma lista de nomes (1). Ao pressionar um botão “Novo” uma tela solicitará um novo nome (2). Ao entrar com um novo nome, a lista original será atualizada(3). Estando um nome selecionado, ao pressionar o botão “Excluir”, este nome deverá desaparecer da lista. (1) (2) (3) J2ME Display Gráfico Alert Display Screen 0..1 Displayable Canvas List StringItem TextBox ImageItem Form TextField DateField 0..n Item Gauge ChoiceGroup Command J2ME Classe Canvas Canvas é um Displayable do tipo abstract. Assim, não pode gerar uma instância direta. J2ME Classe Canvas Para criar um objeto do tipo Canvas, é necessário criar uma subclasse, e instanciá-la. Observe os métodos abstratos da classe Canvas. Java Micro Edition (J2ME) Exercício 16: implementar um MIDlet que exiba uma classe derivada da Canvas. Modifique o código do método paint para o mostrado abaixo e veja o resultado: J2ME Canvas Métodos chaves da classe Canvas: paint: método evocado sempre que a Canvas precisa ser “pintada” na tela. Obs.: este método nunca deve ser evocado diretamente pelo programa do usuário; repaint: método que pode ser evocado pelo programa do usuário solicitando que a tela seja “repintada”; getHeight: retorna ao programa do usuário a altura da tela em pixels; getWith: retorna ao programa do usuário a largura da tela em pixels; hasPointerEvents: retorna true se o dispositivo aceita entradas do ponteiro (caneta, mouse, etc...); hasPointerMotionEvents: retorna true se o dispositivo aceita entradas de movimento do ponteiro (drag); J2ME Graphics Um objeto da classe Graphics é utilizado como parâmetro do método paint. Este objeto é a representação do display gráfico. Para alterar o conteúdo da tela, devemos utilizar os métodos deste objeto: J2ME Graphics Métodos chaves da classe Graphics: setColor: define a cor da caneta para pintar neste objeto; drawLine: desenha uma linha simples; drawRectangle: desenha um retângulo vazado; drawRoundRect: desenha um retângulo vazado com cantos arredondados; drawArc: desenha um arco ou círculo vazado; fillRectangle: desenha um retângulo cheio; fillRoundRect: desenha um retângulo cheio com cantos arredondados; drawArc: desenha um arco ou círculo cheio; drawImage: pinta uma imagem no Canvas; J2ME Graphics Métodos para texto da classe Graphics: setFont: define a fonte para escrever textos; drawChar , drawChars: escreve um ou mais caracteres na tela. Obs.: verificar os parâmetros de âncora (anchor); drawString , drawSubstring: escreve uma string na tela. Obs.: verificar os parâmetros de âncora (anchor); J2ME Graphics “ Clip: área que poderá ser afetada pelos métodos de desenho. Desenhos fora desta área não aparecerão.” Métodos para clipping e mudança de referência da classe Graphics: setClip: define uma nova área para clipping; clipRect: redefine a área de clipping para a intersecção da área atual e um retângulo; translate: redefine uma posição de origem (0,0). Todos os métodos para desenho serão a partir desta nova origem. Java Micro Edition (J2ME) Exercício 17: implementar um MIDlet que exiba uma “cara sorridente” com olhos, nariz e boca, que ocupe a tela inteira, independente do dispositivo. Adicione também um Command para encerrar o MIDlet. J2ME Canvas Eventos: vários métodos relativos a eventos são definidos na classe Canvas: keyPressed: chamado quando uma tecla é pressionada; keyReleased: chamado quando uma tecla é solta; pointerPressed: chamado quando o ponteiro (mouse, caneta) é pressionado em uma posição da tela; pointerDragged: chamado quando o ponteiro (mouse, caneta) é arrastado. É chamado a cada nova posição; pointerReleaser: chamado quando o ponteiro (mouse, caneta) é solto; Java Micro Edition (J2ME) Exercício 18: implementar um MIDlet que exiba uma bola no local onde a tela do PALM for pressionada. Observe que este programa não funcionará com outros dispositivos sem tela sensível. J2ME Threads Assim como em C, Threads são muito fáceis de implementar e podem ser aplicadas em diversas áreas. Uma muito comum, é a animação. Para a construção de threads, temos duas opções: 1) Criar uma subclasse da classe Thread; 2) Adicionar a interface Runnable a uma classe já existente. J2ME Threads Criar uma Thread a partir de uma subclasse da classe Thread; Para disparar a subclasse como uma Thread, basta: J2ME Threads Criar uma Thread a partir de uma classe que implementa Runnable; Para disparar a subclasse como uma Thread, basta: J2ME Threads Observações com relação a Thread: • • A Thread será encerrada ao encerrar o método run(). Laços de repetição podem ser utilizados para que a Thread seja executada por um longo tempo; Para suspender a execução da Thread por algum tempo, utilize o método estático Thread.spleep(); Java Micro Edition (J2ME) Exercício 19: modificar a classe Canvas para que implemente Runnable. No método run(), implemente um laço repetitivo que imprima uma mensagem através do System.out.println. Faça este laço ser repetido a cada 1s (utilize Thread.sleep(1000) ). Java Micro Edition (J2ME) Exercício 20: modificar a classe do exercício 19 para que a bola se mova diagonalmente cada 10ms. Após visualizar a bola em movimento, modifique o código para a bola ficar rebatendo nas bordas. J2ME Threads Efeito de cintilação: • Aplicações que exigem animação geralmente executam o laço repetitivo: 1. Desenha; 2. Apaga; 3. Redesenha; 4. Apaga; 5. ... Porém, o tempo entre apagar e redesenhar muitas vezes provoca um cintilar (pisca-pisca) para o usuário, reduzindo o efeito de animação. Java Micro Edition (J2ME) Exercício 21: modificar o exemplo do exercício 20 para aparecer uma bola com 80 pixels de diâmetro. Observe que a bola algumas vezes parece não ser desenhada corretamente. J2ME Threads Duplo buffer: para minimizar os efeitos da cintilação, o processo de animação pode ser modificado para: 1. Desenha; 2. Sobrescreve; 3. Redesenha; 4. Sobrescreve; 5. ... Com isto, a tela nunca será apagada, evitando o efeito pisca-pisca. J2ME Threads buffer Image drawImage(...) Para evitar a cintilação, primeiramente devemos desenhar em uma imagem previamente criada, para depois sobrescrevê-la no display gráfico. Java Micro Edition (J2ME) Exercício 22: modificar o exemplo do exercício 21 para que o desenho seja realizado em um buffer (objeto) do tipo Image, sendo atualizado na tela posteriormente. Obs.: o apagamento agora deve ser feito no buffer. J2ME Teclas Os eventos de teclado são baseados em códigos de qualquer tecla e em códigos de teclas dedicadas para jogos. Para um Canvas tratar uma tecla, esta deve ser capturada pelos eventos: keyPressed: chamado quando uma tecla é pressionada; keyReleased: chamado quando uma tecla é solta. E pode ser tratada pelo evento: getGameAction: recupera o código de jogo de uma tecla. J2ME Teclas Exercício 23: modificar o exemplo do exercício 22 para que uma mensagem seja exibida pelo System.out.println. Utilize o método getGameAction em um case e mostre uma mensagem customizada. J2ME Teclas Exercício 24: diminua o tamanho da bola para 10 e adicione uma pequena raquete na parte inferior da tela que é movida pelo teclado. Adicione uma variável “estado” que é inicializada com 0; Adicione um botão (Command) que faça “estado”=1; Modifique o código para que permita a movimentação da bola apenas quando “estado”=1; Por fim, caso a bola não rebata na raquete, faça “estado”=0. J2ME Comunicação J2ME tem permite que dispositivos com suporte a rede possam tirar proveito disso. Desta forma, classes foram criadas para fazer acesso UDP, TCP inclusive HTTP, etc. O principal método para acesso é o Connector.open. Este método permite criar conexões para diferentes protocolos seguindo o padrão: J2ME Comunicação •Comunicação em Rede Datagrama: Para melhor controle dos dados recebidos, é conveniente que processos de recepção sejam colocados em uma Thread separada. Isto permite que o programa principal possa receber dados enquanto está sendo executado. Datagrama J2ME Comunicação J2ME Teclas Exercício 25: modifique o exercício 24 para que a cada rebatida, um datagrama seja enviado para sua máquina(IP 127.0.0.1). Utilize a classe Comm criada pelo professor. Experimente mudar o IP para enviar o datagrama ao colega. J2ME Comunicação • Comunicação em Rede – Protocolo HTTP – Utilizando uma requisição GET: HttpConnection c = (HttpConnection)Connector.open(“http://java.sun.com”); int status = c.getResponseCode(); if(status != HttpConnection.HTTP_OK){ ... } else { InputStream is = c.openInuptStream(); ... is.close(); } c.close(); J2ME Comunicação J2ME Comunicação Exemplo: HTTPTest J2ME Teclas Exercício 26: modifique o sistema de controle do exercício 15 para que acesse a página http://10.26.134.100/bd.asp) que controla um banco de dados de nomes) para que todos os nomes sejam lidos e atualizados remotamente. J2ME Teclas Avaliação: modificar o programa do exercício 24 para arquivar no banco de dados remoto (HTTP) o nome do jogador e o número de pontos. Java Micro Edition (J2ME) • Persistência (Record Management System - RMS) – Fornece records e Record Stores RecordStore Record 1 Record 17 Record 10 Record 2 – MIDP garante que um registro manterá seu recordId até que seja deletado. – Um recordId é gerado por um algoritmo de incremento unitário monotônico Java Micro Edition (J2ME) • Acessando RecordStores – Identificados por um nome de até 32 caracteres Unicode, únicos por MIDlet suite • • • • • • RecordStore.listRecordStores: lista os RecordStores da suite; RecordStore.open(String, boolean): abre (ou cria) um RecordStore RecordStore.close() RecordStore.delete(String): remove um RecordStore RecordStore.getNumRecords(): Número de registros no RS RecordStore.getVersion(): Versão do RS, incrementada a cada operação de inserção, alteração ou exclusão de registro • RecordStore.getLastModified: Hora da última modificação Java Micro Edition (J2ME) – Manipulando Registros • • • • • addRecord(byte[] data, int offset, int length) deleteRecord(int Id) getRecordSize(int Id) getRecord(int id) setRecord(int Id, byte[]data, int offset, int length) – Convertendo dados para array de bytes: • ByteArrayOutputStream • DataOutputStream Java Micro Edition (J2ME) – Filtrando Registros public interface RecordFilter { public boolean matches(byte[] candidate); } – Comparando Registros public interface RecordComparator { public int compare(byte[] b1, byte[] b2); public static final int EQUIVALENT; public static final int FOLLOWS; public static final int PRECEDES; }