Está en la página 1de 48

TUTORIAL J2ME (Java Micro Edition)

El siguiente tutorial est enfocado en el desarrollo rpido de aplicaciones, presentando


una breve introduccin a la tecnologa y ejemplos prcticos, tiles para formar un
concepto sobre el tipo de funcionalidades que nos ofrece la plataforma de desarrollo.
Se asume que el lector de este tutorial tiene familiaridad con la programacin orientada
a objetos y con el uso del lenguaje de programacin Java.
En este tutorial se mostrar como realizar aplicaciones de tipo empresarial para
dispositivos mviles. As, se excluye la realizacin de juegos o programas con una
interfaz grfica avanzada; este es un tutorial gil sobre el uso de los componentes
propios de J2ME.
Contenidos:
1. Introduccin a J2ME.
2. MIDLets.
3. Interfaz de Usuario (LCDUI).
4. Comunicacin.
5. Persistencia de datos.
6. Localizacin.

1. INTRODUCCIN A J2ME
Qu es J2ME ?
Java Micro Edition es una versin de Java diseada para dispositivos con capacidades
restringidas de procesamiento y memoria, y conectividad limitada e intermitente; en
concreto, para dispositivos mviles.
Fue creada para cubrir la demanda de
aplicaciones que se pudieran desarrollar en ellos aprovechando las capacidades de
cmputo que, si bien no son comparables con las de un computador personal, son
suficientemente buenas para aplicaciones sencillas que se destaquen ms por
aprovechar las ventajas de la movilidad que por la realizacin de operaciones muy
complejas.
Cuando hablamos de dispositivos mviles nos referimos en concreto a telfonos
celulares, palms, dispositivos blackberry y smartphones, entre otros. Una de las
principales ventajas de j2me es, al igual que en el caso de Java, la portabilidad. Si el
programa fuese diseado especficamente para el sistema operativo propio de cada
tipo de celular tendra capacidades ms amplias, puesto que podra acceder a los

recursos del dispositivo ms ampliamente. En contraposicin, al disear un programa


en j2me este tiene que someterse a ciertas restricciones en el acceso a los recursos
especficos del dispositivo, pero puede ser instalado en mltiples equipos desarrollados
por diferentes fabricantes.
Configuraciones J2ME
Cuando se desarroll el lenguaje se pens en 2 categoras de dispositivos sobre las
cuales se crearan aplicaciones, con el fin de no desaprovechar caractersticas de
dispositivos ms complejos y potentes con respecto de otros ms limitados. Para esto
se crearon 2 configuraciones que vienen predeterminadas en J2ME:
la CDC
(Connected Device Configuration)
y la CLDC (Connected Limited Device
Configuration). La primera de ellas est diseada para dispositivos tipo Set-top-Box;
aquellos que se implementan en conexin con automviles, televisores, y equipos
similares; sus caractersticas incluyen un manejo de memoria de 2MB para Java, y
comunicacion estable, de alta velocidad. Por otro lado la configuracin CLDC fue
diseada para telfonos celulares, palms, pocket pc, tablets y dems dispositivos con
mucho menos poder de cmputo: memoria para Java de 160 a 520K, baja autonoma
(consumo de batera en lugar de alimentacin continua) y comunicacin intermitente (a
causa de la movilidad).
En este tutorial trabajaremos sobre la configuracin CLDC.
Packages J2ME
J2ME es un subconjunto de lo que es el lenguaje formal Java (J2SE), esto quiere decir
que slo un conjunto de libreras y objetos estarn disponibles para usar en J2ME. De
hecho, en comparacin con el desarrollo y robustez de Java, es un conjunto bastante
restringido. Esto se debe a que se presume que el dispositivo tiene poca capacidad de
cmputo, as que se dejaron slo las funciones y paquetes de Java mas esenciales y
bsicos; algunos de ellos fueron reescritos o modificados para cumplir con el propsito
de servir en dispositivos sencillos.
Para permitir que los fabricantes incluyeran la Mquina Virtual de Java de la manera
mas eficiente posible -es decir, del menor tamao- J2ME se constituye de un conjunto
de paquetes bsicos, comunes en todas las implementaciones de J2ME, y paquetes
opcionales, que son especficos para una funcin, y que pueden estar o no estar en el
dispositivo dependiendo del modelo y de las caractersticas que haya incluido el
fabricante.
Entre estos paquetes se cuentan el API de comunicacin Bluetooth (JSR 82), el cual
est incluido en los dispositivos con Bluetooth, el API de localizacin (JSR 179), el API

de acceso al sistema de archivos (JSR 75), etc. Esto hay que tenerlo en cuenta porque
una aplicacin que hace uso de una API opcional que no se encuentre en el dispositivo
en el cual se desea instalar arrojar error al tratar de ser instalada.
Distribucin
Una aplicacin en J2ME se distribuye como un paquete JAR (archivo con extensin
.jar); este archivo acta como instalador de la aplicacin dentro del dispositivo. La
instalacin puede iniciarse por medio de un programa creado por el fabricante, como es
el caso del OVI PC Suite de Nokia, o el PC Suite de Sony Ericsson. En la mayora de
modelos se puede copiar al sistema de archivos del celular y ejecutarlo desde el mismo
dispositivo, o descargarlo de Internet gracias a una tecnologa llamada OTA (Over The
Air) que permite la validacin e instalacin de estos.

2. MIDLets

Un MIDlet es el nombre del objeto que representa un programa dentro de J2ME.


Cuando se crea una aplicacin para J2ME esta puede contener uno o varios MIDLets,
es decir, puede ofrecer varios programas para que el usuario inicie desde su dispositivo
en un solo instalador (archivo .jar). Por lo tanto, un MIDLet es el punto de partida para
crear nuestra aplicacin. Para aquellos familiarizados con las tecnologas web de Java,
un MIDLet puede verse como un applet que corre en un dispositivo mvil.
Un objeto MIDLet luce asi:
Ejemplo 1. Objeto MIDLet.
package hello;
import javax.microedition.midlet.*;
/**
* @author jesus.a.rueda
*/
public class HelloMIDLet extends MIDlet {
private Command cmdSalir;
private Command cmdMostrarMensaje;
public void startApp() {
// Cdigo que se ejecutar al iniciar la aplicacin.
}
public void pauseApp() {

// Cdigo que se ejecutar cuando se pause la aplicacin (por ejemplo, cuando el usuario minimice o cambie de
//aplicacin activa)
}
public void destroyApp(boolean unconditional) {
// Cdigo que se ejecutar cuando la aplicacin finalize; el parmetro unconditional informa
// si el cierre de la aplicacin se produce por demanda de la misma o por demanda del //dispositivo.
}
}

Este es el punto de partida para la creacin de aplicaciones. Seguiremos trabajando


sobre este esquema en la prxima seccin donde veremos el primer ejemplo funcional.

3. INTERFAZ DE USUARIO (LCDUI)


J2ME ofrece 2 mtodos bsicos para mostrar informacin en la pantalla del dispositivo.
Bien puede usarse un conjunto preestablecido de controles de interfaz grfica a la cual
se le denomina API de alto nivel grfico, o bien un objeto Canvas que sirve de lienzo
para dibujar sobre l, es decir, un lienzo en pixeles donde se pueden trazar lneas,
arcos y textos hasta forma la interfaz deseada y que se denomina API de bajo nivel
grafico.
En este tutorial veremos el uso de los controles que conforman el API LCDUI (Liquid
Crystal Display User Interface) de alto nivel.
Display y Displayable (Quin muestra y qu muestra)
Estas 2 clases son las principales para el uso de la pantalla del dispositivo. La clase
Display representa a la pantalla del dispositivo, provee funciones para cambiar lo que
se muestra, obtener lo que se esta mostrando, y otro tipo de informacin acerca de la
pantalla; mientras que la interfaz Displayable hace referencia a algo que se puede
exhibir sobre la pantalla.
La librera de interfaz grfico de alto nivel de J2ME proporciona los siguientes
Displayables: Form, List, TextBox y Alert. Cada uno de ellos es un elemento que
ocupa toda la pantalla al mostrarse, por lo que la aplicacin pasar de uno a otro de
acuerdo a la interaccin con el usuario y el diseo del programa. Form hace referencia
a un formulario que puede contener otros controles para seleccionar o especificar
informacin; List es una lista de opciones donde se puede escoger una de ellas (til
para un men), TextBox representa un cuadro amplio donde introducir texto y Alert es
una alerta que se le mostrar al usuario con informacin acerca de un error, un xito o
una informacin en general.

Ejemplo 2: Hola Mundo.


package hello;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Form;
import javax.microedition.midlet.*;
/**
* @author jesus.a.rueda
*/
public class HelloMIDLet extends MIDlet {
public void startApp() {
// Cdigo que se ejecutar al inciar la aplicacin
Display pantalla = Display.getDisplay(this); // Se obtiene la referencia a la pantalla que usa el MIDLet
Form f = new Form("Hola Mundo"); // Crea un formulario vaco con ttulo 'Hola Mundo'
f.append("HOLA MUNDO !!!"); // Inserta el texto
pantalla.setCurrent(f);
// Establece el formulario como el elemento que se mostrar en pantalla
}
public void pauseApp() {
// Cdigo que se ejecutar cuando se pause la aplicacin (Ej. El usuario minimice o cambie de
// aplicacin activa.
}
public void destroyApp(boolean unconditional) {
// Cdigo que se ejecutar cuando la aplicacion finalice, el parametro unconditional informa
// si el cierre de la aplicacin se produce por demanda de la misma o por demanda del dispositivo
}
}

Comandos
La manera ms comn en que la aplicacin recibe instrucciones por parte del usuario
es por medio de los comandos (Command). Un comando es equivalente a un botn o
a una opcin en un men en una aplicacion regular; es mostrado en pantalla, es decir,
es incluido en un elemento Displayable que puede contener uno o mltiples comandos.
Un comando tiene un nombre, un tipo de comando que especifica una categora
general (Atrs, Salir, Ok, Aceptar) y una prioridad. Todo esto para ayudar al dispositivo
a ubicar el comando dado que el programador no posee control absoluto sobre como
se van a mostrar los elementos; slo puede sugerir algunos parmetros y el dispositivo
ser el que determine automticamente como se ver y donde irn.
Cuando un comando es seleccionado se invoca la funcin commandAction del objeto
registrado en el Displayable para que gestione las acciones de los comandos. Este

objeto debe implementar la interfaz CommandListener. y debe registrarse con el


