Desenvolvendo uma aplicação J2ME

 

Olá pessoal, vamos dar continuidade neste artigo, à nossa série sobre desenvolvimento para dispositivos móveis. No último artigo, aprendemos como configurar um ambiente de desenvolvimento completo para dispositivos móveis baseado em J2ME (utilizando o NetBeans). Este artigo tem como objetivo desenvolver uma pequena aplicação em J2ME que irá apresentar alguns objetos de interface gráfica e responder a comandos acionados pelo usuário. Ao longo dos próximos artigos, iremos cobrir todos (ou quase todos) os objetos da interface gráfica e implementaremos novas e interessantes funcionalidades em nossas aplicações.

 

Bem, antes de começarmos com a escrita do código propriamente dita, é importante definir alguns conceitos e entender o ciclo de vida das aplicações mobile. Uma aplicação móvel, escrita em Java, é chamada de Midlet (MID vem de Mobile Information Device, ou seja, Dispositivos de Informação Móveis). A classe principal de cada aplicação móvel (a classe “executável”, por assim dizer), portanto, deve estender a classe abstrata MIDlet, pois é esta classe que oferece os principais métodos para controlar o ciclo de vida das aplicações. Aplicações móveis não possuem método o main() para rodar, mas sim o método startApp(), definido na classe abstrata MIDlet.

 

As aplicações móveis possuem três estados (iniciado, pausado e destruído) que representam o ciclo de vida das aplicações móveis, e representam, respectivamente, os momentos em que as aplicações começam a rodar (startApp()), entram no estado de pausa (pauseApp()) ou são finalizadas (destroyApp()). As aplicações entram no estado de pausa quando, durante a execução das aplicações, o dispositivo móvel recebe um “chamado” de algum evento com maior prioridade do que a aplicação em execução, como, por exemplo, o recebimento de uma chamada telefônica. Além disso, uma aplicação pode entrar no estado de pausa a pedido do usuário. Já o estado “destruído” é acionado quando a aplicação é finalizada, fato que pode ocorrer à pedido do usuário que está executando a aplicação ou quando ocorre algum erro desconhecido ou não tratado pelo programador e que implica na finalização abrupta da aplicação.

 

Em resumo: a classe abstrata MIDlet define todos os métodos necessários para gerenciar o ciclo de vida das aplicações móveis, e toda aplicação deve ter uma (e somente uma) classe que estende de MIDlet e que deve, portanto, implementar os três principais métodos dessa classe: startApp(), pauseApp() e destroyApp(). A partir de agora, irei me referir às aplicações móveis como Midlets, para ajudar aos leitores na fixação desse termo.

 

Iremos agora desenvolver a aplicação que mencionei no início deste artigo. Para isto, será necessário criar uma nova aplicação no NetBeans (ou em outra IDE qualquer de sua preferência e que ofereça suporte ao desenvolvimento de Midlets). Para os leitores que não possuem um ambiente de desenvolvimento em J2ME configurado e pronto para criação de Midlets, sugiro a leitura do meu artigo anterior, onde explano, em detalhes, sobre a configuração de uma ambiente completo para desenvolvimento de soluções móveis baseado no NetBeans (o link para este artigo pode ser encontrado no final desta página).

 

A aplicação, chamada de PrimeiraMidlet, irá utilizar dois componentes da interface gráfica de alto nível (mais detalhes sobre os componentes de interface com o usuário no próximo artigo) e três comandos, os quais funcionam como botões em outras plataformas de desenvolvimento, ou seja, permitem com que o usuário execute alguma ação que está associada com cada um dos comandos oferecidos a ele pela aplicação. Ao criar o projeto para a aplicação em sua IDE, batize-o de PrimeiraMidlet (e, no caso específico do NetBeans, lembre-se de desmarcar a opção “Create Hello Midlet” durante a criação do projeto para a aplicação). Uma vez criado o projeto, crie, dentro do mesmo, uma Midlet e batize-a de PrimeiraMidlet. Para criar a Midlet dentro do projeto, através do NetBeans, basta clicar com o botão direito sobre o projeto e selecionar a opção “New” e depois “MIDlet”. Vale ressaltar que o nome do projeto e o nome da Midlet não precisam ser o mesmo; demos o mesmo nome ao projeto e à classe da aplicação apenas por simplificação.

 

Independentemente da IDE utilizada, o esqueleto básico da nossa classe Java da aplicação (a Midlet) é representado abaixo. Observe que a classe PrimeiraMidlet estende de MIDlet e, por isso, tem que implementar os três métodos já discutidos neste artigo. As duas primeiras linhas do artigo representam as importações necessárias para o funcionamento da Midlet; o pacote “midlet” contém a classe MIDlet que utilizamos em nossa aplicação, e o pacote “lcdui” contém as classes que definem a interface gráfica com o usuário. A Midlet apresentada abaixo não presenta nehuma funcionalidade (já que ainda não dissemos a ela o que fazer), mas já compila e executa perfeitamente. O próximo passo, portanto, é implementar algum funcionalidade à nossa Midlet.

 