displayable a travs del mtodo setCommandListener.
Ejemplo 3: Comandos.
package hello;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.midlet.*;
/**
* @author jesus.a.rueda
*/
public class HelloMIDLet extends MIDlet implements CommandListener { //Implementa la gestin de comandos
private Command cmdSalir;
private Command cmdMostrarMensaje;
private Form formulario;
public void startApp() {
// Cdigo que se ejecutar al inciar la aplicacin
Display pantalla = Display.getDisplay(this); // Se obtiene la referencia a la pantalla que usa el MIDLet
formulario = new Form("Hola Mundo"); // Crea un formulario vaco con ttulo 'hola mundo'
formulario.append("HOLA MUNDO !!!"); // Inserta el texto
cmdSalir = new Command("Salir", Command.EXIT,0);
// Crea el comando salir
cmdMostrarMensaje = new Command("Mostrar", Command.OK, 0); //Crea el comando mostrar mensaje
formulario.addCommand(cmdSalir);
// Inserta el comando salir
formulario.addCommand(cmdMostrarMensaje); // Inserta el comando mostrar mensaje
formulario.setCommandListener(this); // Establece el gestor de comandos
pantalla.setCurrent(formulario);
// Establece el formulario como el elemento que se mostrar en pantalla
}
public void pauseApp() {
// Cdigo que se ejecutar cuando se pause la aplicacin (Ej. El usuario minimice o cambie de
// aplicacin activa.
}
public void destroyApp(boolean unconditional) {
// Cdigo que se ejecutar cuando la aplicacin finalice; el parmetro unconditional informa
// si el cierre de la aplicacin se produce por demanda de la misma o por demanda del dispositivo
}
// Gestin de comandos
public void commandAction(Command c, Displayable d) {
if(c == cmdSalir){
this.notifyDestroyed(); // Finaliza la aplicacin
}
if(c==cmdMostrarMensaje){
formulario.append("\n");

formulario.append("El Comando fue ejecutado y muestra este mensaje!");


}
}
}

El tipo del comando se obtiene con los campos estticos de la clase command:
Command.EXIT: Comando para salir de la aplicacin.
Command.OK: Comando para aceptar la operacin.
Command.BACK: Comando para regresar.
Command.ITEM: Comando asociado a un tem.
Command.SCREEN: Comando normal.
Command.STOP: Comando para detener la operacin.
Command.CANCEL: Comando para cancelar la operacin.
Command.HELP: Comando para obtener ayuda.
Como se dijo anteriormente, el tipo de comando no le da ninguna funcionalidad al
mismo; slo le sirve al dispositivo para encontrar el mejor lugar donde mostrar el
comando.
Ejemplo 4: Comandos y navegacin.
package hello;
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.List;
import javax.microedition.midlet.*;
/**
* @author jesus.a.rueda
*/
public class HelloMIDLet extends MIDlet implements CommandListener { //Implementa la gestin de comandos
private Command cmdSalir;
private Command cmdIrAEscogerIdioma;
private Command cmdAtras;
private Command cmdEscogerIdioma;
private Form formulario;
private List listaIdiomas;
private Display pantalla;
private String[] saludos = { "Hello", "Hola", "Buon giorno", "Bonjour", "Guten Tag", "Bom dia" };
public void startApp() {

// Cdigo que se ejecutar al inciar la aplicacin


pantalla = Display.getDisplay(this); // se obtiene la referencia a la pantalla que usa el MIDLet
// Creacion del formulario principal
formulario = new Form("Hola Mundo"); // Crea un formulario vaco con titulo 'Hola Mundo'
formulario.append("HOLA MUNDO !!!"); // Inserta el texto
cmdSalir = new Command("Salir", Command.EXIT,0);
// Crea el comando salir
cmdIrAEscogerIdioma = new Command("Idioma", Command.SCREEN, 0); // Comando para ir a la lista
formulario.addCommand(cmdSalir);
// Inserta el comando salir
formulario.addCommand(cmdIrAEscogerIdioma); // Inserta el comando mostrar mensaje
formulario.setCommandListener(this); // Establece el gestor de comandos
pantalla.setCurrent(formulario);
// Establece el formulario como el elemento que se mostrar en pantalla
// Creacin de la lista de idiomas
listaIdiomas = new List("IDIOMAS",List.IMPLICIT); // Se crea la lista
listaIdiomas.append("Ingles", null); // Se aaden opciones a mostrar en la lista
listaIdiomas.append("Espaol", null);
listaIdiomas.append("Italiano", null);
listaIdiomas.append("Frances", null);
listaIdiomas.append("Aleman", null);
listaIdiomas.append("Portuges", null);
cmdEscogerIdioma = new Command("Seleccionar",Command.OK,0); // Se crea el comando para seleccionar el idioma
cmdAtras = new Command("Atras",Command.BACK, 0); // Se crea el comando para volver al formulario
listaIdiomas.addCommand(cmdEscogerIdioma); // Se registra el comando
listaIdiomas.addCommand(cmdAtras);
listaIdiomas.setSelectCommand(cmdEscogerIdioma); // Se establece el comando como el principal en la lista
listaIdiomas.setCommandListener(this); // Se establece el manejador de comandos para la lista
}
public void pauseApp() {
// Cdigo que se ejecutar cuando se pause la aplicacin (Ej. El usuario minimice o cambie de
// aplicacin activa
}
public void destroyApp(boolean unconditional) {
// Cdigo que se ejecutar cuando la aplicacin finalice; el parmetro unconditional informa
// si el cierre de la aplicacin se produce por demanda de la misma o por demanda del dispositivo
}
// Gestin de comandos
public void commandAction(Command c, Displayable d) {
if(c == cmdSalir){
this.notifyDestroyed(); // Finaliza la aplicacin
}
if(c==cmdIrAEscogerIdioma){
pantalla.setCurrent(listaIdiomas); // Se establece la lista como lo que se muestra en pantalla
}
if(c==cmdAtras){
pantalla.setCurrent(formulario); // Se establece el formulario
}
if(c==cmdEscogerIdioma){
int index = listaIdiomas.getSelectedIndex(); // Se obtiene el ndice seleccionado
String saludo = saludos[index]; // Se obtiene el saludo que corresponde al ndice

Alert alrtSaludo = new Alert(saludo); // Se crea la alerta con el saludo


formulario.append("\n"+saludo); // Se escribe el saludo en el formulario
pantalla.setCurrent(alrtSaludo,formulario); // Se muestra la alerta, y luego de ella el formulario
}
}
}

Formularios
Un formulario es un Displayable que contiene mltiples controles para la captura y
visualizacin de informacin; a estos componentes se les denomina formalmente
Items.
Estos tems son agregados secuencialmente en el formulario con el metodo append del
mismo.
tems de formulario:
1. TextField: Este tem provee la funcionalidad de una caja de texto donde el usuario
puede ingresar informacin; en su constructor se debe especificar un ttulo (label) , un
texto, una longitud mxima de caracteres permitida y una mscara, que es una opcin
que limita el conjunto de caracteres que se puede usar en este tem. Estas mscaras
se encuentran como variables estticas en la clase TextField:
TextField.ANY: Cualquier texto es admitido.
TextField.NUMERIC: Solo nmeros.
TextField.DECIMAL: Permite nmeros con decimales.
TextField.EMAILADDR: Permite caracteres usados para direcciones de email.
TextField.PHONENUMBER: Permite nmeros telefnicos.
TextField.PASSWORD: Permite contraseas, es decir, oculta el texto mientras
se escribe.
Para establecer el texto de un TextField se usa el metodo setString(String) y para
recuperar el texto que el usuario a escrito se usa el metodo String getString().
Ejemplo 5. Uso del TextField:
package hello;
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.TextField;
import javax.microedition.midlet.*;

/**
* @author jesus.a.rueda
*/
public class TextFieldExample extends MIDlet implements CommandListener {
private Form formulario;
private TextField tfNombre;
private TextField tfEdad;
private TextField tfEstatura;
private TextField tfUsuario;
private TextField tfClave;
private TextField tfTelefono;
private TextField tfEmail;
private Form resultados;
private Command cmdAceptar;
private Command cmdSalir;
private Command cmdNuevo;
private Display pantalla;
public void startApp() {
// Se obtiene la pantalla
pantalla = Display.getDisplay(this);
// Creacin del formulario principal
formulario = new Form("Creacion de Usuario");
tfNombre = new TextField("Nombre", "", 256, TextField.ANY); // Cualquier caracter
tfEdad = new TextField("Edad", "", 2, TextField.NUMERIC); // Solo nmeros, mximo 2
tfEstatura = new TextField("Estatura", "0", 5, TextField.DECIMAL); // Nmeros decimales
tfEmail = new TextField("Email", "", 256, TextField.EMAILADDR); // Filtro para email
tfTelefono = new TextField("Telefono", "", 20, TextField.PHONENUMBER);
tfUsuario = new TextField("Usuario", "", 256, TextField.ANY);
tfClave = new TextField("Clave", "", 256, TextField.PASSWORD);
formulario.append(tfNombre);
formulario.append(tfEdad);
formulario.append(tfEstatura);
formulario.append(tfEmail);
formulario.append(tfTelefono);
formulario.append(tfUsuario);
formulario.append(tfClave);
// Comandos del formulario principal
cmdAceptar = new Command("Crear", Command.OK, 0);
cmdSalir = new Command("Salir", Command.EXIT, 0);
formulario.addCommand(cmdSalir);
formulario.addCommand(cmdAceptar);
formulario.setCommandListener(this);
// Formulario de resultados
resultados = new Form("Resultados");
cmdNuevo = new Command("Nuevo", Command.OK, 0);
resultados.addCommand(cmdNuevo);
resultados.setCommandListener(this);

pantalla.setCurrent(formulario);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
//Funcin para validar los datos del formulario
private String Validar() {
String error = "";
String nombre = tfNombre.getString();
String strEdad = tfEdad.getString();
if(strEdad.equals(""))
strEdad = "0";
int edad = Integer.parseInt(strEdad);
String strEstatura = tfEstatura.getString();
if(strEstatura.equals(""))
strEstatura = "0";
double estatura = Double.parseDouble(strEstatura);
String usuario = tfUsuario.getString();
String clave = tfClave.getString();
if (nombre.equals("")) {
error = "Debe especificar un nombre";
}
if (edad <= 0) {
error = "Debe especificar una edad vlida";
}
if (estatura <= 0 || estatura > 2.5) {
error = "Debe especificar una altura vlida";
}
if (usuario.equals("")) {
error = "Debe escribir un nombre de usuario";
}
if (clave.length() < 8) {
error = "La clave debe ser mayor de 8 caracteres";
}
return error;
}
public void commandAction(Command c, Displayable d) {
if (c == cmdSalir) {
this.notifyDestroyed();
}
if (c == cmdNuevo) {
// Limpiar datos del formulario principal
tfClave.setString(null);
tfEdad.setString(null);

tfEmail.setString(null);
tfEstatura.setString(null);
tfNombre.setString(null);
tfTelefono.setString(null);
tfUsuario.setString(null);
// Limpiar los datos del formulario de resultados
resultados.deleteAll();
pantalla.setCurrent(formulario);
}
if (c == cmdAceptar) {
String error = Validar();
if (error.equals("")) {
// Escribir en el formulario de resultados los datos capturados
// Por el formulario principal
resultados.append("Nombre: " + tfNombre.getString());
resultados.append("\n");
resultados.append("Edad: " + tfEdad.getString());
resultados.append("\n");
resultados.append("Estatura: " + tfEstatura.getString());
resultados.append("\n");
resultados.append("Login: " + tfUsuario.getString());
resultados.append("\n");
resultados.append("Email: " + tfEmail.getString());
resultados.append("\n");
resultados.append("Telefono: " + tfTelefono.getString());
pantalla.setCurrent(resultados);
} else {
// Si ocurri un error en la validacin, se muestra como una alerta
Alert a = new Alert(error);
pantalla.setCurrent(a, formulario);
}
}
}
}

2. StringItem: El tem StringItem es til para mostrar informacin en texto sobre la


pantalla. Dado que es un control permite que el cdigo del programa cambie ese texto
para mostrar otro en cualquier momento.
Para obtener el texto del StringItem se usa la funcin String getString(), y para
establecerlo la funcion setString(String).

Ejemplo 6. Uso del StringItem.


package hello;

import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.StringItem;
import javax.microedition.midlet.MIDlet;
public class StringItemExample extends MIDlet implements CommandListener {
private Display display;
private Form formulario;
private StringItem siPregunta;
private Command cmdRendirse;
private Command cmdSalir;
public StringItemExample() {
}
public void startApp() {
display = Display.getDisplay(this);
formulario = new Form("Pregunta");
siPregunta = new StringItem("Pregunta: ", "Si un avion se estrella en la frontera entre Colombia y Venezuela, donde se
entierran los sobrevivientes ?");
cmdRendirse = new Command("Me Rindo", Command.SCREEN, 1);
cmdSalir = new Command("Salir", Command.EXIT, 1);
formulario.addCommand(cmdSalir);
formulario.addCommand(cmdRendirse);
formulario.append(siPregunta);
formulario.setCommandListener(this);
display.setCurrent(formulario);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
public void commandAction(Command command, Displayable displayable) {
if (command == cmdRendirse) {
siPregunta.setLabel("Respuesta: ");
siPregunta.setText("Los sobrevivientes no se entierran, porque no estan muertos!");
formulario.removeCommand(cmdRendirse);
} else if (command == cmdSalir) {
destroyApp(false);
notifyDestroyed();
}
}
}

3. ImageItem: El control ImageItem muestra una imagen dentro de un formulario.


Siendo especfico, el ImageItem visualiza un objeto de tipo Image propio de J2ME el
cual soporta imgenes en formato PNG de forma estndar, aunque en algunas
implementaciones soporta JPG y GIF no animado.
Ejemplo 7. Uso del ImageItem.
package hello;
import java.io.IOException;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.ImageItem;
import javax.microedition.lcdui.StringItem;
import javax.microedition.midlet.*;
/**
* @author jesus.a.rueda
*/
public class ImageItemExample extends MIDlet implements CommandListener {
private Display pantalla;
private Form formulario;
private ImageItem iiImagen;
private Command cmdSalir;
private Command cmdDerecha;
private Command cmdIzquierda;
private Command cmdCentrar;
public void startApp() {
pantalla = Display.getDisplay(this);
formulario = new Form("Ejemplo de Imagenes");
Image img = null;
try {
img = Image.createImage("/hello/java.png"); // Creacin del objeto image
} catch (IOException ex) {
formulario.append(new StringItem("Error al crear Imagen", ex.getMessage()));
}
if (img != null) {
//Creacin del tem Image, con la imagen centrada
iiImagen = new ImageItem("Imagen Centrada", img, ImageItem.LAYOUT_CENTER, "Dispoitivo no soporta imagenes");
cmdSalir = new Command("Salir", Command.EXIT, 0);
cmdDerecha = new Command("Alinear Derecha", Command.SCREEN, 0);

cmdIzquierda = new Command("Alinear Izquierda", Command.SCREEN, 1);


cmdCentrar = new Command("Centrar", Command.SCREEN, 2);
formulario.addCommand(cmdDerecha);
formulario.addCommand(cmdIzquierda);
formulario.addCommand(cmdCentrar);
formulario.append(iiImagen);
}
formulario.addCommand(cmdSalir);
formulario.setCommandListener(this);
pantalla.setCurrent(formulario);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
public void commandAction(Command c, Displayable d) {
if (c == cmdSalir) {
this.notifyDestroyed();
}
if (c == cmdDerecha) {
iiImagen.setLabel("Imagen Derecha"); // Cambia el ttulo de la imagen
iiImagen.setLayout(ImageItem.LAYOUT_RIGHT); // Cambia la alineacin de la imagen
}
if (c == cmdIzquierda) {
iiImagen.setLabel("Imagen Izquierda");
iiImagen.setLayout(ImageItem.LAYOUT_LEFT);
}
if (c == cmdCentrar) {
iiImagen.setLabel("Imagen Centrada");
iiImagen.setLayout(ImageItem.LAYOUT_CENTER);
}
}
}

La obtencion del objeto image puede hacerse de mltiples formas: a) Invocando la


ruta donde est el archivo de imagen dentro de la aplicacion, b) Tomndola de un flujo
de datos que puede provenir de Internet o de un archivo fisico dentro del dispositivo,
entre otras opciones, c) Construirla a partir de valores de RGB pixel a pixel.
4. ChoiceGroup: Un ChoiceGroup es un tem encargado de desplegar una lista de
opciones para el usuario.
Esta lista puede ser:
a)
Exclusiva
(ChoicheGroup.EXCLUSIVE), lo cual har que slo se permita la escogencia de un
elemento, b) Mltiple (ChoiceGroup.MULTIPLE), que permite la escogencia de varias
opciones, y c) Desplegable (ChoiceGroup.POPOUT), que har que slo una opcin se