import javax.microedition.midlet.*;

import javax.microedition.lcdui.*;

 

public class PrimeiraMidlet extends MIDlet {

 

    public PrimeiraMidLet() {

    }

 

    public void startApp() {

    }

   

    public void pauseApp() {

    }

   

    public void destroyApp(boolean unconditional) {

    }

 

}

 

Em primeiro lugar, vamos criar dois objetos de interface gráfica: um Alert e um TextBox. O primeiro componente serve para exibir informações na tela do dispositivo; já o segundo, representa uma caixa de texto onde o usuário pode escrever.

 

Estes dois componentes são criados com as seguintes linhas de comando:

 

private Alert alerta = new Alert("Primeira Midlet - Tela principal", "Nenhuma 

                               informacao foi digitada!", null, AlertType.INFO);

private TextBox textBox = new TextBox("Primeira Midlet - Digite o texto", "",

                                      200, TextField.ANY);

 

Os parâmetros passados para a criação do objeto Alert representam, respectivamente: o título do objeto, o conteúdo do objeto, a imagem (neste caso, não estamos exibindo nenhuma imagem), e o tipo de alerta (que pode ser INFO, ERROR, WARNING, ALARM, CONFIRMATION).

 

Já os parâmetros informados para a criação do objeto TextBox representam, respectivamente: o título do objeto, o conteúdo do objeto (estamos passando uma String vazia neste parâmetro), a quantidade máxima de caracteres que podem ser digitados e o tipo de entrada permitida (neste caso, estamos informando que qualquer entrada fornecida pelo usuário é válida).

 

Para podermos exibir os nossos componentes de interface na tela do dispositivo, temos que obter o Display que está associado à tela física do dispositivo. Este procedimento é feito com da seguinte maneira:

 

Declaração de um objeto do tipo Display:

Display display;

           

Associação do nosso display com a tela do dispositivo:

                        display = Display.getDisplay(this);

 

E, por fim, a exibição de um objeto da interface gráfica no display:

                        display.setCurrent();

 

Geralmente, estes dois últimos comandos são os primeiros a serem declarados dentro do método “startApp()”, haja vista que é neste momento (no início da execução da aplicação) que devemos obter a referência para o display do dispositivo e pedirmos para exibir o primeiro componente da interface gráfico.

 

Além disso, iremos criar três componentes do tipo Command, e associaremos ações a cada um deles. O primeiro comando será utilizado para encerrar a plicação quando o usuário assim solicitar, o segundo comando será utilizado realizar a troca entre os objetos da interface que são exibidos (do Alert para o objeto TextBox); por fim, o último comando fará com que o texto digitado no TextBox seja enviado para o Alert para que seja exibido na tela. Para criar os Commands, podemos utilizar as seguintes declarações:

  

private Command sair = new Command("Sair", Command.EXIT, 0);

private Command digitarTexto = new Command("Digitar Texto", Command.OK,

                                           1);

private Command confirmar = new Command("Confirmar", Command.OK, 1);

 

Os parâmetros informados para a criação dos Commands são (respectivamente): título do comando, o tipo do comando (que pode ser OK, BACK, CANCEL, EXIT, HELP, ITEM, SCREEN ou STOP) e a prioridade do comando, a qual indica a ordem com que cada comando irá ser exibido na tela.

 

Uma vez criados, os comandos devem ser associados aos itens da interface gráfica nos quais serão apresentados ao usuário. Para isso, utilizamos as seguintes instruções no construtor da nossa classe:

 

alerta.addCommand(sair);

alerta.addCommand(digitarTexto);

textBox.addCommand(confirmar);

 

Para podermos monitorar e processar os comandos, assim que eles forem acionados pelo usuário, é necessário que a nossa classe implemente a interface CommandListener, e implemente o método “commandAction(Command c, Displayable d)”. Além disso, os objetos da interface gráfica que possuem comandos associados (no nosso caso, os objetos “textBox” e “alerta”) devem se registrar no “escutador de eventos”, para que possam ser monitorados por ele (a nossa própria classe é o “escutador de eventos” da aplicação, uma vez que estendeu a interface “CommandListener”). Para isso, adicionamos as seguintes linhas de código ao construtor da classe:

 

alerta.setCommandListener(this);

textBox.setCommandListener(this);

 

Não iremos implementar, para esta aplicação, o código para o método “pauseApp()”, uma vez que a aplicação não exige a necessidade de realizar nenhum processamento quando a aplicação entra no estado de pausa. Já no método “destroyApp(boolean unconditional)”, iremos inserir a seguinte linha de código:

 

notifyDestroyed();

 

Este método simplesmente avisa ao gerenciador de aplicações do dispositivo móvel que a nossa aplicação está sendo encerrada, e que o dispositivo pode retirá-lo da memória.

 

Neste momento, a implementação de nossa classe deverá estar parecida com o código apresentado abaixo.

 

import javax.microedition.midlet.*;

import javax.microedition.lcdui.*;

 

public class PrimeiraMidlet extends MIDlet implements CommandListener {

   

    private Alert alerta = new Alert("Primeira Midlet - Tela principal",

                "Nenhuma informacao foi digitada!", null, AlertType.INFO);

    private TextBox textBox = new TextBox("Primeira Midlet - Digite o texto",

                "", 200, TextField.ANY);

    private Command sair = new Command("Sair", Command.EXIT, 0);

    private Command digitarTexto = new Command("Digitar Texto", Command.OK, 1);

    private Command confirmar = new Command("Confirmar", Command.OK, 1);

    private Display display;

   

    public PrimeiraMidlet() {

        alerta.addCommand(sair);

        alerta.addCommand(digitarTexto);

        textBox.addCommand(confirmar);

        alerta.setCommandListener(this);

        textBox.setCommandListener(this);

    }

   

    public void startApp() {

        display = Display.getDisplay(this);

        display.setCurrent(alerta);

    }

   

    public void pauseApp() {

    }

   

    public void destroyApp(boolean unconditional) {

         notifyDestroyed();

    }

   

    public void commandAction(Command command, Displayable displayable) {

    }

 

}

 

Neste momento, precisamos apenas implementar o método “commandAction()”, responsável por, no nosso caso, processar a troca e atualização das telas da interface gráfica, de acordo com os comandos acionados pelo usuário. Basicamente, devemos testar o parâmetro “command” recebido pelo método, para sabermos qual foi o comando clicado, e então executamos a ação associada a cada um deles: para o comando “sair”, encerramos a aplicação; para o comando “digitarTexto”, iremos exibir o componente textBox na tela; por fim, o comando “confirmar” mostra novamente o componente alerta na tela, e atualiza o texto do mesmo com o que foi digitado pelo usuário no textBox. A implementação completa do método segue abaixo.

 

    public void commandAction(Command command, Displayable displayable) {

        if (command == sair) {

            destroyApp(true);

        }

        else if (command == digitarTexto) {

            display.setCurrent(textBox);

        }

        else if (command == confirmar) {

            String texto = textBox.getString();

            alerta.setString(texto);

            display.setCurrent(alerta);

        }

    }

 

A seguir, é exibida a implementação completa da nossa classe.

 

import javax.microedition.midlet.*;

import javax.microedition.lcdui.*;

 

public class PrimeiraMidlet extends MIDlet implements CommandListener {

   

    private Alert alerta = new Alert("Primeira Midlet - Tela principal",

                      "Nenhuma informacao foi digitada!", null, AlertType.INFO);

    private TextBox textBox = new TextBox("Primeira Midlet - Digite o texto",

                      "", 200, TextField.ANY);

    private Command sair = new Command("Sair", Command.EXIT, 0);

    private Command digitarTexto = new Command("Digitar Texto", Command.OK, 1);

    private Command confirmar = new Command("Confirmar", Command.OK, 1);

    private Display display;

   

    public PrimeiraMidlet() {

        alerta.addCommand(sair);

        alerta.addCommand(digitarTexto);

        textBox.addCommand(confirmar);

        alerta.setCommandListener(this);

        textBox.setCommandListener(this);

    }

   

    public void startApp() {

        display = Display.getDisplay(this);

        display.setCurrent(alerta);

    }

   

    public void pauseApp() {

    }

   

    public void destroyApp(boolean unconditional) {

        notifyDestroyed();

    }

   

    public void commandAction(Command command, Displayable displayable) {

        if (command == sair) {

            destroyApp(true);

        }

        else if (command == digitarTexto) {

            textBox.setString("");

            display.setCurrent(textBox);

        }

        else if (command == confirmar) {

            String texto = textBox.getString();

            alerta.setString(texto);

            display.setCurrent(alerta);

        }

    }

   

}

 

As imagens abaixo representam as telas resultantes da execução da nossa Midlet.

 

figp1imgangelo.JPG

 

figp2imgangelo.JPG

 

Bem pessoal, assim chega ao fim mais um artigo. Espero que tenha sido de grande valia para todos. No próximo artigo, daremos continuidade à implementação de aplicações móveis (Midlets) e veremos, na prática, outros componentes da interface gráfica com o usuário, bem como mais alguns conceitos por trás da utilização dos mesmos. Qualquer dúvida, sintam-se à vontade para escrever (a.orrico@gmail.com).

 

Abraços a todos, e até lá!!