pueda escoger, pero mostrar la lista como un cuadro desplegable que se abrir
cuando el usuario seleccione la opcin.
El ChoiceGroup muestra cadenas de texto como opcin. Cada una puede tener una
imagen asociada que servir como cono de la opcin. Se puede obtener dependiendo
del modo escogido, el ndice que est seleccionado, o un vector con el estado
(seleccionado o no) de cada una de las opciones.
Ejemplo 8. Uso del ChoiceGroup.
package hello;
import javax.microedition.lcdui.ChoiceGroup;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.StringItem;
import javax.microedition.midlet.*;
/**
* @author jesus.a.rueda
*/
public class ChoiceGroupExample extends MIDlet implements CommandListener {
private Display pantalla;
private Form formulario;
private ChoiceGroup cgCiudad;
private ChoiceGroup cgSexo;
private ChoiceGroup cgBanco;
private Command cmdAceptar; // Comando para ir a la ventana de resultados
private Command cmdSalir; // Comando para salir de la aplicacin
private Command cmdVolver; //Comando para volver de la pantalla de resultados
private Form resultados;

private String[] ciudades = {"Armenia", "Barranquilla", "Bogota", "Bucaramanga", "Cali", "Cartagena", "Cucuta", "Ibague",
"Manizales", "Medellin", "Pereira"};
private String[] bancos = {"BBVA", "Bancolombia", "Davivienda", "HSBC", "Colmena", "Banco Popular", "Banco de Bogota"};
public void startApp() {
pantalla = Display.getDisplay(this);
formulario = new Form("Encuesta Bancaria");
// Se crea el ChoiceGroup de la ciudad, en modo lista desplegable
cgCiudad = new ChoiceGroup("Ciudad", ChoiceGroup.POPUP);
// Se asignan las opciones con el vector de ciudades

for (int i = 0; i < ciudades.length; i++) {


cgCiudad.append(ciudades[i], null);
}
// Se crea el ChoiceGroup de sexo, de forma exclusiva
cgSexo = new ChoiceGroup("Sexo", ChoiceGroup.EXCLUSIVE);
cgSexo.append("Hombre", null);
cgSexo.append("Mujer", null);
// Se crean los bancos posibles de forma mltiple para permitir la escogencia de varios bancos
cgBanco = new ChoiceGroup("Tiene Cuenta en: ", ChoiceGroup.MULTIPLE);
for (int i = 0; i < bancos.length; i++) {
cgBanco.append(bancos[i], null);
}
cmdAceptar = new Command("Aceptar", Command.OK, 0);
cmdSalir = new Command("Salir", Command.EXIT, 0);
cmdVolver = new Command("Volver", Command.BACK, 0);
formulario.append(cgCiudad);
formulario.append(cgSexo);
formulario.append(cgBanco);
formulario.addCommand(cmdSalir);
formulario.addCommand(cmdAceptar);
formulario.setCommandListener(this);
resultados = new Form("Resultados");
resultados.addCommand(cmdVolver);
resultados.setCommandListener(this);
pantalla.setCurrent(formulario);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
public void commandAction(Command c, Displayable d) {
if(c==cmdSalir){
this.notifyDestroyed();
}
if(c==cmdVolver){
// Se limpian los bancos seleccionados al pasar un vector con elementos false
// Esto hace que todas las opciones queden como no seleccionadas
cgBanco.setSelectedFlags(new boolean[bancos.length]);
// Selecciona la primera opcin de las ciudades
cgCiudad.setSelectedIndex(0, true);
// Selecciona la primera opcin del sexo
cgSexo.setSelectedIndex(0, true);
// Elimina todos los datos sobre el formulario de respuesta
resultados.deleteAll();
// Establece el formulario principal como el que se muestra en pantalla
pantalla.setCurrent(formulario);

}
if(c==cmdAceptar){
String sexo = "Hombre";
if(cgSexo.getSelectedIndex()==1) // Obtiene el ndice seleccionado
sexo = "Mujer";
resultados.append(new StringItem("Sexo",sexo));
resultados.append(new StringItem("Ciudad",ciudades[cgCiudad.getSelectedIndex()]));
String strBancos = "";
boolean[] seleccionados = new boolean[bancos.length];
cgBanco.getSelectedFlags(seleccionados); //Obtiene el estado de cada opcin, true si est seleccionada
for(int i=0;i<bancos.length;i++){
if(seleccionados[i]) // Si est seleccionada la opcin con ndice i
strBancos += "\n"+bancos[i]; // Actualiza la cadena de bancos
}
resultados.append(new StringItem("Bancos",strBancos));
pantalla.setCurrent(resultados);
}
}
}

5. DateField: DateField es un tem que sirve para seleccionar o establecer una fecha y
hora, para el manejo de fechas J2ME provee el objeto Date, por lo que este control se
puede establecer en un Date especfico y obtener el Date que el usuario haya
especificado. El modo de seleccin de la fecha depende de la implementacin
especfica del dispositivo, mostrando en algunos un calendario completo, y en otros
solo un cuadro de texto con validacin de la integridad de la fecha.
Un DateField puede configurarse, ya sea para seleccionar fecha y hora
(DateField.DATE_TIME), o bien solo la fecha (DateField.DATE), o bien slo la hora
(DateField.TIME), dependiendo del parmetro mode en su constructor. Para obtener la
fecha que el usuario selecciona se usa el metodo Date getDate(), y para establecerla
se usa el metodo setDate(Date).
Ejemplo 9. Uso del DataField. Seleccin de Fecha
package hello;
import java.util.Calendar;
import java.util.Date;
import javax.microedition.lcdui.ChoiceGroup;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.DateField;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;

import javax.microedition.lcdui.TextField;
import javax.microedition.midlet.*;
/**
* @author jesus.a.rueda
*/
public class DateFieldExample extends MIDlet implements CommandListener {
private Display pantalla;
private Form formulario;
private TextField tfNombre; // Campo de texto para el nombre
private DateField dfFecha; // Seleccin de fecha para el cumpleaos
private ChoiceGroup cgRecordatorios; // Lista de los recordatorios
private Command cmdSalir; // Comando para salir
private Command cmdAgregar; // Comando para agregar una nueva entrada a la lista
private Command cmdEliminar; // Comando para eliminar las entradas seleccionadas
public void startApp() {
pantalla = Display.getDisplay(this);
formulario = new Form("Recordatorios Cumpleannos");
cgRecordatorios = new ChoiceGroup("Recordatorios", ChoiceGroup.MULTIPLE);
cgRecordatorios.setFitPolicy(ChoiceGroup.TEXT_WRAP_ON);
dfFecha = new DateField("", DateField.DATE); // Se crea en modo DATE para escoger solo la fecha
tfNombre = new TextField("Nombre", null, 256, TextField.ANY);
cmdSalir = new Command("Salir", Command.EXIT, 0);
cmdAgregar = new Command("Agregar", Command.OK, 0);
cmdEliminar = new Command("Eliminar", Command.SCREEN, 0);
formulario.append(tfNombre);
formulario.append(dfFecha);
formulario.append(cgRecordatorios);
formulario.addCommand(cmdSalir);
formulario.addCommand(cmdAgregar);
formulario.addCommand(cmdEliminar);
formulario.setCommandListener(this);
pantalla.setCurrent(formulario);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
// Funcin para obtener el nombre del mes
private String getNombreMes(int mes) {
switch (mes) {
case 1:
return "Enero";
case 2:
return "Febrero";

case 3:
return "Marzo";
case 4:
return "Abril";
case 5:
return "Mayo";
case 6:
return "Junio";
case 7:
return "Julio";
case 8:
return "Agosto";
case 9:
return "Septiembre";
case 10:
return "Octubre";
case 11:
return "Noviembre";
case 12:
return "Diciembre";
default:
return null;
}
}
public void commandAction(Command c, Displayable d) {
if (c == cmdSalir) {
this.notifyDestroyed(); // salir
}
if (c == cmdAgregar) {
String text = tfNombre.getString();
Date date = dfFecha.getDate(); // Obtiene el objeto Date que representa la fecha seleccionada
// Formatear la fecha, usando el objeto calendario para obtener informacion de la fecha (Date)
Calendar calendario = Calendar.getInstance(); // Se instancia el calendario
calendario.setTime(date); // Se le establece la fecha seleccionada
int mes = calendario.get(Calendar.MONTH) + 1; // Se obtiene el mes
int dia = calendario.get(Calendar.DAY_OF_MONTH); // Se obtiene el da del mes
String NombreMes = getNombreMes(mes); // Se obtiene el nombre del mes
text = NombreMes + ", " + dia + " - " + text;
cgRecordatorios.append(text, null); // Se agrega la entrada a la lista
tfNombre.setString(null); // Se borrra el cuadro de texto
dfFecha.setDate(new Date()); // Se establece la fecha como la fecha actual
}
if (c == cmdEliminar) {
// Se eliminan los indices seleccionados
int i = 0;
while (i < cgRecordatorios.size()) {
if (cgRecordatorios.isSelected(i)) {
cgRecordatorios.delete(i);
} else {
i++;

}
}
}
}
}

El uso del objeto Calendar es valioso cuando se trabaja con fechas, ya que otorga
informacin detallada sobre las propiedades de la fecha, como hora, minutos,
segundos, da, ao, etc. Tambin sirve para crear una fecha al establecer estos
parmetros y solicitar la fecha con la funcin getTime().
6. Gauge: El tem Gauge representa un indicador de progreso visual. El progreso
tiene asociado un valor que va desde 0 hasta un valor mximo especificado por el
usuario. Este tem es til cuando se quiere mostrar el avance de una operacin, o se
puede usar para mostrar que se est efectuando una operacin, o tambin, como un
control interactivo para que el usuario determine el progreso manualmente. Por lo tanto
el Gauge se puede configurar de 2 formas, como Interactivo y como No Interactivo.
El gauge interactivo permite que el usuario establezca su valor. Normalmente se
muestra como un grfico de barras donde el usuario determina el valor al desplazarse
desde la posicin mnima hasta la posicin deseada. La apariencia exacta de este
tem, as como la del resto, depende enteramente de la implementacin hecha por el
fabricante del dispositivo.
Un gauge no interactivo es controlado por la aplicacin, con la ventaja de que de puede
ser actualizado en cualquier momento. Tambin se puede configurar en modo
continuo, lo cual har que se muestre como un progreso que no tiene fin pero que se
est ejecutando; esto se logra estableciendo su valor mnimo como indefinido
(Gauge.INDEFINITE)
y
su
valor
mximo
como
continuo
(Gauge.CONTINUOUS_RUNNING).
Ejemplo 10. Uso de Gauge.
package hello;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.Gauge;
import javax.microedition.lcdui.StringItem;
import javax.microedition.lcdui.TextField;
import javax.microedition.midlet.*;

/**
* @author jesus.a.rueda
*/
public class GaugeExample extends MIDlet implements CommandListener,Runnable {
private Display pantalla;
private Form formulario;
private Command cmdSalir;
private Command cmdIniciar; // Comando para iniciar el clculo
private Command cmdDetener; // Comando para detener el clculo
private StringItem siResultado; // Texto resultado
private StringItem siNumero; // Nmero de trmino actual
private TextField tfNumero; // Nmero de trmino mximo
private Gauge gVelocidad;
// Velocidad de la operacin de clculo
private Gauge gProgresoTarea; // Progreso del clculo
private Gauge gProgresoContinuo; // Indicador de progreso general
private boolean detener = false; // Variable para indicar si el clculo debe ser detenido
public void startApp() {
pantalla = Display.getDisplay(this);
formulario = new Form("Calculo de la Sumatoria");
// Progreso interactivo para establecer la velocidad del clculo
gVelocidad = new Gauge("Velocidad", true,10,8);
// Progreso no interactivo, para mostrar el progreso del clculo mientras se realiza
gProgresoTarea = new Gauge("Progreso", false, 1000, 0);
// Progreso no interactivo y continuo, para mostrar que el sistema est realizando una tarea
gProgresoContinuo = new Gauge("Tarea en Progreso",false,Gauge.INDEFINITE,Gauge.CONTINUOUS_RUNNING);
siResultado = new StringItem("Resultado","0");
siNumero = new StringItem("Termino No.","0");
cmdIniciar = new Command("Iniciar",Command.OK,0);
cmdDetener = new Command("Detener",Command.CANCEL,0);
cmdSalir = new Command("Salir", Command.EXIT,0);
tfNumero = new TextField("Numero maximo", "1000", 256,TextField.NUMERIC);
formulario.append(new StringItem("Informacion","El programa calcula la sumatoria de los numeros hasta el valor
especificado como valor maximo"));
formulario.append(tfNumero);
formulario.append(gVelocidad);
formulario.append(siResultado);
formulario.append(siNumero);
formulario.append(gProgresoTarea);
formulario.addCommand(cmdIniciar);
formulario.addCommand(cmdSalir);
formulario.setCommandListener(this);
pantalla.setCurrent(formulario);
}
public void pauseApp() {

}
public void destroyApp(boolean unconditional) {
}
public void commandAction(Command c, Displayable d) {
if(c == cmdSalir)
this.notifyDestroyed();
if(c==cmdIniciar){
formulario.removeCommand(cmdIniciar); // Se quita el comando de iniciar
formulario.addCommand(cmdDetener); // Se agrega el comando de parar el clculo
detener = false;
formulario.insert(1, gProgresoContinuo); // Se inserta en la posicin 1 (debajo del texto de informacin) el indicador de
progreso continuo
Thread hilo = new Thread(this); // Se crea un hilo para que ejecute la operacin de clculo en paralelo
hilo.start();
// Se inicia el hilo
}
if(c==cmdDetener){
detener = true;
// Se le indica al clculo que debe detenerse
}
}

public void run() {


int suma = 0;
int limite = Integer.parseInt(tfNumero.getString()); // Se obtiene el valor lmite
gProgresoTarea.setMaxValue(limite); // Se establece el lmite mximo del progreso
for(int i=0;i<limite;i++){
int tiempoEspera = gVelocidad.getMaxValue() - gVelocidad.getValue(); // Se obtiene el valor seleccionado y se invierte
tiempoEspera *= 50;
// Se escala para determinar el nmero de milisegundos a esperar en cada ciclo
if(detener) {
break; // Si fue dada la orden de detener, el ciclo terminar
}
suma += (i+1); // El conteo de la suma
gProgresoTarea.setValue(i+1); // Se actualiza el progreso
siResultado.setText(String.valueOf(suma)); // Se escribe el resultado actual
siNumero.setText(String.valueOf(i+1)); // Se escribe el valor del trmino actual
if(tiempoEspera>0){
try {
Thread.sleep(tiempoEspera); // Se hace la pausa para manejar la velocidad del clculo
} catch (InterruptedException ex) {}
}
}
formulario.delete(1); // Se quita el indicador de progreso continuo que estaba en la posicin 1
formulario.addCommand(cmdIniciar); // Se agrega nuevamente el comando de inciar
formulario.removeCommand(cmdDetener); // Se quita el comando de detener
}
}

En el anterior ejemplo no solo se muestran las diversas configuraciones del gauge,


sino que tambin se muestran los procesos con hilos. Estos son comunes en las
aplicaciones Java, y tambin se encuentran disponibles para las aplicaciones de J2ME.
Al igual que en las aplicaciones de escritorio, en la manipulacion de elementos grficos
dentro de bucles los cambios sobre los elementos grficos no se ven dado que la
actualizacin de la pantalla se har cuando el bloque de cdigo termine. Por eso se
hace necesario el uso de hilos para este ejemplo.

Eventos de cambio de estado de tems: Los tems dentro de un formulario ofrecen


un mecanismo para notificar sobre el cambio de su estado; es decir, cuando ocurre un
evento debido a la interaccin del usuario con el tem la accin que genera el evento es
propia de cada tem, y es este mismo quien decide cuando se ejecuta. Para poder
recibir la notificacin del evento se debe registrar en el formulario un objeto que
implemente la interfaz ItemStateListener.
Ejemplo 11. Cambio de Item.
package hello;
import javax.microedition.lcdui.ChoiceGroup;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.Item;
import javax.microedition.lcdui.ItemStateListener;
import javax.microedition.lcdui.StringItem;
import javax.microedition.lcdui.TextField;
import javax.microedition.midlet.*;
/**
* @author jesus.a.rueda
*/
// Se implementa la interfaz ItemStateListener para evaluar los cambios de estado de los tems del formulario
public class ItemStateExample extends MIDlet implements ItemStateListener,CommandListener {
private Display pantalla;
private Form formulario;
private Command cmdSalir;
private ChoiceGroup cgPaises;
private TextField tfTextoBusqueda;
private StringItem siPaisSeleccionado;

private String[] paises =


{"inglaterra","colombia","espana","francia","alemania","argentina","chile","italia","brasil","ecuador","mexico","suiza"};

public void startApp() {


pantalla = Display.getDisplay(this);
formulario = new Form("Ejemplos de Cambio de Estado");
tfTextoBusqueda = new TextField("Buscar", null,256, TextField.ANY);
cgPaises = new ChoiceGroup("Pais", ChoiceGroup.EXCLUSIVE, paises,null);
siPaisSeleccionado = new StringItem("Seleccionado", null);
cmdSalir = new Command("Salir", Command.EXIT,0);
formulario.append(tfTextoBusqueda);
formulario.append(cgPaises);
formulario.append(siPaisSeleccionado);
formulario.addCommand(cmdSalir);
formulario.setCommandListener(this);
// Se registra a este objeto MIDLet como manejador de cambios de estado de los tems de este formulario
formulario.setItemStateListener(this);
pantalla.setCurrent(formulario);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
// Gestin de los cambios de estado de los tems
public void itemStateChanged(Item item) {
if(item==tfTextoBusqueda){ // Si el tem que cambia es el TextField, se asume que el texto cambi
String busqueda = tfTextoBusqueda.getString().toLowerCase(); //Se obtiene el texto nuevo
cgPaises.deleteAll(); // Se eliminan las anteriores opciones de pases
for(int i=0;i<paises.length;i++){
String pais = paises[i].toLowerCase();
if(pais.indexOf(busqueda)>-1) // Se busca la cadena de bsqueda dentro del nombre del pas
cgPaises.append(paises[i], null); // Si se encuentra coincidencia, se agrega el pas a las opciones
}
if(cgPaises.size()>0)
siPaisSeleccionado.setText(cgPaises.getString(0)); // Se deja seleccionada la primera opcin
else
siPaisSeleccionado.setText(null); // No hay opciones para seleccionar, no se deja nada seleccionado
}
// Si el tem que cambia es el ChoiceGroup de las opciones, se asume que el ndice de la opcion seleccionada cambi
if(item==cgPaises){
// Se establece como seleccionada la opcion que est actualmente elegida en el ChoiceGroup
siPaisSeleccionado.setText(cgPaises.getString(cgPaises.getSelectedIndex()));
}
}
public void commandAction(Command c, Displayable d) {
if(c==cmdSalir)

this.notifyDestroyed();
}
}

Comandos de tem: Tambin es posible asociar un comando especfico a un tem


dentro del formulario; esto har que el comando se muestre slo cuando el usuario
tenga seleccionado el tem, permitiendo tener una serie de comandos contextuales al
tem seleccionado. Para recibir las notificaciones de los comandos asociados a tems
se debe registrar en el formulario un objeto que implemente la interfaz
ItemCommandListener, y los comandos deben ser agregados al tem en lugar de al
formulario.
Ejemplo 12. Comandos de tem: Calculadora bsica.
package hello;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.Item;
import javax.microedition.lcdui.ItemCommandListener;
import javax.microedition.lcdui.StringItem;
import javax.microedition.lcdui.TextField;
import javax.microedition.midlet.*;
/**
* @author jesus.a.rueda
*/
public class ItemCommandExample extends MIDlet implements ItemCommandListener,CommandListener {
private Display pantalla;
private Form formulario;
private Command cmdSalir;
private StringItem siResultado;
private TextField tfEntrada;
public double valorActual = 0; // Valor actual para operar
// Funcin que crea un botn basado en un StringItem
private StringItem CrearBoton(String texto){
StringItem boton = new StringItem(null,texto,StringItem.BUTTON); // Crea el StringItem con estilo de botn
Command cmdBotonPresionado = new Command(texto, Command.ITEM,0); // Crea el comando asociado
boton.setDefaultCommand(cmdBotonPresionado); // Establece el comando como el comando por defecto del tem
boton.setItemCommandListener(this); // Establece al MIDlet como el manejador de comandos de tem
// Establece propiedades de ubicacin
boton.setLayout(boton.getLayout() | Item.LAYOUT_2 | Item.LAYOUT_CENTER | Item.LAYOUT_EXPAND);

return boton; //Regresa el StringItem creado


}

public void startApp() {


pantalla = Display.getDisplay(this);
formulario = new Form("Calculadora");
siResultado = new StringItem("Resultado", "0");
formulario.append(siResultado);
String[] botones = {"+","-","*","/","=","C"}; // Los diferentes botones a crear
tfEntrada = new TextField(null,"0", 25, TextField.DECIMAL); // Creacin del TextBox para la entrada de datos
formulario.append(tfEntrada);
for(int i=0;i<botones.length;i++){
StringItem boton = CrearBoton(botones[i]);
formulario.append(boton); // Se agrega el botn creado al formulario
}
cmdSalir = new Command("Salir",Command.EXIT,0);
formulario.addCommand(cmdSalir);
formulario.setCommandListener(this);
pantalla.setCurrent(formulario);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
// Gestin de comandos de tem
public void commandAction(Command c, Item item) {
// Se obtiene la operacin, asumiendo que el tem siempre es un StringItem, y que la operacion est en su texto
String operacion = ((StringItem)item).getText();
double entrada = Double.parseDouble(tfEntrada.getString()); // Se recupera el valor de entrada
// Se ejecuta la operacin indicada
if(operacion.equals("+")){
valorActual += entrada;
}
if(operacion.equals("-")){
valorActual -= entrada;
}
if(operacion.equals("*")){
valorActual *= entrada;
}
if(operacion.equals("/")){
valorActual = valorActual / entrada;
}
if(operacion.equals("=")){
valorActual = entrada;
}

if(operacion.equals("C")){
valorActual = 0;
}
tfEntrada.setString("0"); // Se limpia la entrada
siResultado.setText(String.valueOf(valorActual)); // Se visualiza el nuevo valor en el texto
}
public void commandAction(Command c, Displayable d) {
if(c ==cmdSalir)
notifyDestroyed();
}
}

Listas (List)
Una lista List es un Displayable que contiene una lista de opciones. Al ser displayable
esta lista ocupa toda la pantalla, a diferencia del tem ChoiceGroup. Su funcionalidad,
sin embargo, es muy similar a la del tem ChoiceGroup. La lista est diseada para
ejecutarse de 3 modos posibles: a) Exclusiva (Choice.EXCLUSIVE), donde se podr
seleccionar slo 1 elemento de la lista; b) Implcita (Choice.IMPLICIT), donde al
seleccionar un tem se ejecutar el comando que se ha definido para la lista con el
mtodo setSelectCommand; c) o Mltiple (Choice.MULTIPLE), donde se podrn
seleccionar varios elementos de la lista. Este Displayable es sumamente til para
generar mens de navegacin dentro de la aplicacin.
Ejemplo 13. Uso de List.
package hello;
import java.util.Enumeration;
import java.util.Hashtable;
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.List;
import javax.microedition.midlet.*;
/**
* @author jesus.a.rueda
*/
public class ListExample extends MIDlet implements CommandListener {
private Display pantalla;
private List menu; // Men principal
private List subMenu; // Submen
private Command cmdSalir;

private Command cmdSeleccionar;


private Command cmdAtras;
private Hashtable data; // Datos del men

public void startApp() {


pantalla = Display.getDisplay(this);
menu = new List("Mundos", List.IMPLICIT); // Se crea la lista en modo implcito
data = new Hashtable();
data.put("Mundo Tierra",new String[]{"Guerrero","Mago","Siervo"});
data.put("Mundo Agua",new String[]{"Pirata","Capitan de barco","Pescador"});
data.put("Mundo Aire",new String[]{"Aguila","Dragon","Paloma mensajera"});
Enumeration menus = data.keys(); // Se obtienen las llaves de los datos
while(menus.hasMoreElements()) {
String item = menus.nextElement().toString();
this.menu.append(item, null); // Se agrega el tem al menu
}
cmdSalir = new Command("Salir",Command.EXIT, 0);
cmdSeleccionar = new Command("Seleccionar",Command.OK,0);
menu.setSelectCommand(cmdSeleccionar); // Se asigna el comando seleccionar como el comando implcito
menu.addCommand(cmdSalir);
menu.setCommandListener(this); // Se asigna al MIDlet como gestor de comandos
subMenu = new List(null,List.IMPLICIT);
cmdAtras = new Command("Atras",Command.BACK,0);
subMenu.addCommand(cmdAtras);
subMenu.setSelectCommand(cmdSeleccionar); // Se asigna el mismo comando como implcito
subMenu.setCommandListener(this);
pantalla.setCurrent(menu);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
public void commandAction(Command c, Displayable d) {
if(c == cmdSalir)
notifyDestroyed();
if(c==cmdSeleccionar && d == menu){
String itemMenu = menu.getString(menu.getSelectedIndex()); // Se obtiene el texto del tem seleccionado
String[] itemsSubMenu = (String[])data.get(itemMenu); // Se obtienen las opciones para este tem, de los datos
subMenu.setTitle("Personajes "+itemMenu); // Se establece el ttulo de la lista submen
subMenu.deleteAll(); // Se eliminan todas las opciones anteriores
for(int i=0;i<itemsSubMenu.length;i++){
subMenu.append(itemsSubMenu[i], null); // Se agrega el tem al submen
}

pantalla.setCurrent(subMenu); // Se establece el submen en la pantalla


}
if(c == cmdAtras && d == subMenu){
pantalla.setCurrent(menu); // Se establece el men principal, porque se est en el submen
}
if(c == cmdSeleccionar && d == subMenu){
String itemMenu = menu.getString(menu.getSelectedIndex()); //Se obtiene el tem del men
String itemSubMenu = subMenu.getString(subMenu.getSelectedIndex()); // Se obtiene el tem del submen
Alert mensaje = new Alert(itemMenu+" > "+itemSubMenu); // Se muestra una alerta con la ruta
pantalla.setCurrent(mensaje,menu); // Se establece la alerta en pantalla, seguida del men
}
}
}

TextBox
Este Displayable muestra un cuadro de texto. Es muy similar al tem TextField de
formularios, con la diferencia que este se muestra en toda la pantalla del dispositivo,
permitiendo capturar grandes extensiones de texto con ms facilidad. La apariencia de
ste es especfica de la implementacin del fabricante del dispositivo.
Posee, al igual que el TextField, la posibilidad de establecer un filtro para que slo
permita un limitado juego de caracteres.
Ejemplo 14. Uso de Textbox: Cifrado Csar
package hello;
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.TextBox;
import javax.microedition.lcdui.TextField;
import javax.microedition.midlet.*;
/**
* @author jesus.a.rueda
*/
public class TextBoxExample extends MIDlet implements CommandListener {
private Display pantalla;
private Command cmdSalir;
private Command cmdLimpiar; //Comando para limpiar la pantalla
private Command cmdEncriptar; //Comando para realizar la encriptacin
private Command cmdDesencriptar; //Comando para desencriptar el texto
private TextBox cuadroTexto; // Cuadro de texto

private String alfabeto = "abcdefghijklmnopqrstuvwxyz0123456789 "; // Alfabeto que contiene los caracteres a usar
int clave = 3; // Clave de encriptacin
public void startApp() {
pantalla = Display.getDisplay(this);
// Se crea el cuadro de texto con el mensaje incial
cuadroTexto = new TextBox("Encriptacion Cesar", "Hola Mundo", 256, TextField.ANY);
cmdSalir = new Command("Salir",Command.EXIT,0);
cmdEncriptar = new Command("Encriptar", Command.SCREEN, 0);
cmdDesencriptar = new Command("Desencriptar", Command.SCREEN, 1);
cmdLimpiar = new Command("Limpiar", Command.SCREEN, 2);
cuadroTexto.addCommand(cmdEncriptar);
cuadroTexto.addCommand(cmdDesencriptar);
cuadroTexto.addCommand(cmdLimpiar);
cuadroTexto.addCommand(cmdSalir);
cuadroTexto.setCommandListener(this); // Se establece el MIDlet como gestor de comandos del cuadro de texto
pantalla.setCurrent(cuadroTexto); // Se establece el cuadro de texto sobre la pantalla
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
// Funcin encargada de encriptar/desencriptar
private String Encriptar(String texto, int clave) {
String encriptado = "";
for (int i = 0; i < texto.length(); i++) {
char letra = texto.charAt(i); // Letra para realizar el corrimiento
int indice = alfabeto.indexOf(letra); // ndice de la letra dentro del alfabeto
if (indice < 0) {
// La letra no esta dentro del alfabeto, arroja una excepcin
throw new IllegalArgumentException("El caracter " + (i + 1) + ": '" + letra + "' no es valido");
} else {
int nuevoI = indice + clave; // Corrimiento del ndice de la letra ms la clave
if(nuevoI<0){
// En el caso de ser negativo (clave negativa para desencriptar), se usa el ndice corriendo desde atras //de la cadena
nuevoI = alfabeto.length() + nuevoI;
}
int indiceNuevo = nuevoI % alfabeto.length(); // Se usa el mdulo para asegurar caer dentro del rango de alfabeto
encriptado += String.valueOf(alfabeto.charAt(indiceNuevo)); // Se agrega la letra encriptada a la cadena
}
}
return encriptado;
}
public void commandAction(Command c, Displayable d) {
if (c == cmdSalir) {
notifyDestroyed();
}

if (c == cmdEncriptar) {
//Se obtiene el texto dentro del cuadro de texto y se pasa a minscula
String texto = cuadroTexto.getString().toLowerCase();
try {
String encriptado = Encriptar(texto, clave); // Se encripta con la funcion
cuadroTexto.setString(encriptado); // Se establece el texto encriptado en el cuadro de texto
} catch (IllegalArgumentException ex) {
// Hubo un error, se muestra un alert con el mensaje
pantalla.setCurrent(new Alert(ex.getMessage()), cuadroTexto);
}
}
if (c == cmdDesencriptar) {
String texto = cuadroTexto.getString().toLowerCase();
try {
String desencriptado = Encriptar(texto, -1*clave); // Se usa la clave negativa para desencriptar
cuadroTexto.setString(desencriptado);
} catch (IllegalArgumentException ex) {
pantalla.setCurrent(new Alert(ex.getMessage()), cuadroTexto);
}
}
if( c == cmdLimpiar){
cuadroTexto.setString(null); // Se limpia el texto en el cuadro
}
}
}

Alert
Este Displayable, como hemos visto en ejemplos anteriores, es til para mostrar
mensajes al usuario; est diseado para llamar la atencin del usuario en forma de una
alerta. En los ejemplos anteriores lo hemos usado de la forma mas bsica, pero un
alert tiene ms opciones de configuracin que slo mostrar un mensaje; por ejemplo,
puede contener un ttulo, mostrar una imagen, y al ser Displayable tambin puede
contener comandos, lo que hace que pueda ser usado para tomar decisiones basado
en su texto.
El constructor de un Alert recibe los siguientes parmetros en su forma mas larga y
completa:
Alert a = new Alert(String titulo,String texto,Image imagen,AlertType tipo);

Aqu titulo es el ttulo del alert, texto el texto que contiene el alert, imagen una
imagen asociada que se mostrar en el alert, y tipo uno de los posibles tipos de alerta
que se encuentran en J2ME que son AlertType.ALARM, AlertType.CONFIRMATION,
AlertType.ERROR, AlertType.INFO y AlertType.WARNING. Cada uno de ellos le

sugiere a la implementacin del dispositivo como debe mostrar el alert; la forma exacta
como se muestra depende enteramente del dispositivo.
Adicionalmente un Alert puede contenter un Gauge para mostrar algn progreso. Esto
se hace por medio del mtodo Alert.setIndicator(Gauge), y con la propiedad
Alert.setTimeout(int) se establecen los milisegundos que el alert debe exhibirse en
pantalla antes de cambiar a otro Displayable. Un valor especial Alert.FOREVER le dice
al alert que debe durar hasta que el programa diga lo contrario.
El Alert es un tipo especial de Displayable, ya que es un error mostrar en pantalla un
alert y despus otro. Se debe mostrar un Displayable diferente de un alert antes de
mostrar el siguiente, o se generar una excepcin.
Ejemplo 15. Uso del Alert. Tipos de alert.
package hello;
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.AlertType;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Gauge;
import javax.microedition.lcdui.List;
import javax.microedition.midlet.*;
/**
* @author jesus.a.rueda
*/
public class AlertExample extends MIDlet implements CommandListener {
private Display pantalla;
private Command cmdSalir;
private Command cmdMostrar; // Comando para mostrar los tipos de alert
private Command cmdCancelar;
private Command cmdOk;
private Alert alrtConfirmacion; // Alerta de confirmacin
private List tipos;
public void startApp() {
pantalla = Display.getDisplay(this);
tipos = new List("Tipos de Alerta", List.IMPLICIT, new String[]{"Simple", "Progreso", "Permanente", "Error", "Informacion",
"Alarma", "Advertencia"}, null);
cmdMostrar = new Command("Mostrar", Command.OK, 0);
cmdSalir = new Command("Salir", Command.EXIT, 0);
cmdCancelar = new Command("Cancelar", Command.CANCEL, 0);

cmdOk = new Command("Ok", Command.OK, 0);


alrtConfirmacion = new Alert("Confirmacion", "Esta Seguro de Salir", null, AlertType.CONFIRMATION); //Se crea //el alerta
de confirmacin de salida
alrtConfirmacion.removeCommand(Alert.DISMISS_COMMAND); // Se elmina el comando por defecto de //cancelar
alrtConfirmacion.setTimeout(Alert.FOREVER); // Se establece como permanente
alrtConfirmacion.addCommand(cmdOk); // Se le agrega el comando cmdOK
alrtConfirmacion.addCommand(cmdCancelar); // Se le agrega el comando cancelar
alrtConfirmacion.setCommandListener(this); // Se establece al MIDlet como el gestor de comandos del Alert
tipos.setSelectCommand(cmdMostrar);
tipos.addCommand(cmdSalir);
tipos.setCommandListener(this);
pantalla.setCurrent(tipos);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
public void commandAction(Command c, Displayable d) {
if (c == cmdOk && d == alrtConfirmacion) { // Si el comando es cmdOK y el Displayable actual es el Alert de confirmacion
notifyDestroyed(); // Salir de la aplicacin
}
if (c == cmdSalir) { // Si el comando es salir
pantalla.setCurrent(alrtConfirmacion, tipos); //Mostrar el alert de confirmacin
}
if (c == cmdCancelar && d == alrtConfirmacion) { //Si el comando es cancelar y el Displayable es el alerta de confirmacin
pantalla.setCurrent(tipos); // Muestra el men con los tipos de alerta a escoger
}
if (c == cmdOk) {
pantalla.setCurrent(tipos);
}
if (c == cmdMostrar) {
switch (tipos.getSelectedIndex()) {
case 0:
pantalla.setCurrent(new Alert("Alerta Simple"), tipos); // Muestra una alerta simple
break;
case 1:
int time = 5000;
Alert a = new Alert("Progreso", "Este alert desaparecera en 5 segundos", null, AlertType.INFO);
//Establece el Gauge como continuo (debe establecerse el ttulo del Gauge como null, o generar un error de
//aplicacin
Gauge gProgreso = new Gauge(null, false, Gauge.INDEFINITE, Gauge.CONTINUOUS_RUNNING);
a.setIndicator(gProgreso); // Establece el indicador de progreso para el alert
a.setTimeout(time); // Establece 5000 milisegundos como tiempo de mostrar el alert
a.removeCommand(Alert.DISMISS_COMMAND); // Quita el comando de cancelar por defecto
pantalla.setCurrent(a, tipos); // Muestra el alert y a continuacin la lista de ejemplos

break;
case 2:
Alert a2 = new Alert("Alerta", "Este Alert no se cerrara hasta que no presione el comando OK", null,
AlertType.WARNING);
a2.setCommandListener(this);
a2.removeCommand(Alert.DISMISS_COMMAND);
a2.setCommandListener(this);
a2.addCommand(cmdOk); // Se agrega el comando cmdOk al alert a2
a2.setTimeout(Alert.FOREVER);
pantalla.setCurrent(a2, tipos);
break;
case 3:
pantalla.setCurrent(new Alert("ERROR", "Alerta Tipica de Error", null, AlertType.ERROR), tipos);
break;
case 4:
pantalla.setCurrent(new Alert("Informacion", "Alerta tipica de Informacion", null, AlertType.INFO));
break;
case 5:
pantalla.setCurrent(new Alert("Alarma", "Alerta tipica de Alarma", null, AlertType.ALARM));
break;
case 6:
pantalla.setCurrent(new Alert("Advertencia", "Alerta tipica de Advertencia", null, AlertType.WARNING));
break;
}
}
}
}

4. COMUNICACIN
Como se ha mencionado anteriormente, J2ME ha sido diseado para equipos con
capacidades limitadas. Las limitaciones de cmputo se compensan entonces con las
caractersticas de movilidad, y ms aun, de conectividad en la movilidad, por lo que las
posibilidades de aplicaciones se hacen infinitas en trminos de poder poseer un
terminal movil con la capacidad de conectarse a servidores de contenido e informacion
en cualquier momento.
Las opciones de conectividad de J2ME son variadas y ofrecen diferentes servicios o,
mejor dicho, diferentes protocolos de comunicacin, que van desde conexiones bsicas
de TCP/IP y UPD hasta protocolos ms elaborados como HTTP y WebServices.
En este tutorial nos centraremos en las conexiones web usando el protocolo HTTP,
ofreciendo as una forma fcil y rpida de entregar y recibir informacion con servidores
web.

HttpConnection
J2ME ofrece un framework gnerico para manejar la conectividad, esto es, ofrece una
interfaz comn para los diversos protocolos de comunicacin que soporta, creando un
sistema facil para el programador.
Existe un objeto nico que crea las conexiones, el objeto Connector, y se usa asi:
Connection conexion = Connector.open(String cadenaConexion);

La cadenaConexion es una cadena de texto que especifica el tipo de conexin, la


direccin de conexin y parmetros adicionales. Esta cadena tiene el formato de una
cadena de URL, es decit
{protocolo}://[{destino}][{parametros}].

Cuando la cadena de conexin especifica el protocolo HTTP o HTTPS, el objeto de


conexin resultante es una conexin de tipo HttpConnection la cual se encargar de
manejar toda la operacin de envo y recepcin de datos. Se utiliza asi:
HttpConnection conexion = (HttpConnection)Connector.open(http://www.miservidor.com/datos.txt);

Las funciones bsicas para crear conexiones HTTP se vern en el ejemplo que se
presenta a continuacin, pero antes hay que hacer nfasis en el hecho de que se
recomienda fuertemente que toda conexin se realize en un hilo, para evitar bloqueos
en hilo principal.

Ejemplo 14. Conexin HTTP.


package hello;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
import javax.microedition.lcdui.ChoiceGroup;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.Gauge;
import javax.microedition.lcdui.StringItem;
import javax.microedition.lcdui.TextField;

import javax.microedition.midlet.*;
/**
* @author jesus.a.rueda
*/
public class HttpConnectionExample extends MIDlet implements CommandListener, Runnable {
private Display pantalla;
private Command cmdSalir;
private Command cmdConsultar;
private Command cmdVolver;
private Form formulario;
private TextField tfURL;
private TextField tfParametros;
private Gauge gProgreso;
private ChoiceGroup cgMetodo;
public void startApp() {
pantalla = Display.getDisplay(this);
formulario = new Form("Comunicacion Http");
tfURL = new TextField("URL", "http://www.javacourses.com/hello.txt", 256, TextField.URL);
tfParametros = new TextField("Parametros", null, 256, TextField.URL);
cgMetodo = new ChoiceGroup("Metodo", ChoiceGroup.EXCLUSIVE, new String[]{"GET", "POST"}, null);
gProgreso = new Gauge("Consultando Servidor", false, Gauge.INDEFINITE, Gauge.CONTINUOUS_RUNNING);
cmdSalir = new Command("Salir", Command.EXIT, 0);
cmdConsultar = new Command("Contular Web", Command.OK, 0);
cmdVolver = new Command("Volver", Command.BACK, 0);
formulario.append(tfURL);
formulario.append(tfParametros);
formulario.append(cgMetodo);
formulario.addCommand(cmdConsultar);
formulario.addCommand(cmdSalir);
formulario.setCommandListener(this);
pantalla.setCurrent(formulario);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
public void run() {
Form respuesta = new Form("Resultado de la consulta");
// Los mtodos que soporta el objeto HttpConnection son HttpConnection.GET, HttpConnection.POST y
//HttpConnection.HEAD
String url = tfURL.getString();
String metodo = cgMetodo.getSelectedIndex() == 0 ? HttpConnection.GET : HttpConnection.POST;
// Los parmetros pueden ser enviados por QueryString (GET) o a travs de POST
String parametros = tfParametros.getString();
try {
// Buffer usado para almacenar la respuesta del servidor
StringBuffer buffer = new StringBuffer();
// Canal de Entrada, por donde van a venir los datos del servidor
InputStream is = null;
// Canal de Salida, por donde ira los parmetros si el mtodo es POST
OutputStream os = null;
// Manejador del canal de salida, es til para formatear correctamente los datos sobre el canal de salida

DataOutputStream dos = null;


// Objeto de conexin HTTP, es el objeto clave en la conexin
HttpConnection conexion = null;
// Variable para almacenar la longitud del contenido que viene del servidor
long longitudContenido = 0;
int ch = 0;
try {
// Si el mtodo es GET, los parametros seran aadidos a la URL
if (metodo.equals(HttpConnection.GET)) {
if (parametros != null && !parametros.equals("")) {
url += "?" + parametros;
}
}
// Se crea la conexin a partir del objeto conector
conexion = (HttpConnection) Connector.open(url);
// Se establece el metodo de peticion para la conexin
conexion.setRequestMethod(metodo);
// Si el mtodo es POST, se envan los datos por el canal de salida
if (metodo.equals(HttpConnection.POST)) {
// Se establece la cabecera explicando el tipo de contenido y el conjunto de caracteres usado
conexion.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
// Se abre la canal de salida sobre la conexin
os = conexion.openOutputStream();
// Se relaciona el manejador del canal de salida
dos = new DataOutputStream(os);
// Se escriben los parmetros sobre el canal de salida
dos.write(parametros.getBytes());
}
// Se abre la conexin de entrada
is = conexion.openInputStream();
// Se obtiene el cdigo de respuesta generado por el servidor; aqu es donde se consulta el servidor
int code = conexion.getResponseCode();
// Si el cdigo es OK (402), entonces se procede con la obtencin de los datos
if (code == HttpConnection.HTTP_OK) {
// Se obtiene la longitud del contenido, si el servidor la report en la cabecera de la conexin
longitudContenido = conexion.getLength();
// Si es diferente de -1 quiere decir que el servidor reporta la longitud
if (longitudContenido != -1) {
// Se leen exactamente el numero de bytes enviados
for (int i = 0; i < longitudContenido; i++) {
if ((ch = is.read()) != -1) {
// Se escriben los datos sobre el buffer
buffer.append((char) ch);
}
}
} else {
// El servidor no reporta la longitud del mensaje, se lee del canal hasta encontrar -1
// que indica que se finaliz la trasmisin de datos
while ((ch = is.read()) != -1) {
// Se establece la longitud de lo que hay sobre el canal de entrada
longitudContenido = is.available();
// Se escriben los datos sobre el buffer
buffer.append((char) ch);
}
}
}
respuesta.append(new StringItem("URL", url));

respuesta.append(new StringItem("Metodo", metodo));


respuesta.append(new StringItem("Codigo Respuesta", conexion.getResponseMessage()));
respuesta.append(new StringItem("Longitud del Contenido (Bytes)", String.valueOf(longitudContenido)));
// Se escribe el contenido en el formulario
respuesta.append(new StringItem("Contenido",buffer.toString()));
} catch (IOException ioe) {
throw ioe;
} finally {
if(is!=null) {
// Se cierra el canal de entrada si ha sido usado
is.close();
}
if (os != null) {
// Si el canal de salida fue usado, se cierra
os.close();
}
// Se cierra la conexin si ha sido establecida
if(conexion!=null)
conexion.close();
}
} catch (Exception ex) {
ex.printStackTrace();
respuesta.append(new StringItem("ERROR", ex.getClass().getName() + ": " + ex.getMessage()));
}
respuesta.addCommand(cmdVolver);
respuesta.setCommandListener(this);
formulario.addCommand(cmdConsultar);
formulario.delete(0);
pantalla.setCurrent(respuesta);
}
public void commandAction(Command c, Displayable d) {
if (c == cmdSalir) {
notifyDestroyed();
}
if (c == cmdConsultar) {
Thread t = new Thread(this);
formulario.removeCommand(cmdConsultar);
formulario.insert(0, gProgreso);
t.start();
}
if (c == cmdVolver) {
pantalla.setCurrent(formulario);
}
}
}

Como podemos ver en el ejemplo, el objeto HttpConnection nos sirve para conectarnos
con un servidor web para obtener informacin. Esta informacin puede no ser esttica
ya que podemos enviar parmetros al servidor tanto por GET como por POST, de esta
forma podemos recibir contenido de programas realizados en el servidor.

5. PERSISTENCIA DE DATOS
Las aplicaciones J2ME, debido a su caractersticas de portabilidad, no pueden
confiarse en el sistema de archivos del dispositivo sobre el cual residen dado que para
muchos fabricantes esto constituye un riesgo a la integridad de sus sistemas
.operativos, y por lo tanto del dispositivo como tal. Para minimizar este impacto, y
puesto que la importancia de la persistencia de los datos de la aplicacin es alta, J2ME
viene equipado con su propio modelo de persistencia de datos que garantiza que se
pueda encontrar en toda implementacin de J2ME.
El sistema que proporciona J2ME se denomina Record Management System (RMS), el
RMS es un sistema basado en almacenamientos (RecordStore) y registros (Records),
estos podrian imaginarse como tablas independientes que almacenan registros
identificados por una llave -el ndice del registro- y unos datos binarios que seran el
cuerpo del registro. El sistema RMS no es un sistema robusto de almacenamiento de
informacin como podra serlo una base de datos, pero se ajusta para el alcance de las
aplicaciones y de las capacidades de cmputo de los dispositivos moviles, proveyendo
una funcionalidad nesesaria.
Deben tomarse algunas consideraciones antes del uso del RMS: el tamao de la
informacin que se puede almacenar, tanto en la longitud de los registros como en la
cantidad de los mismos, es bastante limitada; de hecho, slo se puede asegurar que se
dispone de 8Kb por cada almacenamiento. El acceso a esta informacion es sobre
memoria no voltil, por lo que es bastante lento en comparacin con la informacin que
est en memoria. No hay que fiarse del rendimiento de los emuladores, dado que
estos usan al sistema operativo del PC para obtener acceso al RMS.
El punto mas complicado de usar el RMS es la serializacin, es decir, convertir nuestra
informacin a un arreglo de bytes para ser almacenada, y posterirmente, convertir este
arreglo de bytes de vuelta a la informacion u objetos desedos. Hay que recordar que si
hay semejanza con una tabla, esta sera una tabla que solo tiene 2 columnas, el
nmero de registro y los datos.
Ejemplo 15. Uso de RSS.
package hello;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
import java.util.Vector;
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.ChoiceGroup;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.DateField;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.TextField;
import javax.microedition.midlet.*;
import javax.microedition.rms.RecordComparator;
import javax.microedition.rms.RecordEnumeration;
import javax.microedition.rms.RecordStore;
import javax.microedition.rms.RecordStoreException;
/**
* @author jesus.a.rueda
*/
public class RmsExample extends MIDlet implements CommandListener,RecordComparator {
private Display pantalla;
private Form formulario;
private TextField tfNombre;
private DateField dfFecha;
private ChoiceGroup cgRecordatorios;
private Command cmdSalir;
private Command cmdAgregar;
private Command cmdEliminar;
// Vector usado para relacionar los Recordatorios con los ndices del ChoiceGroup
private Vector recordatorios;
public void startApp() {
pantalla = Display.getDisplay(this);
formulario = new Form("Recordatorios Cumpleannos");
cgRecordatorios = new ChoiceGroup("Recordatorios", ChoiceGroup.MULTIPLE);
cgRecordatorios.setFitPolicy(ChoiceGroup.TEXT_WRAP_ON);
dfFecha = new DateField("", DateField.DATE); //se crea en modo DATE para solo escoger la fecha
tfNombre = new TextField("Nombre", null, 256, TextField.ANY);
cmdSalir = new Command("Salir", Command.EXIT, 0);
cmdAgregar = new Command("Agregar", Command.OK, 0);
cmdEliminar = new Command("Eliminar", Command.SCREEN, 0);
formulario.append(tfNombre);
formulario.append(dfFecha);
formulario.append(cgRecordatorios);
formulario.addCommand(cmdSalir);
formulario.addCommand(cmdAgregar);
formulario.addCommand(cmdEliminar);
formulario.setCommandListener(this);
recordatorios = new Vector();
pantalla.setCurrent(formulario);

try {
// Se obtienen los recordatorios guardados previamente en el RMS
ObtenerRecoratoriosDelRMS();
} catch (Exception ex) {
// Si ocurre error
ex.printStackTrace();
pantalla.setCurrent(new Alert(ex.getMessage()), formulario);
}
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
// funcion para obtener el nombre del mes
private String getNombreMes(int mes) {
switch (mes) {
case 1:
return "Enero";
case 2:
return "Febrero";
case 3:
return "Marzo";
case 4:
return "Abril";
case 5:
return "Mayo";
case 6:
return "Junio";
case 7:
return "Julio";
case 8:
return "Agosto";
case 9:
return "Septiembre";
case 10:
return "Octubre";
case 11:
return "Noviembre";
case 12:
return "Diciembre";
default:
return null;
}
}
public void commandAction(Command c, Displayable d) {
if (c == cmdSalir) {
this.notifyDestroyed(); // salir
}
if (c == cmdAgregar) {
String text = tfNombre.getString();
Date date = dfFecha.getDate();
// Se crea un nuevo objeto recordatorio, con el nombre y la fecha
Recordatorio recordatorio = new Recordatorio(text, date);

// Se llama la funcin de agregar el recordatorio


AgregarRecordatorio(recordatorio, true);
tfNombre.setString(null);
dfFecha.setDate(new Date());
}
if (c == cmdEliminar) {
// se eliminan los indices seleccionados
try {
int i = 0;
while (i < cgRecordatorios.size()) {
if (cgRecordatorios.isSelected(i)) {
// se obtiene el recordatorio relacionado con el ndice seleccionado
Recordatorio r = (Recordatorio)recordatorios.elementAt(i);
// se elimina el recordatorio
EliminarRecordatorio(r);
} else {
i++;
}
}
} catch (RecordStoreException ex) {
ex.printStackTrace();
pantalla.setCurrent(new Alert(ex.getMessage()), formulario);
}
}
}
// Funcin para eliminar un recordatorio de la lista
private void EliminarRecordatorio(Recordatorio recordatorio) throws RecordStoreException {
// Se obtiene el ndice dentro del vector
int indice = recordatorios.indexOf(recordatorio);
// se eliminar de acuerdo al indice, en el ChoiceGroup
cgRecordatorios.delete(indice);
// Se elimina el recordatorio del vector
recordatorios.removeElement(recordatorio);
// Se elimina del RMS
EliminarRecordatorioDelRMS(recordatorio);
}
// Funcin para agregar un nuevo recordatorio
private void AgregarRecordatorio(Recordatorio recordatorio, boolean almacenar) {
Calendar calendario = Calendar.getInstance();
calendario.setTime(recordatorio.getFecha());
int mes = calendario.get(Calendar.MONTH) + 1;
int dia = calendario.get(Calendar.DAY_OF_MONTH);
String NombreMes = getNombreMes(mes);
String text = NombreMes + ", " + dia + " - " + recordatorio.getNombre();
// Se agrega al ChoiceGroup
cgRecordatorios.append(text, null);
// se agrega al vector de recordatorios
recordatorios.addElement(recordatorio);
// Si la opcin almacenar esta en true, se almacena en el RMS
if (almacenar) {
try {
// Se llama la funcin de almacenar en el RMS
AlmacenarRecordatorioAlRMS(recordatorio);
} catch (Exception ex) {
// si hay error ...
ex.printStackTrace();

pantalla.setCurrent(new Alert(ex.getMessage()), formulario);


}
}
}
// Funcin encargada de convertir un recodatorio en un conjunto de bytes
private byte[] SerializarRecordatorio(Recordatorio recordatorio) throws IOException {
// Flujo de datos hacia un array de bytes
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// Manejador del flujo de salida
DataOutputStream dos = new DataOutputStream(baos);
// Se escribe la fecha, como el nmero
dos.writeLong(recordatorio.getFecha().getTime());
// Se escribe el nombre sobre el flujo
dos.writeUTF(recordatorio.getNombre());
// Se obtiene el vector de bytes del flujo
byte[] data = baos.toByteArray();
// Se cierra el flujo
baos.close();
// Se regresa el vector de bytes
return data;
}
// Funcion encargada de convertir un arreglo de bytes a un objeto Recordatorio
private Recordatorio DeserializarRecordatorio(byte[] data) throws IOException {
// Flujo de datos de entrada de un arreglo de bytes
ByteArrayInputStream bais = new ByteArrayInputStream(data);
// Manejador de datos del flujo de entrada
DataInputStream dis = new DataInputStream(bais);
// Se lee la fecha
long fechaLong = dis.readLong();
// se asigna al objeto fecha
Date fecha = new Date(fechaLong);
// Se lee el nombre
String nombre = dis.readUTF();
// Se cierra el flujo
bais.close();
// Se instancia el recordatorio con los datos obtenidos
Recordatorio r = new Recordatorio(nombre, fecha);
return r;
}
// Funcin encargada de obtener los recordatorios que estan almacenados en el RMS
private void ObtenerRecoratoriosDelRMS() throws RecordStoreException, IOException {
// Se abre el almacen de datos, si no existe, el parmetro pasado como true lo crea
RecordStore almacen = RecordStore.openRecordStore("recordatorios", true);
// Se obtiene un conjunto de datos del almacen, al no especificar filtro, se obtienen todos
// Se le establece un comparador para tener los datos ordenados
// El tercer parmetro indica si debe actualizar los datos si estos cambian, paso false
// Porque no manipul el vector de bytes.
RecordEnumeration items = almacen.enumerateRecords(null,this,false);
// Se itera por cada registro
while (items.hasNextElement()) {
// Se obtiene el ID del registro
int ID = items.nextRecordId();
// Con el ID se obtiene el registro
byte[] data = new byte[256];
almacen.getRecord(ID,data,0);

// Se deserializa el recordatorio
Recordatorio recordatorio = DeserializarRecordatorio(data);
// Se le asigna el ID
recordatorio.setID(ID);
// Se agrega a los controles de interfaz grfica
AgregarRecordatorio(recordatorio, false);
}
// Se cierra el almacen
almacen.closeRecordStore();
}

// Funcin para eliminar un recordatorio del RMS


private void EliminarRecordatorioDelRMS(Recordatorio recordatorio) throws RecordStoreException {
// Se abre el almacen
RecordStore almacen = RecordStore.openRecordStore("recordatorios", true);
// Se elimina de acuerdo al ID que se le dio
almacen.deleteRecord(recordatorio.getID());
// Se cierra el almacen
almacen.closeRecordStore();
}
// Funcin para almacenar un recordatorio en el RMS
private void AlmacenarRecordatorioAlRMS(Recordatorio recordatorio) throws RecordStoreException, IOException {
// Se abre el almacen
RecordStore almacen = RecordStore.openRecordStore("recordatorios", true);
// Se serializa el recordatorio para almacenarlo
byte[] data = SerializarRecordatorio(recordatorio);
// Se almacena y se obtiene el ID generado por el RMS
int ID = almacen.addRecord(data, 0, data.length);
// Se le asigna el ID al Recordatorio
recordatorio.setID(ID);
// Se cierra el almacen
almacen.closeRecordStore();
}
// Comparacin de 2 registros, para hacer el ordenamiento
public int compare(byte[] recordA, byte[] recordB) {
try {
if(recordA==null)
return 1;
if(recordB==null)
return -1;
Recordatorio rA = DeserializarRecordatorio(recordA);
Recordatorio rB = DeserializarRecordatorio(recordB);
long fa = rA.getFecha().getTime();
long fb = rB.getFecha().getTime();
return (int)(fa - fb);
} catch (IOException ex) {
return -1;
}
}
}

6. LOCALIZACION
La funcion de localizacin para J2ME no est incluida en todos los dispositivos; se
distribuye como un paquete opcional (JSR 179), disponible en la mayoria de
dispositivos de gama media - alta, especialmente aquellos dotados con dispositivos
GPS.
El API de localizacin provee funcionalidades de ubicacin no solo en trminos
estrictos de coordenadas latitud y longitud, sino que tambien para metodos basados en
la topologia de la red, cuando el operador lo permita, y otros sistemas basados en
referencias.
Para efectos de este tutorial, nos centraremos en el uso y captura de coordenadas
geogrficas con el uso de dispositivos dotados de GPS.
La clase LocationProvider nos brinda toda la funcionalidad para poder obtener la
posicion actual del dispositivo, para notificar la posicion actual y los cambios de esta
con el tiempo.
Se puede registrar un objeto que implemente la interfaz
LocationListener, la cual se registrara con un intervalo de tiempo en la cual se
consultara la posicin con el GPS.
Ejemplo 16. Localizacin.
package hello;
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.StringItem;
import javax.microedition.location.Coordinates;
import javax.microedition.location.Criteria;
import javax.microedition.location.Location;
import javax.microedition.location.LocationException;
import javax.microedition.location.LocationListener;
import javax.microedition.location.LocationProvider;
import javax.microedition.midlet.*;
/**
* @author jesus.a.rueda
*/
public class LocalizationExample extends MIDlet implements CommandListener, LocationListener {
private Display pantalla;

private Form formulario;


private StringItem siLatitud;
private StringItem siLongitud;
private StringItem siEstado;
private Command cmdSalir;
private Command cmdIniciarLecturas;
private Command cmdDetenerLecturas;
// Proveedor de localizacin
private LocationProvider proveedorLocalizacion;
public void startApp() {
pantalla = Display.getDisplay(this);
formulario = new Form("Localizacion por GPS");
cmdSalir = new Command("Salir", Command.EXIT, 0);
siLatitud = new StringItem("latitud: ", null);
siLongitud = new StringItem("Longitud: ", null);
siEstado = new StringItem("Estado", null);
cmdIniciarLecturas = new Command("Iniciar", Command.OK, 0);
cmdDetenerLecturas = new Command("Detener", Command.CANCEL, 1);
formulario.append(siLatitud);
formulario.append(siLongitud);
formulario.append(siEstado);
formulario.addCommand(cmdIniciarLecturas);
formulario.addCommand(cmdSalir);
formulario.setCommandListener(this);
pantalla.setCurrent(formulario);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
public void commandAction(Command c, Displayable d) {
if (c == cmdSalir) {
this.notifyDestroyed();
}
if (c == cmdIniciarLecturas) {
if (proveedorLocalizacion == null) {
// Se crea el objeto criteria, para asistir al dispositivo
// A elegir el mtodo de localizacin que se ajuste al criterio
Criteria criterio = new Criteria();
// No tome en cuenta el consumo de batera
criterio.setPreferredPowerConsumption(Criteria.NO_REQUIREMENT);
// Permite los mtodos de localizacin que pueden incurrirr en cargos monetarios
criterio.setCostAllowed(true);
try {
// Se instancia el proveedor de localizacin
proveedorLocalizacion = LocationProvider.getInstance(criterio);
// Se establece al MIDlet como gestor de las lecturas
// El segundo parmetro es el intervalo en el cual se consulta el mtodo de localizacin
// El tercero es el timeout, cuando est en -1 indica que se usa l por defecto
// El cuarto es la edad de la lectura, si es -1 se usa la lectura no importa que tanto tiempo se haya tomado
proveedorLocalizacion.setLocationListener(this, 5, -1, -1);
formulario.removeCommand(cmdIniciarLecturas);
formulario.addCommand(cmdDetenerLecturas);

} catch (LocationException ex) {


ex.printStackTrace();
pantalla.setCurrent(new Alert(ex.getMessage()), formulario);
}
}
}
if (c == cmdDetenerLecturas) {
if (proveedorLocalizacion != null) {
// Cuando se establece el gestor en null, se desactivan las consultas al mtodo de localizacin
// El proveedor de localizacin slo soporta un gestor a la vez
proveedorLocalizacion.setLocationListener(null, 5, -1, 0);
formulario.addCommand(cmdIniciarLecturas);
formulario.removeCommand(cmdDetenerLecturas);
}
}
}
// Funcin que se llama cuando se obtienen nuevas lecturas
public void locationUpdated(LocationProvider lp, Location lctn) {
// Se obtienen las coordenadas del proveedor de localizacin
Coordinates coordenadas = lctn.getQualifiedCoordinates();
// Hay que preguntar si las coordenadas son vlidas
if (lctn.isValid()) {
// Se obtiene la latitud
siLatitud.setText(String.valueOf(coordenadas.getLatitude()));
// Se obtiene la longitud
siLongitud.setText(String.valueOf(coordenadas.getLongitude()));
}
}
public void providerStateChanged(LocationProvider lp, int state) {
// Se gestiona el cambio de estado del proveedor, mostrardo el mensaje correspondiente
switch (state) {
case LocationProvider.AVAILABLE:
siEstado.setText("Disponible");
break;
case LocationProvider.OUT_OF_SERVICE:
siEstado.setText("Fuera de Servicio");
break;
case LocationProvider.TEMPORARILY_UNAVAILABLE:
siEstado.setText("Temporalmente Fuera de Servicio");
break;
}
}
}

También podría gustarte