You are on page 1of 158

Desarrollo de

Aplicaciones
Móviles I
2

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 3

ÍNDICE

Presentación 3
Red de contenidos 5
UNIDAD 1
SEMANA 1 : Java2 Micro Edition 7
SEMANA 2 : Manejo de Midlets 21
UNIDAD 2
SEMANA 3 : Interfaces de usuario 35
SEMANA 4 : Manejo de ventanas 49
SEMANA 5 : Manejo de listas 61
SEMANA 6 : Controles adicionales 71
SEMANA 9 : Manejo de formularios 79
SEMANA 10 : Manejo de controles Item 97
UNIDAD 3
SEMANA 11 : Almacenamiento se datos 111
SEMANA 12 : Manejo avanzado de datos 1 125
SEMANA 13 : Manejo avanzado de datos 2 137
SEMANA 14 : Introducción a las comunicaciones 149

CIBERTEC CARRERAS PROFESIONALES


4

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 5

PRESENTACIÓN

Desarrollo de Aplicaciones Móviles I, forma parte de la Escuela Técnica de


Computación e Informática. Proporciona la base teórica y práctica para la
comprensión de las tecnologías de comunicación móvil actualmente
existentes. La parte correspondiente a laboratorio se centra exclusivamente
en el desarrollo de aplicaciones para dispositivos móviles usando la
plataforma Java2 Micro Edition.

El manual para el curso ha sido diseñado bajo la modalidad de unidades de


aprendizaje, las que se desarrollan durante semanas determinadas. En cada
una de ellas, hallará los logros que debe alcanzar al final de la unidad; el tema
tratado, el cual será ampliamente desarrollado; y los contenidos. Por último,
encontrará las actividades que deberá desarrollar en cada sesión, que le
permitirán reforzar lo aprendido en la clase.

El curso es eminentemente práctico. Empieza por una introducción sobre la


tecnología móvil y los diferentes aspectos que comprende, para enfocarse
posteriormente en el lenguaje Java 2 Micro Edition y los elementos a utilizar
durante el desarrollo de una aplicación. Se explicará la forma de construir
interfases de usuario, utilizando los diferentes controles existentes.
Posteriormente, se tratará el tema de almacenamiento de datos. Finalmente,
se explicará la forma de construir aplicaciones que se comuniquen a través de
la red. En cada sesión del presente manual, el alumno podrá encontrar
ejemplos prácticos que podrá probar paulatinamente, complementando los
conocimientos adquiridos en clase.

CIBERTEC CARRERAS PROFESIONALES


6

RED DE CONTENIDOS

Desarrollo de Aplicaciones Móviles I

Introducción Almacenamiento
a J2ME de Datos

Interfaz de
usuario Básico Avanzado Conectividad
J2ME MIDlets

Manejo de la Ventanas Controles Formularios


pantalla básicas adicionales

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 7

UNIDAD DE
APRENDIZAJE

1
SEMANA

JAVA2 MICRO EDITION


LOGRO DE LA UNIDAD DE APRENDIZAJE

• Al término de la unidad, los alumnos reconocerán las características


necesarias para desarrollar una aplicación en un entorno de programación en
dispositivos móviles.

• Al término de la unidad, los alumnos identificarán las características


específicas de la plataforma Java 2 Micro Edition, y las clases que se utilizan
para un perfil móvil.

TEMARIO

• Introducción a J2ME
• Máquina virtual KVM, configuraciones y perfiles
• Sistemas operativos para móviles
• El AMS, el ciclo de vida de un MIDlet
• Estados de un MIDlet y su estructura básica

ACTIVIDADES PROPUESTAS

• Investiga acerca de las especificaciones J2ME para los diversos modelos de


dispositivos existentes en el mercado
• Crea y ejecuta un proyecto haciendo uso de Sun Java Wireless Toolkit.

CIBERTEC CARRERAS PROFESIONALES


8

INTRODUCCION A J2ME
1.1. Introducción a las tecnologías móviles

Durante los últimos años, la telefonía celular ha alcanzado niveles altos en


desarrollo de equipos y su evolución continúa siendo extremadamente acelerada.
En efecto, la evolución de la tecnología móvil ha permitido llevar al mercado
soluciones que brindan rentabilidad y ofrecen una mejor calidad de vida, ya que
ponen al servicio del cliente la integración de las comunicaciones con la
información. Hoy en día, se puede observar cómo el desarrollo de aplicaciones
para dispositivos móviles va creciendo en el mercado comercial y se puede
apreciar cómo aplicaciones que antes solo se podían manejar en un computador,
funcionan en forma similar en un dispositivo móvil.
Las características concretas de este tipo de dispositivos han obligado a los
desarrolladores de Java a construir un subconjunto del lenguaje y a reconfigurar
sus principales bibliotecas para permitir su adaptación a un entorno limitado,
propio de los dispositivos móviles. Todo esto hace que necesitemos una nueva
plataforma de desarrollo y ejecución sobre la que centraremos nuestro estudio:
Java 2 Micro Edition, o de forma abreviada: J2ME.

1.2. Lenguaje Java2

1.2.1 Historia
La tecnología Java se creó como una herramienta de programación para
ser usada en un proyecto de Sun Microsystems en el año 1991. En un
principio fue diseñado para generar aplicaciones que controlaran
electrodomésticos.
Con la llegada de Internet Java2 obtiene gran difusión. Esto se produce
debido a su gran robustez e independencia de la plataforma donde se
ejecutase el código, lo cual lo hace ideal para la creación de componentes
interactivos integrados en páginas Web y programación de aplicaciones
independientes. Estos componentes se denominaron applets. Con los años,
Java ha progresado enormemente en varios ámbitos, e hizo necesaria la
creación de diferentes ediciones, cada una de ellas orientadas a algún tipo de
aplicación en particular.
La edición Java2 Micro Edition fue presentada en 1999 por Sun
Microsystems, orientada al desarrollo de aplicaciones para dispositivos
pequeños. Su primera versión estaba orientada al desarrollo sobre Palms. Es

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 9

actualmente la tecnología mas difundida para el desarrollo de aplicaciones


para móviles.

1.2.2 Características
Algunas de las características de la tecnología Java2, y que han sido en
buena parte la razón de su gran difusión, se indican a continuación:
• Orientado a objetos.
Al programar en Java se pueden usar las clases existentes, derivar otras
clases a partir de las primeras y crear nuevas clases.
• Portable.
Las aplicaciones java2 se ejecutarán sobre cualquier sistema que tenga
instalado una máquina virtual java. No dependen de un hardware sistema
operativo en particular.
• Interpretado.
La ejecución de una aplicación Java2 es realizada por la máquina virtual,
instrucción por instrucción.
• Robusto.
La forma en que se diseño la arquitectura de Java2 hace que los errores
graves sean menos frecuentes.

1.2.3 Ediciones
Existen varias ediciones de Java, cada una de ellas diseñada para cierto
ambiente en particular, tal como se indica en la figura 1.1.
• Java Standard Edition (J2SE)
Es la edición que se emplea para desarrollar aplicaciones de escritorio,
así como applets. Es también la versión que base para las demás
ediciones.
• Java Entreprise Edition (J2EE)
Es la edición que se emplea para desarrollar aplicaciones distribuidas,
tales como aplicaciones Web o servlets. Incluye a la edición estándar.

CIBERTEC CARRERAS PROFESIONALES


10

Java 2
Enterprise
Edition
Java 2 TV Auto
Kilo Virtual Machine
Standard Profile Profile
Edition
Java 2
Micro Edition
Java 2
Micro Edition Smart
Card
Profile
Card VM
HotSpot CVM KVM
Figura 1.1: Ediciones de Java2

• Java Micro Edition (J2ME)


Es la edición que se emplea para desarrollar aplicaciones para dispositivos
móviles, denominados MIDlets. Es un subconjunto de la edición estándar
con ciertas clases adicionales orientadas a las necesidades de este tipo de
aplicaciones.

javax.microedition.*

J2EE

J2SE
J2ME

Figura 1.2: Las clases de J2ME son un subconjunto de J2SE

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 11

• Java Card
Es la versión de Java enfocada a aplicaciones que se ejecutan en “tarjetas
inteligentes” (smart cards), encontradas en equipos móviles, tarjetas de
crédito, etc. Es una versión muy limitada de Java.

1.3. Definición de Java2 MicroEdition

Es un entorno de ejecución Java muy pequeño, altamente optimizado para ser


ejecutado en dispositivos consumibles, desde teléfonos móviles, PDAs, palmtops,
handhelds, etc. Se dice consumible, ya que estos equipos consumen varios
recursos; dentro de ellos, uso de procesador, memoria y sobre todo energía.

2. ARQUITECTURA DE J2ME

La edición J2ME es una plataforma, una colección de tecnologías y


especificaciones diseñadas para soportar la gran diversidad de dispositivos en el
mercado. Por esta razón, su arquitectura es modular y escalable para conservar su
funcionalidad y portabilidad. Los elementos que la conforman están graficados en la
figura 2.1 y se especifican a continuación.

Figura 2.1. Arquitectura de J2ME

CIBERTEC CARRERAS PROFESIONALES


12

2.1. Sistema operativo

Es desarrollado por el proveedor del dispositivo y sobre él se ejecutará la


máquina virtual, también desarrollado por el proveedor. En buena parte de los
dispositivos móviles, consiste de un sistema propietario limitado. Sin embargo,
existen en el mercado algunos sistemas operativos para dispositivos móviles
avanzados, tales como Symbian, Windows Mobile, Palm OS, etc.

Figura 2.2. Sistemas operativos para móviles

2.2. Máquina virtual

Una máquina virtual de Java (JVM: Java Virual Machine) es un programa


encargado de lo siguiente:
• Interpretar el código intermedio (bytecode) de los programas Java a código
máquina ejecutable por la plataforma;
• Efectuar las llamadas pertinentes al sistema operativo subyacente;
• Observar las reglas de seguridad y corrección de código definidas para el
lenguaje Java.
De esta forma, la JVM proporciona al programa Java independencia de la
plataforma con respecto al hardware y al sistema operativo subyacente. Las
implementaciones tradicionales de JVM son, en general, muy pesadas en cuanto
a memoria ocupada y requerimientos computacionales. J2ME define varias JVMs
de referencia adecuadas al ámbito de los dispositivos electrónicos que, en
algunos casos, suprimen algunas características con el fin de obtener una
implementación menos exigente.

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 13

2.2.1 Kilo Virtual Machine (KVM)


Se corresponde con la máquina virtual más pequeña desarrollada por Sun.
Su nombre KVM proviene de Kilobyte (haciendo referencia a la baja
ocupación de memoria, entre 40Kb y 80Kb). Se trata de una implementación
de máquina virtual reducida y especialmente orientada a dispositivos con
bajas capacidades computacionales y de memoria. La KVM está escrita en
lenguaje C, aproximadamente unas 24000 líneas de código, y fue diseñada
para ser:
• Pequeña, con una carga de memoria entre los 40Kb y los 80Kb,
dependiendo de la plataforma y las opciones de compilación;
• Alta portabilidad;
• Modulable;
• Lo más completa y rápida posible y sin sacrificar características para las
que fue diseñada.

2.2.2 Compact Virtual Machine (CVM)


La CVM soporta las mismas características que la máquina virtual de
J2SE. Está orientada a dispositivos electrónicos con procesadores de 32 bits
de gama alta y en torno a 2Mb o más de memoria RAM.

2.3. Configuración

Una configuración es el conjunto mínimo de APIs Java que permiten desarrollar


aplicaciones para un grupo de dispositivos. Éstas APIs describen las
características básicas, comunes a todos los dispositivos:
• Características soportadas del lenguaje de programación Java
• Características soportadas por la Máquina Virtual Java
• Bibliotecas básicas de Java y APIs soportadas
Existen dos configuraciones en J2ME: CLDC, orientada a dispositivos con
limitaciones computacionales y de memoria y CDC, orientada a dispositivos con
no tantas limitaciones.

2.3.1 Configuración de disposivos con conexión, CDC (Connected Device


Configuration)
La CDC está orientada a dispositivos con cierta capacidad computacional
y de memoria. Por ejemplo, decodificadores de televisión digital, televisores
con Internet, algunos electrodomésticos y sistemas de navegación en

CIBERTEC CARRERAS PROFESIONALES


14

automóviles. CDC usa una máquina virtual Java2 similar en sus


características a una de J2SE, pero con limitaciones en el apartado gráfico y
de memoria del dispositivo. Ésta máquina virtual es la que hemos visto como
CVM (Compact Virtual Machine). La CDC está enfocada a dispositivos con
las siguientes capacidades:
• Procesador de 32 bits;
• Disponer de 2 Mb o más de memoria total, incluyendo memoria RAM y
ROM;
• Poseer la funcionalidad completa de la máquina virtual Java2;
• Conectividad a algún tipo de red.

2.3.2 Configuración de disposivos limitados con conexión, CDC (Connected


Limited Device Configuration)
La CLDC está orientada a dispositivos dotados de conexión y con
limitaciones en cuanto a capacidad gráfica, cómputo y memoria. Un ejemplo
de estos dispositivos son teléfonos móviles, buscapersonas, PDAs,
organizadores personales, etc.
Algunas de estas limitaciones vienen dadas por el uso de la KVM,
necesaria al trabajar con la CLDC debido a su pequeño tamaño. Los
dispositivos que usan CLDC deben cumplir los siguientes requisitos:
• Disponer entre 160 Kb y 512 Kb de memoria total disponible. Como
mínimo se debe disponer de 128 Kb de memoria no volátil para la
máquina virtual Java2 y las bibliotecas CLDC, y 32 Kb de memoria volátil
para la máquina virtual en tiempo de ejecución.
• Procesador de 16 a 32 bits con al menos 25 MHZ de velocidad;
• Ofrecer bajo consumo, debido a que estos dispositivos trabajan con
suministro de energía limitado, normalmente baterías;
• Tener conexión a algún tipo de red, normalmente sin cable, con conexión
intermitente y ancho de banda limitado (unos 9600 bps).
La CLDC aporta las siguientes funcionalidades a los dispositivos:
• Un subconjunto del lenguaje Java2 y todas las restricciones de su
máquina virtual (KVM);
• Un subconjunto de las bibliotecas Java del núcleo;
• Soporte para entrada y salida básica;
• Soporte para acceso a redes;
• Seguridad.

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 15

2.4. Perfiles

El perfil es el que define las APIs que controlan el ciclo de vida de la aplicación,
interfaz de usuario, etc. Más concretamente, un perfil es un conjunto de APIs
orientado a un ámbito de aplicación determinado. Los perfiles identifican un grupo
de dispositivos por la funcionalidad que proporcionan, por ejemplo,
electrodomésticos, teléfonos móviles, etc. y el tipo de aplicaciones que se
ejecutarán en ellos. Las librerías de la interfaz gráfica son un componente muy
importante en la definición de un perfil. Aquí podemos encontrar grandes
diferencias entre interfaces, desde el menú textual de los teléfonos móviles hasta
los táctiles de los PDAs.

2.4.1 Perfiles de la CDC


• Foundation Profile:
Este perfil define una serie de APIs sobre la CDC orientadas a
dispositivos que carecen de interfaz gráfica como, por ejemplo,
decodificadores de televisión digital. Este perfil incluye gran parte de los
paquetes de la J2SE, pero excluye, totalmente, los paquetes “java.awt”
Abstract Windows Toolkit (AWT) y “java.swing” que conforman la interfaz
gráfica de usuario (GUI) de J2SE. Si una aplicación requiriera una GUI,
entonces sería necesario un perfil adicional.
• Personal Profile:
El Personal Profile es un subconjunto de la plataforma J2SE v1.3, y
proporciona un entorno con un completo soporte gráfico AWT. El objetivo
es el de dotar a la configuración CDC de una interfaz gráfica completa,
con capacidades web y soporte de applets Java. Este perfil requiere una
implementación del Foundation Profile.
• RMI Profile:
Este perfil requiere una implementación del Foundation Profile, se
construye encima de él. El perfil RMI soporta un subconjunto de las APIs
J2SE v1.3 RMI. Algunas características de estas APIs se han eliminado
del perfil RMI debido a las limitaciones de cómputo y memoria de los
dispositivos.

CIBERTEC CARRERAS PROFESIONALES


16

2.4.2 Perfiles CLDC


• PDA Profile:
El PDA Profile está construido sobre CLDC. Pretende abarcar PDAs de
gama baja, tipo Palm, con una pantalla y algún tipo de puntero (ratón o
lápiz) y una resolución de al menos 200x100 pixels.
• Mobile Information Device Profile (MIDP):
Este perfil está construido sobre la configuración CLDC. Al igual que
CLDC, fue la primera configuración definida para J2ME. MIDP fue el
primer perfil definido para esta plataforma y diseñado para dispositivos
como teléfonos celulares y otros equipos de limitada capacidad.

2.5. Paquetes opcionales

Constituyen una extensión de los perfiles y consisten de un conjunto de


librerías que proporcionan funcionalidad adicional. Dichas librerías tienen una
fuerte dependencia con una configuración o perfil en particular, y son instalados
en cada modelo de equipo en particular según el criterio del fabricante.
Ejemplos:
• Java API para Bluetooth (JSR 82), para manejo de conectividad a través
de Bluetooth
• Wireless Messaging API (JSR 120), para envío y recepción de mensajes
cortos (SMS)
• Mobile Media API (JSR 135), para manejo de datos multimedia

2.6. Limitaciones

El presente manual está orientado al desarrollo en J2ME usando las clases del
perfil MIDP sobre la configuración CLDC. Para este tipo de desarrollo, existen
limitaciones en comparación con la programación en J2SE, que se especifican a
continuación:
• En la version CLDC1.0 no hay soporte para tipos en coma flotante. No
existen, por tanto, los tipos double ni float. Esta limitación está presente
porque los dispositivos carecen del hardware necesario para estas
operaciones. A partir de la versión CLDC 1.1, esta característica está
soportada.
• No existe soporte para JNI (Java2 Native Interface) debido a los recursos
limitados de memoria.

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 17

• No existen cargadores de clases (class loaders) definidos por el usuario.


Sólo existen los predefinidos.
• El manejo de hilos es limitado, se pueden crear hilos de manera individual,
pero no usando los grupos de hilos o Thread Groups.
• No hay referencias débiles.
• No está implementada la reflexión, mecanismo por el cual un objeto puede
obtener información acerca de otros objetos (variable, métodos, etc.).
• Limitada capacidad para el manejo de excepciones, debido a que el
manejo de éstas depende, en gran parte, de las APIs de cada dispositivo,
por lo que son éstos los que controlan la mayoría de las excepciones.

3. Proceso de desarrollo

3.1. Etapas del desarrollo en J2ME CLDC - MIDP

Para poder hacer un desarrollo móvil en Java y siguiendo los patrones de


desarrollo que el lenguaje orientado a objetos implica, el desarrollo supone ciertas
fases, que se grafican en la figura:
1. La digitalización del archivo .java que contiene el codigo fuente del aplicativo
2. Luego, el código es compilado generando el archivo .class.
3. Pasa por un preverificador que constata el estado del código.
4. Luego el aplicativo es empaquetado y llevado al dispositivo móvil donde
pasará por otra verificación al momento de ser ejecutado

Figura 3.1. Proceso de desarrollo de una aplicación MIDP/CLDC

CIBERTEC CARRERAS PROFESIONALES


18

3.2. Herramientas de desarrollo

3.2.1 Consideraciones
Para realizar un desarrollo en J2ME, específicamente en MIDP/CLDC,
se deben contar con las siguientes aplicaciones:
• Editor de código
• Preverificador
• Compilador
• Emulador
• Servidor Web Internet, del cual descargar las aplicaciones
Este último puede ser reemplazado por cualquier mecanismo de transferencia
de archivos actualmente disponibles en los dispositivos móviles (Bluetooth,
Infrarrojo, cable de datos, etc.), pero con algunas limitaciones dependientes
del modelo del equipo y con la desventaja que no se podría realizar una
instalación masiva.
Existen herramientas que integran varias de estas aplicaciones. Sun
Microsystems proporciona una que, si bien no es la única, es ampliamente
utilizada. Esta herramienta se denomina Sun Java Wireless Toolkit (SJWTK),
y cumple algunos de los requerimientos. Diversos editores de código, como
Eclipse o Netbeans, han creado librerías adicionales o plug-ins basadas en
SJWT, que proporcionan las herramientas faltantes.

3.2.2 Sun Java Wireless Toolkit


Creado por Sun Microsystem, nos proporciona lo siguiente:
• Administrador de proyectos
• Preverificador / Compilador
• Emuladores
Dicho programa se puede descargar de la página de SUN Microsystem.

http://java.sun.com/products/sjwtoolkit/download.html

La versión usada para los ejemplos del presente manual es la 2.5 y,


para poder instalar y ejecutar este programa, se debe tener instalada la
versión 1.5 del JSDK.

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 19

Figura 3.2. Pantalla inicial de Sun Java Wireless Toolkit

3.2.3 Eclipse
Eclipse es una de las herramientas mas usadas para el desarrollo de
aplicaciones móviles con Java 2 Micro Edition. Como se indicó anteriormente,
existen paquetes adicionales o plug-ins que se basan en SJWTK y que
proporcionan las herramientas para la edición y depuración de código. Entre
los más conocidos están:
• Mobile Toolkit por Java2 applications
• Eclipse ME (http://eclipseme.org)

3.2.4 Netbeans
Al igual que Eclipse, Netbeans posee un paquete adicional, denominado
Mobility Pack, basado en SJWTK y que proporcionan las herramientas para la
edición y depuración de código.

3.2.5 Instalación
Los pasos para la instalación son:
1. Instalar JSDK 1.5;
2. Instalar Sun Java Wireless Toolkit 2.5;
3. Instalar la herramienta escogida para la edición de código. Esto es
independiente del paso 2;
4. Instalar el plug-in correspondiente;
5. Configura el plug-in para que utilice el SJWTK instalador en el paso 2.

CIBERTEC CARRERAS PROFESIONALES


20

Resumen

 J2ME es una de las cuatro ediciones de Java2 que existen. Es la plataforma de


desarrollo sobre dispositivos móviles mas usada.

 J2ME posee una arquitectura orientada a soportar la escasez de recursos de los


dispositivos móviles, así como su gran diversidad. Su maquina virtual es reducida,
y se incluyen dos elementos adicionales, la configuración y el perfil, sobre los
cuales se ejecutan las aplicaciones.

 El proceso de desarrollo de una aplicación en J2ME incluye dos fases de


verificación: una durante el desarrollo, llamada preverificación, y otra cuando dicha
aplicación se encuentra instalada en el dispositivo móvil.

 Si desea saber más acerca de estos temas, puede consultar las siguientes
páginas.

 http://www.mailxmail.com/curso/informatica/dispositivosinalambricos
 http://www.mailxmail.com/curso/informatica/j2me
 http://www.it.uc3m.es/java/
 http://programacion.com/java/tutorial/ags_j2me/
 Si desea descargar las herramientas de programación, puede ir a las siguientes
páginas:

 SJWTK: http://java.sun.com/products/sjwtoolkit/download.html
 Eclipse ME: http://eclipseme.org

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 21

UNIDAD DE
APRENDIZAJE

1
SEMANA

MANEJO DE MIDLETS
LOGRO DE LA UNIDAD DE APRENDIZAJE

• Al término de la unidad, los alumnos reconocerán las características


necesarias para desarrollar una aplicación en un entorno de programación en
dispositivos móviles.

• Al término de la unidad, los alumnos identificarán las características


específicas de la plataforma Java 2 Micro Edition, y las clases que se utilizan
para un perfil móvil.

TEMARIO

• El gestor de aplicaciones (AMS). Ciclo de vida de un MIDlet


• Estados de un MIDlet y su estructura básica
• Clase MIDlet

ACTIVIDADES PROPUESTAS

• Identifica y modifica los elementos de un MIDlet.


• Identifica las etapas del ciclo de vida.
• Realiza los MIDlets indicados en el punto 5.

CIBERTEC CARRERAS PROFESIONALES


22

MIDlets
3.3. Definición

Un MIDlet es una aplicación Java2 para dispositivos móviles. Se caracteriza


por usar las librerías del perfil MIDP sobre la configuración CLDC. Los MIDlets
han sido diseñados pensando en que su principal medio de instalación será la
descarga a través de Internet.
Al medio que garantiza la correcta descarga de la aplicación se denomina
OTA (over the air).

3.4. Elementos

3.4.1 MIDlet jar


Es el archivo de extensión jar, que contiene las clases y otros recursos
asociados, por ejemplo, las imágenes. Adicionalmente, incluye un archivo
manifiesto con información acerca del contenido, este archivo tiene el nombre
manifest.mf.

3.4.2 Descriptor
Es el archivo de texto plano con extensión jad. Contiene diversos datos
que son leídos por el gestor de aplicaciones al momento de descargar el
MIDlet. Revisar el capítulo siguiente para más detalles acerca del gestor de
aplicaciones. Los datos guardados pueden ser obligatorios y opcionales, y
adicionalmente se pueden agregar datos personalizados de la aplicación
• Datos obligatorios
o MIDlet-Name: Nombre del MIDlet
o MIDlet-Version: Versión del MIDlet
o MIDlet-Vendor: Nombre del vendedor
o MIDlet-Jar-URL: URL del sitio donde se descarga el MIDlet.
o MIDlet-Jar-Size: Tamaño del archivo jar
o MicroEdition-Profile: Nombre y version del perfil
o MicroEdition-Configuration: Nombre y version de la configuración

Nota:
Se utiliza el término MIDlet suite para referirse a los dos archivos, MIDlet jar y
descriptor, especialmente cuando contienen varias clases de tipo MIDlet.

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 23

4. Gestor de aplicaciones

4.1. Introducción

Para que todo aplicativo pueda ser instalado y funcione en un dispositivo móvil,
éste debe contar con ciertas características tanto en hardware como en software.
En cuanto al hardware, el equipo debe contar con los siguientes elementos:
• Un procesador, que es el que se va encargar de administrar los diferentes
accesorios del dispositivo celular;
• Una cantidad de memoria para el manejo de los procesos del sistema
operativo y aplicaciones. Cabe resaltar que esta memoria se divide en una
memoria tipo RAM, que es donde se ejecutan las aplicaciones, y una
memoria tipo ROM, en la cual se almacena parte de las aplicaciones que
contiene el dispositivo móvil.
• Además de poder tener una gran capacidad de batería.
En cuanto los requerimientos de software, el dispositivo debe contar con una
aplicación dentro del sistema operativo que sea el encargado de manejar las
aplicaciones. A dicha aplicación se le denomina gestor de aplicaciones.

4.2. Definición

El gestor de aplicaciones o AMS (Application Management System) es el


encargado de administrar y controlar todas las aplicaciones existentes en el
dispositivo móvil. Se encarga de monitorear el funcionamiento de las aplicaciones
y de administrar la ejecución del mismo, ya que todo equipo móvil tiene una
función primordial que es la de comunicar voz, el AMS debe ser capaz de detener
la aplicación en curso cuando ingrese una llamada o un mensaje de texto al
dispositivo móvil.
Al detectar el ingreso de una llamada telefónica, el AMS invocará al método
pausa del aplicativo, el cual colocará en espera a la aplicación para que el
usuario móvil tenga la opción de contestar la llamada recibida. Una vez finalizada
la conversación, el AMS preguntará si desea retomar la ejecución de la aplicación

4.3. Ciclo de vida de un MIDlet

El ciclo de vida representa la existencia del MIDlet desde el momento que el


aplicativo se encuentra empaquetado. Las fases por las que pasa se indican en la
figura 2.1.

CIBERTEC CARRERAS PROFESIONALES


24

Figura 2.1. Fases del ciclo de vida de una aplicación

4.3.1 Localización:
Es la fase en la que el aplicativo es localizado para ser instalado en el
dispositivo celular. Dicha localización se realiza por cualquiera de los medios
de instalación usados, como cable de datos, infrarrojo, Bluetooth y OTA.
4.3.2 Instalación:
Es la fase en el cual el MIDlet es instalado en el equipo.
4.3.3 Ejecución:
Es la fase en la cual el MIDlet es activado para su ejecución. El AMS se
encarga de cargar la aplicación y los elementos que implica para la ejecución,
como la máquina virtual.
4.3.4 Actualización:
Es la fase en el cual el MIDlet es actualizado en el equipo.
4.3.5 Borrado:
Es la fase en el cual el MIDlet es eliminado del equipo.

4.4. Estados de un MIDlet

El AMS no solo se encarga de gestionar el ciclo de vida del MIDlet sino de


manejar los estados de éste durante su ejecución, los cuales se indican en la
figura 2.2.

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 25

Figura 2.2. Estados de una aplicación en ejecución

• En primer lugar, el AMS crea una nueva instancia del MIDlet y realiza la
llamada a su constructor, pasando éste al estado de “Pausa” durante un
corto período de tiempo que es utilizado por el AMS para cargar en
memoria el MIDlet y algunos recursos asociados.
• Cuándo el dispositivo está preparado para ejecutar el MIDlet, el AMS
invoca al método MIDlet.startApp() y pasa al estado de “Activo”. El MIDlet,
entonces, ocupa todos los recursos que necesita para su ejecución.
• Durante el estado “Activo”, el MIDlet puede pasar al estado de “Pausa” por
una acción del usuario, o bien, por el AMS (por ejemplo, por el ingreso de
una llamada telefónica) que reduciría, en todo lo posible, el uso de los
recursos del dispositivo por parte del MIDlet.
• Tanto en el estado “Activo” como en el de “Pausa”, el MIDlet puede pasar
al estado “Destruido” realizando una llamada al método
MIDlet.destroyApp(). Esto puede ocurrir porque el MIDlet haya finalizado
su ejecución o porque una aplicación prioritaria necesite ser ejecutada en
memoria en lugar del MIDlet. Una vez destruido el MIDlet, éste libera todos
los recursos ocupados.

5. Estructura básica

Un MIDlet es una aplicación realizada usando el perfil MIDP; por lo tanto, para
crear una aplicación con estas características se debe realizar lo siguiente:
• Crear una clase que herede de la clase javax.microedition.midlet.MIDlet, para
que el AMS pueda gestionar sus estados y tener acceso a sus propiedades;

CIBERTEC CARRERAS PROFESIONALES


26

• Sobrescribir los métodos que el MIDlet posee, que son: startApp, pauseApp y
destroyApp.
Asimismo, tomar en cuenta las siguientes observaciones:
• Los MIDlets, al igual que los applets carecen de la función main(). Aunque
existiese, el gestor de aplicaciones la ignoraría por completo.
• Un MIDlet no puede realizar una llamada a System.exit(). Una llamada a este
método lanzaría la excepción SecurityException.
La estructura básica de un MIDlet quedaría como sigue:

import javax.microedition.midlet.*;

public class MiMidlet extends MIDlet{


public MiMidlet(){
/* Éste es el constructor de clase. Aquí debemos
Inicializar nuestras variables.
*/
}
public startApp(){
/* Aquí incluiremos el código que queremos que el
MIDlet ejecute cuándo se active.
*/
}
public pauseApp(){
/* Aquí incluiremos el código que queremos que el
MIDlet ejecute cuándo entre en estado de pausa (Opcional)
*/
}
public destroyApp(){
/* Aquí incluiremos el código que queremos que el
MIDlet ejecute cuándo sea destruido. Normalmente
aquí se liberaran los recursos ocupados por el
MIDlet como memoria, procesador, etc (Opcional)
*/
}
}

6. Clase MIDlet

Es la clase base de todas las aplicaciones J2ME basadas en el perfil MIDP. A


continuación se describen sus métodos más importantes.

6.1. Constructor

Método que posee el mismo nombre de la clase sin argumentos. Aquí se pone
el código que se ejecutará al inicio de la aplicación. Si la llamada a este
constructor falla, se lanzaría la excepción SecurityException.

6.2. pauseApp()

6.2.1 Definición
protected abstract void pauseApp()

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 27

6.2.2 Descripción
Método que será llamado por el AMS cuando el MIDlet pasa a un
estado de “Pausa”. Para esto, el MIDlet debe estar en estado “Activo”.
Cuando se crea un MIDlet, este método debe ser sobrescrito para indicar lo
que se realizará cuando se produzca dicho cambio de estado, por ejemplo,
grabar algún dato en la memoria persistente. Si ocurre una excepción
RuntimeException durante la llamada a MIDlet.pauseApp(), el MIDlet será
destruido inmediatamente. Se llamará a su método MIDlet.destroyApp() para
liberar los recursos ocupados.

6.3. startApp()

6.3.1 Definición
protected abstract void startApp()
throws MIDletstateChangeException

6.3.2 Descripción
Método que será llamado por el AMS cuando el MIDlet pasa a un
estado “Activo”. Para esto el MIDlet debe estar en estado de “Pausa”. Cuando
se crea un MIDlet, este método debe ser sobrescrito para indicar lo que se
realizará cuando se produzca dicho cambio de estado, por ejemplo, mostrar
la ventana inicial. En el caso de que el MIDlet no pueda pasar al estado
“Activo” en este momento pero si pueda hacerlo en un momento posterior, se
lanzaría la excepción MIDletstateChangeException.

6.4. destroyApp()

6.4.1 Definición
protected abstract void (boolean incondicional)
throws MIDletstateChangeException

6.4.2 Descripción
Método que será llamado por el AMS cuando el MIDlet pasa a un
estado “Destruido”. Para esto el MIDlet debe estar en estado de “Pausa” o
“Activo”. Cuando se crea un MIDlet, este método debe ser sobrescrito para
indicar lo que se realizará cuando se produzca dicho cambio de estado, por
ejemplo, liberar todos los recursos y/o salvar en el almacenamiento
persistente algún dato que que deba ser guardado.
Si el parámetro ‘incondicional’ es false, el MIDlet puede lanzar la
excepción MIDletstateChangeException para indicar que no puede ser

CIBERTEC CARRERAS PROFESIONALES


28

destruido en este momento. Si es true, el MIDlet asume su estado de


destruido independientemente de como finalice el método.

6.5. notifyDestroyed()

6.5.1 Definición
public final void notifyDestroyed()

6.5.2 Descripción
Este método es usado para indicar al AMS que el MIDlet ha entrado en
el estado de “Destruido”. Normalmente, se llama este método después de
haber llamado a destroyApp(). El AMS considerará que todos los recursos
que ocupaba el MIDlet están libres para su uso.

6.6. notifyPaused()

6.6.1 Definición
public final void notifyPaused()

6.6.2 Descripción
Este método es usado para indicar al AMS que el MIDlet ha entrado en
el estado de “Pausa”. Este método sólo debe ser invocado cuándo el MIDlet
esté en el estado “Activo”. Para volver al estado “Activo” se deberá llamar al
método resumeRequest().

6.7. resumeRequest()

6.7.1 Definición
public final void resumeRequest()

6.7.2 Descripción
Este método proporciona un mecanismo a los MIDlets para indicar al
AMS su cambio de estado a “Activo”. El AMS, en consecuencia, es el
encargado de determinar qué aplicaciones han de pasar a este estado
llamando al método startApp().

Nota:
Los métodos startApp(), pauseApp() y destroyApp() los utiliza el AMS para
comunicarse con el MIDlet, mientras que los métodos resumeRequest(),
notifyPaused() y notifyDestroyed() los utiliza el MIDlet para comunicarse con el
AMS.

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 29

6.8. checkPermission()

6.8.1 Definición
public final int checkPermission(String permiso)

6.8.2 Descripción
Devuelve el estado de un permiso para la aplicación. El permiso se
especificado en el parámetro del mismo nombre. A continuación algunos
ejemplos de permisos:
• javax.wireless.messaging.sms.send: Permiso para enviar mensajes de
texto de tipo SMS
• javax.microedition.pim.ContactList.read: Permiso para leer la agenda de
contactos
• javax.microedition.io.Connector.bluetooth.client: Permiso para conectarse
como cliente a través de Bluetooth
Los valores devueltos por el método se corresponden con la siguiente
descripción:
• 0: si el permiso ha sido denegado
• 1: si el permiso ha sido habilitado
• -1: si el estado es desconocido
Usando este método podemos verificar con anterioridad si el usuario ha
autorizado a la aplicación a realizar ciertos servicios. De este modo, se podrá
realizar algún tipo de notificación al usuario.

6.9. getAppProperty()

6.9.1 Definición
public final String getAppProperty(String key)

6.9.2 Descripción
Este método devuelve el valor de una propiedad guardada en el
descriptor. El nombre de la propiedad a recuperar debe ir indicado en el
parámetro key. El método nos devuelve un String con el valor de la propiedad
o null si no existe ningún valor asociado al parámetro key. Si key es null, se
lanzará la excepción NullPointerException.

CIBERTEC CARRERAS PROFESIONALES


30

6.10. platformRequest()

6.10.1 Definición
public void boolean platformRequest(String url)

6.10.2 Descripción
Este método permite llamar a algún servicio proporcionado por el
dispositivo. Dicho servicio se especifica en el parámetro url, y varían de
acuerdo al modelo del mismo.

7. Ejemplos

7.1. Aplicación HolaMundo

7.1.1 Enunciado
Construir una aplicación que realice lo siguiente:
• Mostrar una ventana con el mensaje “Bienvenido a J2ME”
• Tendrá un botón para salir de la aplicación.
• La figura 5-1 indica como deberá verse la pantalla.

Figura 5.1. Pantalla inicial de la aplicación HolaMundo

7.1.2 Código
/*
*Importar espacios de nombres
*javax.microedition.midlet: Aquí están el MIDlety clases relacionadas
*javax.microedition.lcdui: Aqui están las clases de la interfaz de usuario
**/

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 31

public class HolaMundo extends MIDlet implements CommandListener


{
// Variables a utilizar
private Command botonSalir;
private Display pantalla;
private Form formulario;

public HolaMundo()
{
// Inicializacion de variables
pantalla = Display.getDisplay(this);
botonSalir = new Command("Salir", Command.EXIT, 2);
formulario = new Form("Hola");
StringItem texto = new StringItem(" ", "Bienvenido a J2ME");

// Adicion del StringItem


formulario.append(texto);

// Adicion del commando e inicio de la captura de eventos de entrada


formulario.addCommand(botonSalir);
formulario.setCommandListener(this);
}

public void startApp() throws MIDletStateChangeException


{
// Inicio de la aplicación.
// Se establece a formulario como la pantalla inicial
pantalla.setCurrent(formulario);
}

public void pauseApp()


{
}

public void destroyApp(boolean unconditional)


{
}

public void commandAction(Command c, Displayable s)


{
/*
* Se ha pulsado un boton
**/
if (c == botonSalir)
{
// Si el boton pulsado es el boton salir, salir de la aplicacion
destroyApp(false); // Método definido arriba
notifyDestroyed(); // Método para notificar al Gestor de
// aplicaciones que finalice la aplicacion
}
}
}

7.2. Aplicación Llamada

7.2.1 Enunciado
Construir una aplicación que realice lo siguiente:
• Permita ingresar un número telefónico en formato internacional. Para esto
se usará un control TextBox, cuyo valor inicial será la propiedad “prefijo”
(que debe ser creada en el descriptor).
• El título de la ventana indicará si la aplicación tiene o no el permiso de
envío de mensajes.

CIBERTEC CARRERAS PROFESIONALES


32

• Tendrá dos botones: uno para salir y otro para realizar la llamada usando
el método platformRequest().
• La figura 5-1 indica como deberá verse la pantalla.

Figura 5.2. Pantalla inicial de la aplicación Llamada

7.2.2 Código
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;

/*
Esta aplicación utiliza algunas funciones de la clase MIDlet, como
- getAppProperty: Para obtener el valor de una propiedad
- checkPermission: Para verificar el estado de un permiso
- platformRequest: Para efecutar una llamada a una funcion del equipo, en este
caso, para realizar una llamada telefonica
- notifyDestroyed: Para salir de la aplicacion
Algunas partes del codigo aun no han sido explicadas. Se recomienda no
detenerse alli, pues en las semanas siguientes se explicaran a detalle.
*/

// La clase tiene que heredar de MIDlet


public class Llamada extends MIDlet implements CommandListener {

// Se realiza lo siguiente:
// 1. Obtener una referencia a la pantalla
// 2. Crear una ventana de texto
// 3. Crear dos comandos
private Display dsp = Display.getDisplay(this);
private TextBox txtTelefono = new TextBox("Telefono", "", 13,
TextField.PHONENUMBER);
private Command cmdLlamar = new Command("Llamar", Command.OK, 2);
private Command cmdSalir = new Command("Salir", Command.EXIT, 2);

public Llamada()
{
// Se lee la variable “prefijo” del descriptor
if(getAppProperty("prefijo") != null)
txtTelefono.setString(getAppProperty("prefijo"));

// Se verifica el permiso para enviar mensajes


int permiso = checkPermission("javax.wireless.messaging.sms.send");

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 33

// Dependiendo del valor devuelto, se actualiza el titulo

if (permiso == 0)
txtTelefono.setTitle("SMS no permitidos");
else if (permiso == 1)
txtTelefono.setTitle("SMS permitidos");
else
txtTelefono.setTitle("SMS no configurado");

// Se agregan los botones


txtTelefono.addCommand(cmdLlamar);
txtTelefono.addCommand(cmdSalir);
txtTelefono.setCommandListener(this);
}

protected void destroyApp(boolean arg0)


{
}

protected void pauseApp()


{
}

protected void startApp() throws MIDletStateChangeException


{
// Cuando se inicia la aplicación se muestra la ventana
dsp.setCurrent(txtTelefono);
}

public void commandAction(Command c, Displayable d)


{
// Se verifica el boton pulsado
if(c == cmdLlamar)
{
// Si es el boton Llamar, se realiza la llamada
// usando la funcion platformRequest
try
{
platformRequest("tel:" + txtTelefono.getString());
}
catch(Exception ex)
{}
}
else if (c == cmdSalir)
{
// Si es el boton Salir, se realiza la llamada
// usando las funciones destroyApp
// (que de momento esta vacia)
// y notifyDestroyed()
destroyApp(false);
notifyDestroyed();
}
}
}

CIBERTEC CARRERAS PROFESIONALES


34

Resumen

 Un MIDlet es una aplicación construida usando el perfil MIDP sobre la


configuración CLDC. Ha sido diseñada para ser descargada a través de Internet
vía OTA. Está conformada por dos archivos: el archivo jar (que contiene clases,
recursos y un manifiesto) y el descriptor o archivo jad. Tanto el manifiesto como el
descriptor contienen información sobre el contenido del MIDlet.

 El Gestor de aplicaciones es una aplicación instalada en el dispositivo móvil y es


quien controla todo el ciclo de vida del MIDlet, así como los estados por los que
pasa durante su ejecución.

 Para construir un MIDlet, el paso inicial es crear una clase que herede de la clase
MIDlet y sobrescribir los métodos startApp(), pauseApp() y destroyApp().

 La clase MIDlet tiene adicionalmente métodos para cambio de estado


(notifyDestroyed(), notifyPaused(), resumeRequest()), para obtener el estado de los
permisos (checkPermission()) y para leer propiedades del descriptor
(getAppProperty())

 Si desea saber más acerca de estos temas, puede consultar las siguientes
páginas.

 http://www.mailxmail.com/curso/informatica/j2me
 http://programacion.com/java/tutorial/ags_j2me/
 http://leo.ugr.es/J2ME/MIDP/enlaces.htm

 Referencia oficial de Java (en inglés)

 http://java.sun.com/javame/reference/apis/jsr118/

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 35

UNIDAD DE
APRENDIZAJE

2
SEMANA

INTERFACES DE USUARIO
LOGRO DE LA UNIDAD DE APRENDIZAJE

• Desarrolla aplicaciones basadas en las clases de la interfaz de alto nivel,


permitiendo la construcción de aplicaciones que realicen un correcto ingreso
de datos y presentación ordenada de información.

• Identifica las necesidades de las aplicaciones móviles comerciales y las aplica


mediante las clases ítems para un mejor manejo de la interfaz de usuario.

TEMARIO

• Introducción a las interfaces de usuario


• Manejo de la pantalla: Clases Display y Displayable
• Eventos del teclado: Clase Command / Interfaz CommandListener

ACTIVIDADES PROPUESTAS

• Crea la aplicación que se indica en el punto 4, que muestra una ventana con las
propiedades de la pantalla.

CIBERTEC CARRERAS PROFESIONALES


36

1. Introducción a las interfaces de usuario

Las interfaces de usuarios se refieren a las clases que van a gestionar el manejo
de la pantalla de los dispositivos móviles. Para ello, J2ME define 2 tipos de interfaces,
con las cuales el desarrollador puede generar las pantallas que interactuarán con el
usuario final.

1.1. Interfaz de alto nivel

Está diseñada para manejar componentes portables como cajas de texto,


botones, imágenes, formularios, etc. En esta interfaz, el usuario depende mucho
de la pantalla del dispositivo móvil, ya que éste define la forma en que serán
visualizados.

Figura 1.1. Ejemplo de interfaces de alto y bajo nivel

1.2. Interfaz de bajo nivel

Aquí se tiene control total de toda la pantalla del dispositivo móvil ya que se
dará un control completo sobre los recursos del dispositivo y podremos controlar
eventos de bajo nivel como, por ejemplo, el rastreo de pulsaciones de teclas.
Como contraparte, las aplicaciones construidas con esta interfaz son menos
portables. Generalmente, esta interfaz se utiliza para la creación de juegos donde
el control sobre lo que aparece por pantalla y las acciones del usuario juegan un
papel fundamental.

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 37

1.3. Diagrama de clases

Clases de la interfaz de alto nivel

Clases de interfaz de bajo nivel

Figura 1.2. Diagrama de clases de las interfaces de alto y bajo nivel

2. Manejo de la pantalla

2.1. Clase Display

2.1.1 Definición
Esta clase es la que se encarga de controlar y administrar la pantalla del
dispositivo móvil, proporcionando los métodos que permitirán obtener
propiedades de la pantalla o realizar algunos cambios de estado, por ejemplo,
saber la cantidad de colores de la pantalla, si la pantalla maneja colores o es
monocromática, tamaño, producir efectos de iluminación, etc.
La clase Display no posee un constructor. En lugar de eso, tiene la
función estática getDisplay() que permite obtener una referencia a la pantalla
actual.

2.1.2 Métodos
• getDisplay()

CIBERTEC CARRERAS PROFESIONALES


38

o Definición
public static Display getDisplay(MIDlet m)
o Descripción
Devuelve una referencia a la pantalla. La variable m es una
referencia al MIDlet que se está ejecutando en ese momento.
o Ejemplo:
/*Si estuvieramos dentro del codigo del MIDlet*/
Display dsp = Display.getDisplay(this)

• flashBacklight()
o Definición
public boolean flashBacklight(int duracion)
o Descripción
Provoca un efecto de flash en la pantalla. En el parámetro de
duración, se colocará la cantidad de segundos que durará el flash.
Dicha cantidad esta definida en milisegundo (cada 1000 representa
1 segundo).
• getBorderStyle()
o Definición
public int getBorderStyle(boolean luminosidad)
o Descripción
Devuelve el estilo de borde actual. El parámetro luminosidad
activará la luminosidad de la pantalla del dispositivo.
• getColor()
o Definición
public int getColor(int color)
o Descripción
Devuelve un color basado en el parámetro pasado, es decir, que
podremos colocar en el parámetro el valor correspondiente a la
propiedad que se desea conocer, por ejemplo el color de fondo,
letra, borde, etc.; los parámetros a usar son :
Display.COLOR_BACKGROUND
Display.COLOR_FOREGROUND
Display.COLOR_HIGHLIGHTED_BACKGROUND
Display.COLOR_HIGHLIGHTED_FOREGROUND
Display.COLOR_BORDER
Display.COLOR_HIGHLIGHTED_BORDER

• numColors()
o Definición
public int numColors()

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 39

o Descripción
Devuelve el número de colores aceptados por el dispositivo.
• setCurrent()
o Definición
public void setCurrent(Displayable d)
public void setCurrent(Alert a, Displayable d)
o Descripción
Establece la pantalla actual o la que se desea mostrar. En el
caso de la segunda definición, previamente, se mostrará la alerta
especificada
• vibrate()
o Definición
public boolean vibrate(int duracion)
o Descripción
Realiza la operación de hacer vibrar el dispositivo. El parámetro
recibirá la cantidad de tiempo que deba vibrar en milisegundos.
• getCurrent()
o Definición
public Displayable getCurrent()
o Descripción
Retornará la pantalla que se encuentre activa.
• isColor()
o Definición
public boolean isColor()
o Descripción
Retorna un valor lógico que indicará que la pantalla es a color o
monocromática.

2.2. Clase Displayable

2.2.1 Definición
Esta clase es la que se va encargar de controlar las diversas ventanas
que se podrán mostrar en la pantalla del dispositivo celular y sus diversas
propiedades. Es la clase base de la cual derivan las clases TextBox, Alert,
List y Form, de la interfaz de alto nivel; y Canvas, de la interfaz de bajo nivel.
Por lo tanto, todos los métodos que se especifican a continuación pueden ser
usados en dichas clases.

CIBERTEC CARRERAS PROFESIONALES


40

2.2.2 Métodos
• getHeight()
o Definición
public int getHeight()
o Descripción
Devuelve el alto de la pantalla en píxeles.
• getWidth()
o Definición
public int getWidth()
o Descripción
Devuelve el ancho de la pantalla en píxeles.
• setTicker()
o Definición
public void setTicker(Ticker t)
o Descripción
Establece un Ticker en la pantalla del dispositivo. Un Ticker es
un control similar una marquesina, es decir, un texto desplazándose
en la parte superor de la ventana. Ir a la sección correspondiente a
la semana 6 para una explicación mas detallada acerca de este
control.
• getTicker()
o Definición
public Ticker getTicker()
o Descripción
Devuelve el Ticker asignado a la pantalla del dispositivo
• setTitle()
o Definición
public void setTitle(String s)
o Descripción
Establece el título de la pantalla
• getTitle()
o Definición
public String getTitle()
o Descripción
Devuelve el título de la pantalla

• addCommand()
o Definición

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 41

public void addCommand(Command c)


o Descripción
Añade un objeto de tipo Command a la ventana. Un mismo
objeto Command puede agregarse a varias ventanas.
• removeCommand()
o Definición
public void removeCommand(Command c)
o Descripción
Elimina un objeto de tipo Command a la ventana.
• setCommandListener()
o Definición
public void setCommandListener(CommandListener cl)
o Descripción
Establece el objeto (conocido como listener) que capturará y
procesará los eventos que ocurran cuando se presione un objeto de
tipo Command. Para mas detalle, ver el punto 3 correspondiente a
los eventos del teclado.

3. Eventos del teclado

3.1. Consideraciones

Los eventos del teclado considerados son las pulsaciones de los botones
situados, generalmente, en la parte superior del dispositivo móvil. Estos botones
se indican en la ventana 2-1. Si se desea control las pulsaciones de otras teclas,
se debe usar la interfaz de bajo nivel.

CIBERTEC CARRERAS PROFESIONALES


42

Boton Derecho

Boton Izquierdo

Boton SELECT

Figura 2.1. Botones usados en la interfaz de alto nivel

La forma de implementar el manejo de los eventos de entrada es la siguiente:


1. Crear una clase que implemente la interfaz CommandListener y
sobrescribir el método commandAction;
2. Crear tantos objetos Command como botones se deseen utilizar;
3. Crear un objeto de una clase que derive de Displayable, es decir, de los
siguientes tipos: TextBox, Alert, List, Form o una clase derivada;
4. Agregarle, al objeto Displayable, los objetos Command correspondientes,
usando el método addCommand.
5. Agregarle, al objeto Displayable, la referencia al objeto que implementa la
interfaz CommandListener, usando el método setCommandListener.

3.2. Clase Command

3.2.1 Definición
Esta clase representa a los botones que se visualizan en la pantalla.
Debe ser agregado a un objeto Displayable usando el método addCommand.
Se puede agregar el mismo objeto Command a varios objetos Displayable.

3.2.2 Métodos
• Constructor()
o Definición
public Command(String label,int commandType,int priority)

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 43

o Descripción
Crea un comando. Los parámetros son:
o etiqueta: Nombre a mostrar del botón
o tipo: Tipo de Command a representrar
o prioridad: Prioridad que tendrá el botón en pantalla. Esto solo
aplica con botones que tengan el mismo tipo.
Los tipos de botones están definidos por valores de tipo entero y
pueden ser los siguientes:
o Command.BACK: Petición para volver a la pantalla anterior
o Command.CANCEL: Petición para cancelar la acción en curso
o Command.EXIT: Petición para salir de la aplicación
o Command.HELP: Petición para mostrar información de ayuda
o Command.ITEM: Petición para introducir el comando en un “item”
en la pantalla
o Command.OK: Aceptación de una acción por parte del usuario
o Command.STOP: Petición para parar una operación
• getCommandType()
o Definición
public int getCommandType()
o Descripción
Devuelve el tipo de Command.
• getLabel()
o Definición
public String getLabel()
o Descripción
Devuelve la etiqueta del Command.
• getPriority()
o Definición
public int getPriority()
o Descripción
Devuelve la prioridad del objeto Command.

3.3. Interfaz CommandListener

3.3.1 Definición
Esta interfaz se encarga de procesar los eventos que van a ser
generados por los objetos de tipo Command que se encuentra en la pantalla
del dispositivo móvil.

CIBERTEC CARRERAS PROFESIONALES


44

3.3.2 Métodos
• commandAction()
o Definición
protected abstract void commandAction(Command c,
Displayable d)
o Descripción
Este es único método definido para esta interfaz. Cada vez que
creemos una clase que implemente esta interfaz, debemos declarar
este método donde programaremos los procesos que se van a
realizar cuando se presione alguno de los botones. Este método
cuenta con 2 parámetros:
o c: representa al objeto Command que ha realizado la acción.
o d: representa la pantalla donde se encuentra el objeto
Command que realizó la acción. Recuerde que un objeto
Command puede ser agregado a diferentes ventanas.

4. Ejemplos

4.1. Aplicación DatosDisplay

4.1.1 Enunciado
Construir una aplicación que realice lo siguiente:
• Mostrar una ventana con el título “Configuración” y con las siguientes
propiedades de la pantalla:
o Estilo del borde cuando los controles están resaltados
o Estilo del borde cuando los controles no están resaltados
o Color de fondo
o Numero de colores
o Un valor que indique si soporta colores o no.
o Alto de la pantalla
o Ancho de la pantalla
• Tendrá un botón para salir de la aplicación
• La figura 4-1 indica como deberá verse la pantalla.

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 45

Figura 4-1. Pantalla inicial de la aplicación DatosDisplay

4.1.2 Código
/*
*Importar espacios de nombres
**/
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

public class DatosDisplay extends MIDlet implements CommandListener


{
/*
* Variables a utilizar
**/
private Command botonSalir; // Command: Para manejar los eventos de entrada
private Display pantalla; // Display: Para manipular la pantalla
private Form formulario; // Form: Clase que hereda de Displayable

public DatosDisplay()
{
/*
Obtiene una referencia de la pantalla, para poder colocar los
diferentes objetos gráficos
*/
pantalla = Display.getDisplay(this);
botonSalir = new Command("Salir", Command.EXIT, 2);
formulario = new Form("Configuracion");

/*
* Inicializacion de variables de tipo StringItem con datos diversos
**/
// Estilo del borte de los controles cuando estan resaltados
StringItem borde = new StringItem("Borde1:",
String.valueOf(pantalla.getBorderStyle(true)));

// Estilo del borte de los controles cuando no estan resaltados


StringItem borde2 = new StringItem("Borde2:",
String.valueOf(pantalla.getBorderStyle(false)));

// Color usado para el fondo de la pantalla


int colorFondo = pantalla.getColor(Display.COLOR_BACKGROUND);
StringItem color = new StringItem("Color de fondo: ",
Integer.toHexString(colorFondo).toUpperCase());

CIBERTEC CARRERAS PROFESIONALES


46

/*NOTA: La funcion getColor puede recibir otros parametros constantes


* Cuando la pantalla no está iluminada
*Display.COLOR_BACKGROUND: Color de fondo
*Display.COLOR_BORDER: Color del borde
*Display.COLOR_FOREGROUND: Color de la letra

* Cuando la pantalla está iluminada


*Display.COLOR_HIGHLIGHTED_BACKGROUND: Color de fondo
*Display.COLOR_HIGHLIGHTED_BORDER: Color del borde
*Display.COLOR_HIGHLIGHTED_FOREGROUND: Color de la letra
**/
// Numero de colores en total que soporta la pantalla
StringItem numColores = new StringItem("Numero de colores:",
String.valueOf(pantalla.numColors()));

// Valor que nos indica si la pantalla soporta colores o no


StringItem esColor = new StringItem("¿Soporta colores?:",
String.valueOf(((pantalla.isColor())? "Si": "No")));

// Altura de la pantalla
StringItem altura = new StringItem("Altura:",
String.valueOf(formulario.getHeight()));

// Ancho de la pantalla
StringItem ancho = new StringItem("Ancho:",
String.valueOf(formulario.getWidth()));

/*
*Adicion de los objetos de tipo StringItem con los datos
**/
formulario.append(borde);
formulario.append(borde2);
formulario.append(color);
formulario.append(numColores);
formulario.append(esColor);
formulario.append(altura);
formulario.append(ancho);

/*
* Adicion del comando e inicio de la captura de eventos de entrada
**/
formulario.addCommand(botonSalir);
formulario.setCommandListener(this);
}

public void startApp() throws MIDletStateChangeException


{
/*
*Inicio de la aplicacion
**/
// Se establece a formulario como la pantalla inicial
pantalla.setCurrent(formulario);
}

public void pauseApp()


{
}

public void destroyApp(boolean unconditional)


{
}

public void commandAction(Command c, Displayable d)


{
/*
* Se ha pulsado un boton
**/

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 47

if (c == botonSalir)
{
// Si es el boton Salir, se realiza la llamada
// usando las funciones destroyApp
// (que de momento esta vacia)
// y notifyDestroyed()
destroyApp(false);
notifyDestroyed();
}
}
}

CIBERTEC CARRERAS PROFESIONALES


48

Resumen

 La clase Display se encarga de manejar la pantalla del dispositivo móvil. Usando


sus métodos podemos, principalmente, mostrar ventanas y obtener algunas
propiedades.

 La clase Displayable es la clase de la cual derivan todas las clases que


representan a ventanas, tales como TextBox, Alert, Form, List y Canvas. Usando
sus métodos, podemos obtener y modificar algunas propiedades, así como
procesar los eventos de entrada. Esto ultimo se realiza en combinación con la
clase Command y la interfaz CommandListener

 Para implementar los eventos de pulsación de teclas, se debe usar la clase


Command, que representa un botón; y la interfaz CommandListener, que
proporciona el método donde se realiza el procesamiento.

 Si desea saber más acerca de estos temas, puede consultar las siguientes
páginas.

 http://www.mailxmail.com/curso/informatica/j2me
 http://programacion.com/java/tutorial/ags_j2me/
 http://leo.ugr.es/J2ME/MIDP/enlaces.htm

 Referencia oficial de Java (en inglés)

 http://java.sun.com/javame/reference/apis/jsr118/

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 49

UNIDAD DE
APRENDIZAJE

2
SEMANA

MANEJO DE VENTANAS
LOGRO DE LA UNIDAD DE APRENDIZAJE

• Desarrolla aplicaciones basadas en las clases de la interfaz de alto nivel,


permitiendo la construcción de aplicaciones que realicen un correcto ingreso
de datos y presentación ordenada de información.

• Identifica las necesidades de las aplicaciones móviles comerciales y las aplica


mediante las clases ítems para un mejor manejo de la interfaz de usuario.

TEMARIO

• Visualización de datos: Clase Alert


• Ingreso de datos: Clase TextBox

ACTIVIDADES PROPUESTAS

• Crea la aplicación indicada en el punto 3: Aplicación que realiza un inicio de


sesión (ingreso de usuario y clave)

CIBERTEC CARRERAS PROFESIONALES


50

Visualización de datos: Clase Alert


4.2. Definición

Esta clase se utiliza para mostrar mensajes en toda la pantalla del dispositivo
móvil. Tiene un tiempo de visualización (timeout), luego de lo cual desaparece
(por defecto es 2000 milisegundos), así como un tipo que define su
comportamiento.

4.3. Métodos

4.3.1 Constructor
• Definición
public Alert(String titulo, String mensaje, Image imagen,
AlertType tipoAlerta)
public Alert(String titulo)

• Descripción
Permite construir un control de tipo Alert. Sus parámetros son:
o título: Título a mostrar en la parte superior de la pantalla
o mensaje: Mensaje que se mostrará
o imagen: Imagen que se mostrará. Si no se desea mostrar
ninguna imagen el valor debe ser null.
o tipoAlerta: Es un entero que define el comportamiento que
tendrá el Alert. Este comportamiento depende del dispositivo y
puede consistir en mostrar un sonido, realizar una vibración, etc.
Los valores posibles se indican en la tabla 1-1.

Constante Descripción
AlertType.ALARM Aviso de una petición previa
AlertType.CONFIRMATION Indica la aceptación de una acción
AlertType.ERROR Indica que ha ocurrido un error
AlertType.INFO Indica algún tipo de información
AlertType.WARNING Indica una advertencia
Tabla 1-1. Tipos de Alert

• Ejemplo
El siguiente fragmento crea un Alert de tipo INFO, con el título
“Éxito” y el mensaje “Proceso culminó con éxito”

private Alert alt = new Alert(“Exito”,


“Proceso culmino con exito”, null, AlertType.INFO);

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 51

El siguiente fragmento crea un Alert con el título “Éxito” y el resto de


parámetros por defecto, esto indica
private Alert alt = new Alert(“Exito”);

4.3.2 getImage()
• Definición
public Image getImage()

• Descripción
Devuelve la imagen configurada para la alerta.

4.3.3 getString()
• Definición
public String getString()

• Descripción
Devuelve el mensaje configurado para la alerta.

4.3.4 getString()
• Definición
public String getString()

• Descripción
Devuelve el mensaje configurado para la alerta.

4.3.5 getTimeout()
• Definición
public int getTimeout()

• Descripción
Devuelve el tiempo que se mostrará la alerta (en milisegundos).

4.3.6 getType()
• Definición
public AlertType getType()

• Descripción
Devuelve el tipo de alerta definido para un objeto Alert.

4.3.7 setImage()
• Definición
public void setImage(Image img)

• Descripción
Define la imagen a mostrar en un objeto Alert.

CIBERTEC CARRERAS PROFESIONALES


52

4.3.8 setString()
• Definición
public void setString(String str)

• Descripción
Define el mensaje a mostrar en un objeto Alert.

4.3.9 setTimeout()
• Definición
public void setTimeout(int timeout)

• Descripción
Define el tiempo que se mostrará un objeto Alert (en milisegundos).
Se puede usar la constante Alert.FOREVER para indicar que el Alert no
va a desaparecer automáticamente.

4.3.10 setType()
• Definición
public void setType(AlertType tipo)

• Descripción
Define el tipo de alerta que se mostrará.

5. Ingreso de datos: Clase TextBox

5.1. Definición

Esta clase se encarga de representar a una caja de texto para el ingreso de


datos de diferente tipo. Este control ocupará toda la pantalla del dispositivo móvil.

5.2. Métodos

5.2.1 Constructor
• Definición
public TextBox(String titulo, String textoInicial,
int longitudMaxima, int filtros)

• Descripción
Permite construir un control de tipo TextBox. Sus parámetros son:
o Título: Título a mostrar en la parte superior de la pantalla.
o textoInicial: Texto mostrado al inicio.
o longitudMaxima: Longitud máxima de caracteres
o filtros: Es un entero que define que tipo de texto se va a
ingresar. Este entero puede ser un filtro restrictivo solo (ver tabla

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 53

2-1) o combinado con uno o varios filtros opcionales (ver tabla 2-


2) con el operador barra vertical (“|”).

Constante Descripción
TextField.ANY Permite el ingreso de cualquier caracter.
TextField.NUMERIC Permite el ingreso de cualquier número entero.
TextField.PHONENUMBER Permite caracteres válidos sólo para números de teléfono.
TextField.EMAILADDR Permite caracteres válidos para direcciones de correo.
TextField.DECIMAL Permite el ingreso de cualquier número decimal.
TextField.URL Permite caracteres válidos sólo para direcciones URL.
Tabla 2-1. Filtros restrictivos de un TextBox’

Constante Descripción
TextField.PASSWORD Muestra asteriscos en vez del texto realmente ingresado.
TextField.UNEDITABLE No permite la edición del texto.
TextField.SENSITIVE Es un dato sensible y no debe ser guardado en memoria.
TextField.NON_PREDICTIVE No usar el mecanismo de texto predictivo.
TextField.INITIAL_CAPS_WORD Cada palabra comenzará en mayúsculas.
TextField.INITIAL_CAPS_SENTENCE Cada oración comenzará con mayúsculas
Tabla 2-2. Filtros opcionales de un TextBox

• Ejemplo
El siguiente fragmento crea una ventana de texto que permite el
ingreso de una contraseña numérica de máximo 10 dígitos e indica que
es un dato sensible.
private TextBox txt = new TextBox(“Clave”, “”, 10,
TextField.NUMERIC | TextField.PASSWORD | TextField.SENSITIVE);

5.2.2 delete()
• Definición
public void delete(int desplazamiento, int longitud)

• Descripción
Borra caracteres del TextBox, donde:
o desplazamiento: Posición inicial a borrar
o longitud: Cantidad de caracteres a eliminar

5.2.3 getCaretPosition()
• Definición
public int getCaretPosition()

• Descripción
Devuelve la posición del cursor en pantalla.

CIBERTEC CARRERAS PROFESIONALES


54

5.2.4 getChars()
• Definición
public int getChars(char [] datos)

• Descripción
Copia el contenido del TextBox en el arreglo “datos” y devuelve el
número de caracteres copiados.

5.2.5 getMaxSize()
• Definición
public int getMaxSize()

• Descripción
Devuelve el tamaño máximo del TextBox.

5.2.6 getString()
• Definición
public String getString()

• Descripción
Devuelve el contenido del TextBox.

5.2.7 insert()
• Definición
public void insert(char[] datos, int des, int long, int pos)
public void insert(char[] datos, int pos)

• Descripción
Inserta el contenido del arreglo datos en el TextBox.
o datos: arreglo a copiar
o des: posición del arreglo desde donde se copiará
o long: cantidad de caracteres que se copiarán
o pos: posición en el TextBox donde se colocarán los caracteres

5.2.8 setChars()
• Definición
public void setChars(char[] datos, int des, int long)

• Descripción
Reemplaza el contenido del TextBox por el arreglo “datos”.
o datos: arreglo a copiar
o des: posición del arreglo desde donde se copiará
o long: cantidad de caracteres que se copiarán

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 55

5.2.9 setMaxSize()
• Definición
public int setMaxSize(int capacidad)

• Descripción
Establece el tamaño máximo del TextBox. Devuelve el tamaño que
realmente se le ha asignado.

5.2.10 setString()
• Definición
public void setString(String texto)

• Descripción
Establece el contenido del TextBox.

5.2.11 size()
• Definición
public int size()

• Descripción
Devuelve el número de caracteres actualmente ingresados.

6. Ejemplos

6.1. Aplicación InicioSesion

6.1.1 Enunciado
Construir una aplicación que realice lo siguiente:
• Mostrar una ventana inicial de bienvenida por 2 segundos.
• Luego mostrar una ventana que permita el ingreso de un usuario. Esta
ventana tendrá botones para salir y aceptar.
• Si se pulsa aceptar, mostrar una ventana que permita el ingreso de una
contraseña. Esta ventana tendrá botones para salir, volver y aceptar.
• Si se pulsa aceptar, verificar que el usuario y contraseña sean iguales a
las propiedades “usuario” y “clave” del descriptor. Se deben crear
previamente dichas propiedades. Mostrar una ventana de éxito o error
según sea el caso.
• La figura 3-1 indica como deberá verse la pantalla.

CIBERTEC CARRERAS PROFESIONALES


56

Figura 3-1. Pantallas de la aplicación InicioSesion

• Ejemplo de cómo debería quedar el descriptor (InicioSesion.jad):


MIDlet-1: InicioSesion, , InicioSesion
MIDlet-Jar-URL: InicioSesion.jar
MIDlet-Name: InicioSesion Midlet Suite
MIDlet-Vendor: Midlet Suite Vendor
MIDlet-Version: 1.0.0
MicroEdition-Configuration: CLDC-1.1
MicroEdition-Profile: MIDP-2.1
Usuario: admin
Clave: 123

6.1.2 Código

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.Form;
import javax.microedition.lcdui.StringItem;
import javax.microedition.lcdui.TextBox;
import javax.microedition.lcdui.TextField;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;

public class InicioSesion extends MIDlet implements CommandListener {

// Obtener referencia de la pantalla


private Display dsp = Display.getDisplay(this);

// Creacion del Alert de bienvenida


private Alert altBienvenida = new Alert("", "Bienvenido", null,
AlertType.INFO);
// Creacion del TextBox para el ingreso del usuario
private TextBox txtUsuario = new TextBox("Ingrese usuario", "", 10,
TextField.ANY);
// Creacion del TextBox para el ingreso de clave
private TextBox txtClave = new TextBox("Ingrese clave", "", 10,
TextField.ANY | TextField.PASSWORD);

// Creacion del Alert para los mensajes de error


private Alert altError = new Alert("Error", "", null, AlertType.ERROR);

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 57

// Creacion de botones
private Command cmdSalir = new Command("Salir", Command.EXIT, 2);
private Command cmdVolver = new Command("Volver", Command.BACK, 2);
private Command cmdAceptar = new Command("Aceptar", Command.OK, 2);

public InicioSesion()
{
// Agregar botones e indicar la clase que procesara los eventos
txtUsuario.addCommand(cmdSalir);
txtUsuario.addCommand(cmdAceptar);
txtUsuario.setCommandListener(this);

// Agregar botones e indicar la clase que procesara los eventos


txtClave.addCommand(cmdSalir);
txtClave.addCommand(cmdAceptar);
txtClave.addCommand(cmdVolver);
txtClave.setCommandListener(this);
}

protected void destroyApp(boolean arg0)


{
}

protected void pauseApp()


{
}

protected void startApp() throws MIDletStateChangeException


{
// Mostrar el Alert de bienvenida y luego el TextBox de usuario
dsp.setCurrent(altBienvenida, txtUsuario);
}

public void commandAction(Command c, Displayable d) {


// Se pulso un boton
if(c == cmdSalir)
{
// Si el boton es salir, salir de la aplicacion
destroyApp(false);
notifyDestroyed();
}
else if(c == cmdAceptar)
{
// Si el boton es Aceptar, verificar cual es la ventana
if(d == txtUsuario)
{
// Si la ventana es la de Usuario, validar el texto ingresado
// Si el texto es correcto, ir a la ventana de Clave
if(!txtUsuario.getString().equals("") &&
txtUsuario.getString().equals(getAppProperty("Usuario")))
dsp.setCurrent(txtClave);
else
{
// Si el texto no es correcto, mostrar un mensaje de error
altError.setString("Usuario no valido");
dsp.setCurrent(altError);
}
}
else if (d == txtClave)
{
// Si la ventana es la de Clave, validar el texto ingresado
// Si el texto es correcto, mostrar los datos en un Alert
if(!txtClave.getString().equals("")
&& txtClave.getString().equals(getAppProperty("Clave")))
{
// Crear una cadena con el usuario y la clave
String strMensaje = "Ingreso correcto"
+ "\n\rUsuario: " + txtUsuario.getString()

CIBERTEC CARRERAS PROFESIONALES


58

+ "\n\rClave: " + txtClave.getString();


Alert altIngresoCorrecto = new Alert("Exito", strMensaje,
null, AlertType.INFO);
// Cambiarle el timeout a FOREVER, para que no desaparezca
altIngresoCorrecto.setTimeout(Alert.FOREVER);
// Mostrar Alert
dsp.setCurrent(altIngresoCorrecto);
}
else
{
// Si el texto no es correcto, mostrar un mensaje de error
altError.setString("Usuario no valido");
dsp.setCurrent(altError);
}
}
}
else if(c == cmdVolver)
{
// Si el boton es Volver, ir a la ventana de Usuario
dsp.setCurrent(txtUsuario);
}
}
}

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 59

Resumen

 La clase Alert define una ventana que muestra un mensaje, y adicionalmente


puede tener una imagen y un tiempo de visualización (timeout).

 La clase TextBox define una ventana que pide el ingreso de un dato, el cual puede
ser de diferentes tipos.

 Si desea saber más acerca de estos temas, puede consultar las siguientes
páginas.

 http://www.mailxmail.com/curso/informatica/j2me
 http://programacion.com/java/tutorial/ags_j2me/
 http://leo.ugr.es/J2ME/MIDP/enlaces.htm

 Referencia oficial de Java (en inglés)

 http://java.sun.com/javame/reference/apis/jsr118/

CIBERTEC CARRERAS PROFESIONALES


60

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 61

UNIDAD DE
APRENDIZAJE

2
SEMANA

MANEJO DE LISTAS
LOGRO DE LA UNIDAD DE APRENDIZAJE

• Desarrolla aplicaciones basadas en las clases de la interfaz de alto nivel,


permitiendo la construcción de aplicaciones que realicen un correcto ingreso
de datos y presentación ordenada de información.

• Identifica las necesidades de las aplicaciones móviles comerciales y las aplica


mediante las clases ítems para un mejor manejo de la interfaz de usuario.

TEMARIO

• Selección de datos: Clase List

ACTIVIDADES PROPUESTAS

• Crea la aplicación indicada en el punto 3, que muestra como realizar un menú.

CIBERTEC CARRERAS PROFESIONALES


62

1. Selección de datos: Clase List

1.1. Definición

Esta clase nos permite utilizar diferente tipos de lista de opciones en la pantalla
del dispositivo móvil. Puede ser utilizado como una lista de selección, ya sea
única o múltiple, o para la elaboración de un menú con el que interactuará el
usuario de la aplicación. Sus elementos se identifican por un índice o posición que
comienza en cero (0).

1.2. Métodos

1.2.1 Constructor
• Definición
public List(String titulo, int tipo)
public List(String titulo, int tipo, String[] elementos,
Image[] imagenes)

• Descripción
Permite construir un control de tipo List. Sus parámetros son:
o Título: Título a mostrar en la parte superior de la pantalla
o tipo: Dato entero que indica el tipo de lista. Se pueden usar las
constantes de la tabla 1-1
o elementos: arreglo conteniendo la lista inicial de elementos
o imágenes: arreglo del mismo tamaño de “elementos”,
conteniendo sus imágenes, o null si no existieran imágenes

Constante Descripción
List.EXCLUSIVE Permite la selección de sólo un elemento a la vez.
List.MULTIPLE Permite la selección de varios elementos a la vez.
List.IMPLICIT Permite la selección de sólo un elemento a la vez y genera un evento.
Se utiliza para la creación de menús
Tabla 1-1. Tipos de Lista

• Ejemplo
El siguiente fragmento crea una lista exclusiva con 3 elementos
private String astrTipoDoc[] = {“Partida”, “DNI”, “Pasaporte”};
private List lst = new List(“Tipo Documento”, List.EXCLUSIVE,
astrTipoDoc, null);
El siguiente fragmento crea una lista implícita con 3 elementos
private String astrOpciones[] = {“Ingreso”, “Reportes”, “Salir”};
private List lst = new List(“Opciones”, List.IMPLICIT,
astrOpciones, null);

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 63

El siguiente fragmento crea una lista multiple sin elementos


private List lst = new List(“Pasatiempos”, List.MULTIPLE);

1.2.2 append()
• Definición
public int append(String texto, Image img)

• Descripción
Añade un elemento al final de la lista y devuelve su índice en la lista.
o texto: Elemento a agregar
o img: Imagen del elemento a agregar o null si no existiera

1.2.3 delete()
• Definición
public void delete(int pos)

• Descripción
Elimina el elemento en la posición que se especifica.

1.2.4 deleteAll()
• Definición
public void deleteAll()

• Descripción
Elimina todos los elementos de la lista.

1.2.5 insert()
• Definición
public void insert(int pos, String texto, Image img)

• Descripción
Inserta un elemento en la posición indicada. Todos los elementos
posteriores corren una posición.
o pos: Posición del elemento a agregar
o texto: Elemento a agregar
o img: Imagen del elemento a agregar o null si no existiera

1.2.6 getFont()
• Definición
public Font getFont(int pos)

• Descripción
Devuelve la fuente del elemento en la posición indicada por “pos”.

CIBERTEC CARRERAS PROFESIONALES


64

En el capítulo 6 se trata a mayor detalle los tipos de letra que se


pueden manejar desde J2ME.

1.2.7 getImage()
• Definición
public Image getImage(int pos)

• Descripción
Devuelve la imagen del elemento en la posición indicada por “pos”.

1.2.8 getSelectedFlags()
• Definición
public int getSelectedFlags(boolean [] estado)

• Descripción
Llena el arreglo “estado” con el estado de los elementos (true si
fueron seleccionados, false si no) y devuelve el número de elementos
seleccionados. Este método se usa para las listas múltiples.

1.2.9 getSelectedIndex()
• Definición
public int getSelectedIndex()

• Descripción
Obtiene el índice del elemento seleccionado. Este método se usa
para las listas exclusiva e implícita.

1.2.10 getString()
• Definición
public String getString(int pos)

• Descripción
Obtiene el texto del elemento señalado por el parámetro “pos”.

1.2.11 isSelected()
• Definición
public boolean isSelected(int pos)

• Descripción
Devuelve un valor que indica si el elemento señalado por el
parámetro “pos” está seleccionado.

1.2.12 set()
• Definición
public void set(int pos, String texto, Image img)

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 65

• Descripción
Modifica un elemento ya existente en la posición indicada.
o pos: Posición del elemento a agregar
o texto: Elemento a agregar
o img: Imagen del elemento a agregar o null si no existiera

1.2.13 setDefaultCommand()
• Definición
public void setDefaultCommand(Command cmd)

• Descripción
Establece el botón que se ejecutará cuando se pulse el botón
SELECT. Se usa al crear un menú con una lista implícita.

1.2.14 setFitPolicy()
• Definición
public void setFitPolicy(int estilo)

• Descripción
Modifica la forma cómo se muestran los elementos con texto muy
largo. El parámetro estilo es un entero que puede usar las constantes
indicadas en la tabla 1-2.

Constante Descripción
List.TEXT_WRAP_OFF Textos que sobrepasan la pantalla son cortados, de manera que todos
los elementos ocupan un renglón.
List.TEXT_WRAP_ON Textos que sobrepasan la pantalla no son cortados, de manera que
los elementos se ven completos en más de un renglón.
List.TEXT_WRAP_DEFAULT Textos que sobrepasan la pantalla se muestran de acuerdo como se
haya definido por defecto en el dispositivo.
Tabla 1-2. Valores para usar con el método serFitPolicy

1.2.15 setFont()
• Definición
public void setFont(int pos, Font fuente)

• Descripción
Cambia la fuente del elemento en la posición “pos” por la fuente
indicada en el parámetro “fuente”. En el capítulo 6 se trata a mayor
detalle los tipos de letra que se pueden manejar desde J2ME.

1.2.16 setSelectedFlags()
• Definición
public void setSelectedFlags(Boolean [] nuevoEstado)

CIBERTEC CARRERAS PROFESIONALES


66

• Descripción
Cambia el estado de los elementos (true si fueron seleccionados,
false si no fuese así) por el que se indica en el arreglo “nuevoEstado”.
Se usa en listas múltiples.

1.2.17 setSelectedIndex()
• Definición
public void setSelectedIndex(int pos, boolean seleccionado)

• Descripción
Cambia el estado del elemento indicado en la posición “pos” por el
que se indica en el parámetro “seleccionado”.

1.2.18 size()
• Definición
public int size()

• Descripción
Devuelve el número de elementos de la lista.

2. Creación de menús

2.1. Consideraciones

Con una lista implícita se pueden crear menús de usuario. Para esto, la lista
tiene un botón implícito llamado SELECT_COMMAND que genera un evento
cuando se pulsa el botón SELECT sobre uno de sus elementos. Este evento es
procesado por el método commandAction como si fuera un objeto Command
convencional.
Eventualmente, se podría dejar de usar el botón por defecto y usar un objeto
Command creado para esto. En ese caso, se debe agregar el botón a la lista con
el método addCommand y establecerlo como botón por defecto con el método
setDefaultCommand.

2.2. Pasos a seguir

1. Crear una lista implícita con los elementos correspondientes a las opciones
del menú
private String astrOpciones[] = {“Ingreso”, “Reportes”, “Salir”};
private List lst = new List(“Opciones”, List.IMPLICIT,
astrOpciones, null);

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 67

2. Indicar la clase que procesará sus eventos de entrada


/* Se asume que esta clase ha implementado la interfaz
CommandListener */
lst.setCommandListener(this);

3. En el método commandAction, verificar si el botón pulsado es el correcto y


el objeto Displayable es la lista que se ha creado.

public void commandAction(Command c, Displayable d)


{
if(c == List.SELECT_COMMAND && d == lst)
{
/*Aca va la lógica del menú*/
}
}

4. Implementar la lógica que se desee para dicho menú


public void commandAction(Command c, Displayable d)
{
if(c == List.SELECT_COMMAND && d == lst)
{
/*Verificar que elemento se selecciono
usando el método getSelectedIndex()*/

if(lst.getSelectedIndex() == 0)
{
// Poner la logica correspondiente a la opcion 0
}
}
}

3. Ejemplos

3.1. Aplicación MenuInicial

3.1.1 Enunciado
Construir una aplicación que realice lo siguiente:
• Mostrar un menú que, al seleccionar una opción, muestre, en un Alert, un
mensaje
• Adicionalmente, debe tener un botón “salir”.
• La figura 3-1 indica cómo deberá verse la pantalla.

CIBERTEC CARRERAS PROFESIONALES


68

Tabla 3-1. Ventanas de la aplicación MenuInicial

3.1.2 Código

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

public class MenuInicial extends MIDlet implements CommandListener


{
private Command salir; //Declaracion de Variables
private Display pantalla;
private List menu;
private Alert alerta;

public MenuInicial()
{
pantalla = Display.getDisplay(this); //Creacion de pantallas

menu = new List("Menú",List.IMPLICIT);

menu.insert(0,"Opcion3",null);
menu.insert(0,"Opcion2",null);
menu.insert(0,"Opcion1",null);

alerta=new Alert("Menu Principal");


alerta.setTimeout(3000);

salir = new Command("Salir",Command.EXIT,1);

menu.addCommand(salir);
menu.setCommandListener(this);
}

public void startApp()


{
pantalla.setCurrent(menu); // Pongo el menu en pantalla
}

public void pauseApp()


{
}

public void destroyApp(boolean unconditional)


{
}

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 69

public void commandAction(Command c, Displayable d)


{
if (c == List.SELECT_COMMAND && d == menu)
{ // Si selecciono opcion del menu
switch(menu.getSelectedIndex())
{
case 0:
alerta.setString("Eligio la Opcion 1");
pantalla.setCurrent(alerta);
break;
case 1:
alerta.setString("Eligio la Opcion 2");
pantalla.setCurrent(alerta);
break;
case 2:
alerta.setString("Eligio la Opcion 3");
pantalla.setCurrent(alerta);
break;
}
}
else if (c == salir)
{ // Selecciono salir de la aplicacion
destroyApp(false);
notifyDestroyed();
}
}
}

CIBERTEC CARRERAS PROFESIONALES


70

Resumen

 La clase List se usa para mostrar una lista de selección de datos. Dicha selección
puede ser única o múltiple. También, se utiliza para la creación de menús.

 Si desea saber más acerca de estos temas, puede consultar las siguientes
páginas.

 http://www.mailxmail.com/curso/informatica/j2me
 http://programacion.com/java/tutorial/ags_j2me/
 http://leo.ugr.es/J2ME/MIDP/enlaces.htm

 Referencia oficial de Java (en inglés)

 http://java.sun.com/javame/reference/apis/jsr118/

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 71

UNIDAD DE
APRENDIZAJE

2
SEMANA

CONTROLES ADICIONALES
LOGRO DE LA UNIDAD DE APRENDIZAJE

• Desarrolla aplicaciones basadas en las clases de la interfaz de alto nivel,


permitiendo la construcción de aplicaciones que realicen un correcto ingreso
de datos y presentación ordenada de información.

• Identifica las necesidades de las aplicaciones móviles comerciales y las aplica


mediante las clases ítems para un mejor manejo de la interfaz de usuario.

TEMARIO

• Clases adicionales: Image, Font, Ticker

ACTIVIDADES PROPUESTAS

• Realiza la actividad del punto 4 que ilustra en el uso de estos controles.

CIBERTEC CARRERAS PROFESIONALES


72

1. Clase Image

1.1. Definición

Esta clase nos permite visualizar una imagen. El formato estándar para los
archivos de imagen de los dispositivos móviles es PNG, aunque dependiendo del
equipo se puede trabajar con otros formatos conocidos, como GIF, JPG, etc. No
existe un constructor para una imagen, en lugar de eso se usa el método estático
createImage. Sólo algunas clases, como Alert, List o Form, pueden mostrar una
imagen.

1.2. Métodos

1.2.1 createImage()
• Definición
public static createImage(String archivo)

• Descripción
Crea una imagen con el archivo señalado por el parámetro “archivo”.
Los archivos de imagen deben estar guardados en la carpeta “res” del
proyecto. Dicha carpeta debe tratarse como la carpeta raíz. El método
puede lanzar una excepción, por lo que debe estar dentro de un bloque
try – catch.
• Ejemplo
El siguiente fragmento, crea una imagen con el archivo imagen.png,
el cual se encuentra en la carpeta res.
private Image img = null;
try {
img = Image.createImage(“/imagen.png”);
}
catch(Exception ex) {
}

2. CLASE FONT

2.1. Definición

Los tipos de letra en J2ME son limitados y esta clase nos permite definir uno.
No existe un constructor para una fuente. En lugar de eso, se usa el método
estático getFont. Sólo algunas clases, como List, pueden modificar el tipo de letra
de sus elementos.

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 73

2.2. Métodos

2.2.1 getFont()
• Definición
public static getFont(int tipo, int estilo, int tamano)

• Descripción
Crea un tipo de letra con los parámetros indicados. Estos datos son
enteros y están representados por las constantes de las tablas 2-1, 2-2
y 2-3.
• Ejemplo
El siguiente fragmento crea un tipo de letra proporcional, itálica y
pequeña.
private Font fnt = Font.getFont(Font.FACE_PROPORTIONAL,
Font.STYLE_ITALIC, Font.SIZE_SMALL);

Constante Descripción
Font.FACE_MONOSPACE3 Los caracteres tienen el mismo ancho.
Font.FACE_PROPORTIONAL Las dimensiones de los caracteres son proporcionales.
Font.FACE_SYSTEM Tipo de letra definido para el sistema.
Tabla 2-1. Constantes de tipo de letra

Constante Descripción
Font.STYLE_BOLD Resaltado o en “negrita”
Font.STYLE_ITALIC Cursiva o itálica
Font.STYLE_PLAIN Normal
Font.STYLE_UNDERLINED Subrayado
Tabla 2-2. Constantes de estilo de letra

Constante Descripción
Font.SIZE_LARGE Grande
Font.SIZE_MEDIUM Mediano
Font.SIZE_SMALL Pequeño
Tabla 2-3. Constantes de tamaño de letra

3. Clase Ticker

3.1. Definición

Un objeto Ticker define una especie de marquesina que aparecerá en la parte


superior de la pantalla. Todos los controles que heredan de Displayable pueden
mostrar un Ticker. Para esto, se debe usar el método setTicker (ver el punto 2.2
del capítulo 3).

CIBERTEC CARRERAS PROFESIONALES


74

3.2. Métodos

3.2.1 Constructor
• Definición
public Ticker(String texto)

• Descripción
Permite construir un Ticker con el texto indicado en el parámetro.
• Ejemplo
El siguiente fragmento, crea un Ticker con el texto “Bienvenido”.
private Ticker ticker = new Ticker(“Bienvenido”);

3.2.2 getString()
• Definición
public String getString()

• Descripción
Devuelve el texto del Ticker.

3.2.3 setString()
• Definición
public void setString(String texto)

• Descripción
Cambia el texto del Ticker.

4. Ejemplos

4.1. Aplicación MenuInicial

4.1.1 Enunciado
Modificar la aplicación del capítulo anterior para que realice lo siguiente:
• Mostrar una ventana inicial con una imagen
• Agregar un Ticker al menú con el texto “Seleccione opción”
• Modificar los tipos de letra de las opciones del menú
• La figura 4-1 indica como deberá verse la pantalla.

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 75

Figura 4-1. Ventanas de la aplicación MenuInicial

4.1.2 Código

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

public class MenuInicial extends MIDlet implements CommandListener


{
private Command salir; //Declaracion de Variables
private Display pantalla;
private List menu;
private Alert alerta;

// Ventana de bienvenida
private Alert bienvenida;
// Imagen
private Image imgDuke;

public MenuInicial()
{
pantalla = Display.getDisplay(this); //Creacion de pantallas

menu = new List("Menú",List.IMPLICIT);

menu.insert(0,"Opcion3",null);
menu.insert(0,"Opcion2",null);
menu.insert(0,"Opcion1",null);

// Creación de fuentes
Font fnt0 = Font.getFont(Font.FACE_PROPORTIONAL, Font.STYLE_BOLD,
Font.SIZE_SMALL);
Font fnt1 = Font.getFont(Font.FACE_PROPORTIONAL, Font.STYLE_BOLD,
Font.SIZE_MEDIUM);
Font fnt2 = Font.getFont(Font.FACE_PROPORTIONAL, Font.STYLE_BOLD,
Font.SIZE_LARGE);
// Cambiar las fuentes del menú
menu.setFont(0, fnt0);
menu.setFont(1, fnt1);
menu.setFont(2, fnt2);

// Creación del Ticker


Ticker ticker = new Ticker("Seleccione opcion");
// Mostrar el Ticker
menu.setTicker(ticker);

alerta=new Alert("Menu Principal");


alerta.setTimeout(3000);

CIBERTEC CARRERAS PROFESIONALES


76

// Crear la imagen
try
{
imgDuke = Image.createImage("/duke.png");
}
catch(Exception ex)
{
imgDuke = null;
}

// Crear el alert y agregarle la imagen


bienvenida=new Alert("Bienvenido");
bienvenida.setTimeout(3000);
bienvenida.setImage(imgDuke);

salir = new Command("Salir",Command.EXIT,1);


menu.addCommand(salir);
menu.setCommandListener(this);
}

public void startApp()


{
// Mostrar el Alert y luego el menú
pantalla.setCurrent(bienvenida, menu);
}

public void pauseApp()


{
}

public void destroyApp(boolean unconditional)


{
}

public void commandAction(Command c, Displayable d)


{
if (c == List.SELECT_COMMAND && d == menu)
{ // Si selecciono opcion del menu
switch(menu.getSelectedIndex())
{
case 0:
alerta.setString("Elegio la Opcion 1");
pantalla.setCurrent(alerta);
break;
case 1:
alerta.setString("Elegio la Opcion 2");
pantalla.setCurrent(alerta);
break;
case 2:
alerta.setString("Elegio la Opcion 3");
pantalla.setCurrent(alerta);
break;
}
}
else if (c == salir)
{ // Selecciono salir de la aplicacion
destroyApp(false);
notifyDestroyed();
}
}
}

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 77

Resumen

 La clase Image se usa para mostrar una imagen. El formato estándar de los
archivos imagen para móviles es PNG. Estos archivos deben ser copiados en la
carpeta res del proyecto para poder ser usados.

 La clase Font se usa para definir un tipo de letra, el cual puede ser usado para
cambiar la fuente del texto de un control.

 La clase Ticker se usa para mostrar un texto de una manera similar a una
marquesina. Un ticker debe ser agregado a un objeto que herede de Displayable
(TextBox, Alert, List, Form, Canvas) para poder ser visto.

 Si desea saber más acerca de estos temas, puede consultar las siguientes
páginas:

 http://www.mailxmail.com/curso/informatica/j2me
 http://programacion.com/java/tutorial/ags_j2me/
 http://leo.ugr.es/J2ME/MIDP/enlaces.htm

 Referencia oficial de Java (en inglés)

 http://java.sun.com/javame/reference/apis/jsr118/

CIBERTEC CARRERAS PROFESIONALES


78

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 79

UNIDAD DE
APRENDIZAJE

2
SEMANA

MANEJO DE FORMULARIOS
LOGRO DE LA UNIDAD DE APRENDIZAJE

• Desarrolla aplicaciones basadas en las clases de la interfaz de alto nivel,


permitiendo la construcción de aplicaciones que realicen un correcto ingreso
de datos y presentación ordenada de información.

• Identifica las necesidades de las aplicaciones móviles comerciales y las aplica


mediante las clases ítems para un mejor manejo de la interfaz de usuario.

TEMARIO

• Manejo de formularios: Clase Form


• Elementos de un formulario: Clases StringItem, TextField y ChoiceGroup
• Eventos de cambio de estado: Interfaz ItemStateListener

ACTIVIDADES PROPUESTAS

• Crea la aplicación especificada en el punto 6, que permite ingresar datos


usando los controles TextField y ChoiceGroup.

CIBERTEC CARRERAS PROFESIONALES


80

1. CLASE FORM

1.1. Definición

Un formulario es un contenedor de controles donde cada control nos va a


permitir el ingreso y/o visualización de un dato. Los controles se almacenan en un
arreglo dentro del formulario donde el primer elemento tiene el indice cero (0).
Todos los controles son objetos de tipo Item, aunque, generalmente, se usarán
clases que heredan de Item, los cuales se grafican en la figura 5-1.

Item

ChoiceGroup DateField

TextField ImageItem

Gauge StringItem

Tabla 1-1. Clases Item

1.2. Métodos

1.2.1 Constructor
• Definición
public Form(String titulo)
public Form(String titulo, Item [] elementos)

• Descripción
Permite crear un control de tipo Form. Sus parámetros son:
o título: Título a mostrar en la parte superior de la pantalla
o elementos: Elementos que se agregarán al formulario
• Ejemplo
El siguiente fragmento crea un formulario con el título “Ingreso”.
private Form frm = new Form(“Ingreso”);

1.2.2 append()
• Definición
public int append(String texto)
public int append(Item item)
public int append(Image imagen)

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 81

• Descripción
Agrega un elemento al formulario y devuelve su índice.
o texto: Texto que se agregará al formulario como un control
StringItem
o item: Item que se agregará al formulario
o imagen: Imagen que se agregará al formulario como un control
ImageItem

1.2.3 delete()
• Definición
public void delete(int posicion)

• Descripción
Elimina el elemento del formulario dado por el parámetro “posición”.

1.2.4 deleteAll()
• Definición
public void deleteAll()

• Descripción
Elimina todos los elementos del formulario.

1.2.5 insert()
• Definición
public void insert(int posicion, Item item)

• Descripción
Inserta un objeto de tipo Item en la posición dada por el parámetro.

1.2.6 set()
• Definición
public void set(int posicion, Item item)

• Descripción
Reemplaza el objeto de tipo Item de la posición dada por el
parámetro “posición” con el nuevo objeto “item”.

1.2.7 size()
• Definición
public int size()

• Descripción
Obtiene el número de elementos que contiene el formulario.

CIBERTEC CARRERAS PROFESIONALES


82

1.2.8 setItemStateListener()
• Definición
public void setItemStateListener(ItemStateListener listener)

• Descripción
Establece la clase que escuchará los eventos de cambio de estado
de los objetos de tipo Item insertados en un formulario. Ver el punto 5
para más detalle sobre acerca de este tipo de eventos.

2. Clase StringItem

2.1. Definición

La clase StringItem es una clase similar a una etiqueta, la cual podrá ser
insertada en un formulario. Esta clase también permite simular un botón o
hyperlink. Para más detalle sobre como realizar esto último, ir al capítulo 10.

2.2. Métodos

2.2.1 Constructor
• Definición
public StringItem(String etiqueta, String texto)
public StringItem(String etiqueta, String texto,
int apariencia)

• Descripción
Permite construir un control de tipo StringItem. Sus parámetros son:
o etiqueta: Texto a mostrar en la parte izquierda del control, a
manera de título
o texto: Texto a mostrar en la parte derecha del control
o apariencia: Dato entero que define cómo se mostrará el control
La tabla 2-1 indica las constantes definidas para este valor.

Constante Descripción
Item.PLAIN Texto plano
Item.HYPERLINK Enlace. Ir al capítulo 10 para más detalle
Item.BUTTON Botón. Ir al capítulo 10 para más detalle

Tabla 2-1. Tipos de aparienca para un control StringItem

2.2.2 getAppearanceMode()
• Definición
public int getAppearanceMode()

• Descripción
Devuelve la apariencia del control StringItem.

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 83

2.2.3 getText()
• Definición
public String getText()

• Descripción
Devuelve el texto del control StringItem.

2.2.4 setFont()
• Definición
public void setFont(Font font)

• Descripción
Define un tipo de letra para el control StringItem.
2.2.5 setText()
• Definición
public void setText(String texto)

• Descripción
Define el nuevo texto del control StringItem.

3. Clase TextField

3.1. Definición

Esta clase nos permite crear objetos de tipo caja de texto dentro de un
formulario. Es similar al objeto TextBox, con la diferencia que pueden existir varios
objetos de tipo TextField al mismo tiempo en un solo formulario.

3.1 Métodos

3.1.1 Constructor
• Definición
public TextField(String titulo, String textoInicial,
int longitudMaxima, int filtros)

• Descripción
Permite construir un control de tipo TextField. Sus parámetros son:
o título: Título a mostrar en la parte superior de la pantalla.
o textoInicial: Texto mostrado al inicio.
o longitudMaxima: Longitud máxima de caracteres
o filtros: Es un entero que define que tipo de texto se va a
ingresar. Este entero puede ser un filtro restrictivo solo (ver tabla

CIBERTEC CARRERAS PROFESIONALES


84

3-1) o combinado con uno o varios filtros opcionales (ver tabla 3-


2) con el operador barra vertical (“|”).

Constante Descripción
TextField.ANY Permite el ingreso de cualquier caracter.
TextField.NUMERIC Permite el ingreso de cualquier número entero.
TextField.PHONENUMBER Permite caracteres válidos sólo para números de teléfono.
TextField.EMAILADDR Permite caracteres válidos para direcciones de correo.
TextField.DECIMAL Permite el ingreso de cualquier número decimal.
TextField.URL Permite caracteres válidos sólo para direcciones URL.
Tabla 2-1. Filtros restrictivos de un TextField

Constante Descripción
TextField.PASSWORD Muestra asteriscos en vez del texto realmente ingresado.
TextField.UNEDITABLE No permite la edición del texto.
TextField.SENSITIVE Es un dato sensible y no debe ser guardado en memoria.
TextField.NON_PREDICTIVE No usar el mecanismo de texto predictivo.
TextField.INITIAL_CAPS_WORD Cada palabra comenzará en mayúsculas.
TextField.INITIAL_CAPS_SENTENCE Cada oración comenzará con mayúsculas
Tabla 2-2. Filtros opcionales de un TextField

• Ejemplo
El siguiente fragmento, crea una ventana de texto que permite el
ingreso de una contraseña numérica de máximo 10 dígitos, e indica que
es un dato sensible.
private TextField txf = new TextField(“Clave”, “”, 10,
TextField.NUMERIC | TextField.PASSWORD | TextField.SENSITIVE);

3.1.2 delete()
• Definición
public void delete(int desplazamiento, int longitud)

• Descripción
Borra caracteres del TextField, donde:
o desplazamiento: Posición inicial a borrar
o longitud: Cantidad de caracteres a eliminar

3.1.3 getCaretPosition()
• Definición
public int getCaretPosition()

• Descripción
Devuelve la posición del cursor en pantalla.

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 85

3.1.4 getChars()
• Definición
public int getChars(char [] datos)

• Descripción
Copia el contenido del TextField en el arreglo “datos” y devuelve el
número de caracteres copiados.

3.1.5 getMaxSize()
• Definición
public int getMaxSize()

• Descripción
Devuelve el tamaño máximo del TextField.

3.1.6 getString()
• Definición
public String getString()

• Descripción
Devuelve el contenido del TextField.

3.1.7 insert()
• Definición
public void insert(char[] datos, int des, int long, int pos)
public void insert(char[] datos, int pos)

• Descripción
Inserta el contenido del arreglo datos en el TextField.
o datos: arreglo a copiar
o des: posición del arreglo desde donde se copiará
o long: cantidad de caracteres que se copiarán
o pos: posición en el TextField donde se colocarán los caracteres

3.1.8 setChars()
• Definición
public void setChars(char[] datos, int des, int long)

• Descripción
Reemplaza el contenido del TextField por el arreglo “datos”.
o datos: arreglo a copiar
o des: posición del arreglo desde donde se copiará
o long: cantidad de caracteres que se copiarán

CIBERTEC CARRERAS PROFESIONALES


86

3.1.9 setMaxSize()
• Definición
public int setMaxSize(int capacidad)

• Descripción
Establece el tamaño máximo del TextField. Devuelve el tamaño que
realmente se le ha asignado.

3.1.10 setString()
• Definición
public void setString(String texto)

• Descripción
Establece el contenido del TextField.

3.1.11 size()
• Definición
public int size()

• Descripción
Devuelve el número de caracteres actualmente ingresados.

4. Clase ChoiceGroup

4.1. Definición

Esta clase nos permite crear listas de selección que podrán ser incrustados en
un formulario, tal como lo hacía el objeto List.

4.2. Métodos

4.2.1 Constructor
• Definición
public ChoiceGroup(String etiqueta, int tipo)
public ChoiceGroup(String etiqueta, int tipo,
String[] elementos, Image[] imagenes)

• Descripción
Permite crear un control de tipo ChoiceGroup. Sus parámetros son:
o etiqueta: Etiqueta que se mostrará arriba del control
o tipo: Dato entero que indica el tipo de lista. Se pueden usar las
constantes de la tabla 4-1
o elementos: arreglo conteniendo la lista inicial de elementos

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 87

o imágenes: arreglo del mismo tamaño de “elementos”,


conteniendo sus imágenes, o null si no existieran imágenes

Constante Descripción
ChoiceGroup.EXCLUSIVE Permite la selección de sólo un elemento a la vez.
ChoiceGroup.MULTIPLE Permite la selección de varios elementos a la vez.
ChoiceGroup.POPUP Permite la selección de sólo un elemento a la vez y se muestra como
una lista desplegable.
Tabla 4-1. Constantes de tipos de ChoiceGroup

• Ejemplo
El siguiente código crea un ChoiceGroup exclusivo con 3 elementos
private String astrTipoDoc[] = {“Partida”, “DNI”, “Pasaporte”};
private ChoiceGroup lst = new ChoiceGroup(“Tipo Documento”,
ChoiceGroup.EXCLUSIVE, astrTipoDoc, null);

El siguiente código crea una ChoiceGroup multiple sin elementos


private ChoiceGroup lst = new ChoiceGroup(“Pasatiempos”,
ChoiceGroup.MULTIPLE);

4.2.2 append()
• Definición
public int append(String texto, Image img)

• Descripción
Añade un elemento al final de la ChoiceGroup y devuelve su índice.
o texto: Elemento a agregar
o img: Imagen del elemento a agregar o null si no existiera

4.2.3 delete()
• Definición
public void delete(int pos)

• Descripción
Elimina el elemento en la posición que se especifica.

4.2.4 deleteAll()
• Definición
public void deleteAll()

• Descripción
Elimina todos los elementos de la ChoiceGroup.

4.2.5 insert()
• Definición
public void insert(int pos, String texto, Image img)

CIBERTEC CARRERAS PROFESIONALES


88

• Descripción
Inserta un elemento en la posición indicada. Todos los elementos
posteriores corren una posición.
o pos: Posición del elemento a agregar
o texto: Elemento a agregar
o img: Imagen del elemento a agregar o null si no existiera

4.2.6 getFont()
• Definición
public Font getFont(int pos)

• Descripción
Devuelve la fuente del elemento en la posición indicada por “pos”.
En el capítulo 6, se trata a mayor detalle los tipos de letra que se
pueden manejar desde J2ME.

4.2.7 getImage()
• Definición
public Image getImage(int pos)

• Descripción
Devuelve la imagen del elemento en la posición indicada por “pos”.

4.2.8 getSelectedFlags()
• Definición
public int getSelectedFlags(boolean [] estado)

• Descripción
Llena el arreglo “estado” con el estado de los elementos (true si
fueron seleccionados, false si no) y devuelve el número de elementos
seleccionados. Este método se usa para los controles de tipo
ChoiceGroup múltiples.

4.2.9 getSelectedIndex()
• Definición
public int getSelectedIndex()

• Descripción
Obtiene el índice del elemento seleccionado. Este método se usa
para la controles de tipo ChoiceGroup exclusivo o popup.

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 89

4.2.10 getString()
• Definición
public String getString(int pos)

• Descripción
Obtiene el texto del elemento señalado por el parámetro “pos”.

4.2.11 isSelected()
• Definición
public boolean isSelected(int pos)

• Descripción
Devuelve un valor que indica si el elemento señalado por el
parámetro “pos” está seleccionado.

4.2.12 set()
• Definición
public void set(int pos, String texto, Image img)

• Descripción
Modifica un elemento ya existente en la posición indicada.
o pos: Posición del elemento a agregar
o texto: Elemento a agregar
o img: Imagen del elemento a agregar o null si no existiera

4.2.13 setFitPolicy()
• Definición
public void setFitPolicy(int estilo)

• Descripción
Modifica la forma cómo se muestran los elementos con texto muy
largo. El parámetro estilo es un entero que puede usar las constantes
indicadas en la tabla 4-2.

Constante Descripción
ChoiceGroup.TEXT_WRAP_OFF Textos que sobrepasan la pantalla son cortados, de manera
que todos los elementos ocupan un renglón.
ChoiceGroup.TEXT_WRAP_ON Textos que sobrepasan la pantalla no son cortados, de manera
que los elementos se ven completos en más de un renglón.
ChoiceGroup.TEXT_WRAP_DEFAULT Textos que sobrepasan la pantalla se muestran de acuerdo
como se haya definido por defecto en el dispositivo.
Tabla 1-2. Valores para usar con el método serFitPolicy

4.2.14 setFont()
• Definición
public void setFont(int pos, Font fuente)

CIBERTEC CARRERAS PROFESIONALES


90

• Descripción
Cambia la fuente del elemento en la posición “pos” por la fuente
indicada en el parámetro “fuente”. En el capítulo 6, se trata, con mayor
detalle, los tipos de letra que se pueden manejar desde J2ME.

4.2.15 setSelectedFlags()
• Definición
public void setSelectedFlags(Boolean [] nuevoEstado)

• Descripción
Cambia el estado de los elementos (true si fueron seleccionados,
false si no es así) por el que se indica en el arreglo “nuevoEstado”. Se
usa en controles de tipo ChoiceGroup múltiples.

4.2.16 setSelectedIndex()
• Definición
public void setSelectedIndex(int pos, boolean seleccionado)

• Descripción
Cambia el estado del elemento indicado en la posición “pos” por el
que se indica en el parámetro “seleccionado”.

4.2.17 size()
• Definición
public int size()

• Descripción
Devuelve el número de elementos de la ChoiceGroup.

5. Eventos de cambio de estado

5.1. Consideraciones

Los eventos de cambio de estado se producen cuando un control de tipo Item


modifica su valor. Por ejemplo, cuando un usuario ingresa un dato en un control
TextField, se generará el evento cada vez que se escriba un caracter o, cuando
se modifica el valor seleccionado en un control ChoiceGroup, se generará el
evento con cada cambio en la selección.

5.2. Implementación

La forma de implementar el manejo de los eventos de cambio de estado es el


siguiente:

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 91

1. Crear una clase que implemente la interfaz ItemStateListener y sobrescribir el


método itemStateChanged
public class MiClase extends MIDlet implements ItemStateListener

2. Crear un formulario y controles tipo Item


private Form frm = new Form("Prueba");
private TextField txf = new TextField("Prueba", "", 10, TextField.ANY);

3. Agregarle los controles Item que cambiarán de estado


frm.append(txf);

4. Indicarle al objeto Form el objeto que procesará los eventos usando el método
setItemStateListener
frm.setItemStateListener(this);

5. Poner la lógica correspondiente en el método itemStateChanged


public void itemStateChanged(Item i) {
if (i == txf)
{
/* Poner la logica que se desea realizar*/
}
}

6. Ejemplos

6.1. Aplicación DatosVivienda

6.1.1 Enunciado
Construir una aplicación que realice lo siguiente:
• Mostrar una ventana con el título “Datos vivienda”, que permita ingresar
los siguientes datos:
• Tipo vía: Avenida, Calle o Pasaje
• Nombre vía: Dato alfanumérico, 100 caracteres como máximo
• Número: Dato numérico, 5 dígitos como máximo
• Tipo vivienda: Casa, piso, departamento, habitación
• Sub Número: Dato numérico, 5 dígitos como máximo. Solo se
muestra si el tipo de vivienda no es Casa
• La aplicación tendrá dos botones: uno para salir y otro para mostrar una
ventana que muestre los datos que se han ingresado.
• La figura 6-1 indica cómo deberá verse la pantalla.

CIBERTEC CARRERAS PROFESIONALES


92

Figura 6-1. Ventana de la aplicación DatosVivienda

6.1.2 Código

import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.AlertType;
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.Image;
import javax.microedition.lcdui.ImageItem;
import javax.microedition.lcdui.Item;
import javax.microedition.lcdui.ItemStateListener;
import javax.microedition.lcdui.TextField;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;

public class DatosVivienda extends MIDlet implements CommandListener,


ItemStateListener
{
// Referencia a la pantalla
private Display dsp = Display.getDisplay(this);

// Creación del formulario y sus controles


private Form frmVivienda = new Form("Datos vivienda");
private String astrTiposVia[] = {"Avenida", "Calle", "Pasaje"};
private ChoiceGroup chgTipoVia = new ChoiceGroup("Tipo Via",
ChoiceGroup.POPUP, astrTiposVia, null);
private TextField txfNombreVia = new TextField("Nombre", "", 100,
TextField.ANY);
private TextField txfNumero = new TextField("Numero", "", 5,
TextField.NUMERIC);
private String astrTiposVivienda[]
= {"Casa", "Piso", "Departamento", "Habitacion"};
private ChoiceGroup chgTipoVivienda = new ChoiceGroup("Tipo Vivienda",
ChoiceGroup.POPUP, astrTiposVivienda, null);
private TextField txfSubNumero = new TextField("", "", 5,
TextField.NUMERIC);

// Creación de los botones


private Command cmdAceptar = new Command("Aceptar", Command.OK, 2);
private Command cmdSalir = new Command("Salir", Command.EXIT, 2);

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 93

public DatosVivienda()
{
// Agregar controles
// El control de txfSubNumero no se agrega en el constructor.
// Este control se agregara solo si se selecciona un elemento
// diferente de “Casa”
frmVivienda.append(chgTipoVia);
frmVivienda.append(txfNombreVia);
frmVivienda.append(txfNumero);
frmVivienda.append(chgTipoVivienda);

// Agregar botones
frmVivienda.addCommand(cmdAceptar);
frmVivienda.addCommand(cmdSalir);

// Indicar la clase que procesara los eventos de los botones


// y de cambio de estado
frmVivienda.setCommandListener(this);
frmVivienda.setItemStateListener(this);
}

protected void destroyApp(boolean arg0)


{
}

protected void pauseApp()


{
}

protected void startApp() throws MIDletStateChangeException


{
// Establecer la ventana inicial
dsp.setCurrent(frmVivienda);
}

public void commandAction(Command c, Displayable d)


{
// Se pulso un botón
if(c == cmdAceptar)
{
// Crear el mensaje que se mostrará
// Se concatenan todos los datos
String strMensaje = "Vivienda registrada\n\rDatos:"
+ "\n\rTipo Via: "
+ chgTipoVia.getString(chgTipoVia.getSelectedIndex())
+ "\n\rNombre Via: " + txfNombreVia.getString()
+ "\n\rNumero: " + txfNumero.getString()
+ "\n\rTipo Vivienda: "
+ chgTipoVivienda.getString(chgTipoVivienda.getSelectedIndex())
+ " \n\rNumero: " + txfSubNumero.getString();

// Crear el Alert correspondiente


Alert altMensaje = new Alert("Datos ingresados", strMensaje, null,
AlertType.CONFIRMATION);

// Mostrar el Alert
dsp.setCurrent(altMensaje);
}
else if (c == cmdSalir)
{
// Salir de la aplicacion
destroyApp(false);
notifyDestroyed();
}
}

CIBERTEC CARRERAS PROFESIONALES


94

public void itemStateChanged(Item i)


{
// Se modifico el estado de algun elemento
// se verifica cual fue
if(i == chgTipoVivienda)
{
// Si el elemento fue chgTipoVivienda
// Verificar si el indice es diferente de 0
// Esto indicaria que se ha seleccionado un elemento
// diferente de “Casa”
if (chgTipoVivienda.getSelectedIndex() != 0)
{
// Se obtiene el elemento seleccionado para
// mostrarlo en la etiqueta
String tipoVivienda =
chgTipoVivienda.getString(chgTipoVivienda.getSelectedIndex());

// Se cambia el valor de la etiqueta


txfSubNumero.setLabel(tipoVivienda + " numero");

// Se verifica el número de elementos del formulario.


// Si son 4 o menos se agrega txfSubNumero,
// en caso contrario no se agrega, pues indicaria que
// ya se ha agregado
if(frmVivienda.size() <= 4)
frmVivienda.append(txfSubNumero);
}
else
{
// El indice es igual a 0, esto indica
// que se ha seleccionado “Casa”
// Se verifica si los elementos son mas que 4
// Si asi fuera, se elimina el control txfSubNumero
if(frmVivienda.size() > 4)
frmVivienda.delete(4);
}
}
}

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 95

Resumen

 La clase Form se usa como contenedor de objetos de tipo Item. De este modo,
permite la creación de ventanas para el ingreso de múltiples datos.

 La clase StringItem es una sub clase de Item. Permite crear controles similares a
las etiquetas dentro de un formulario. También, pueden ser usadas para simular un
botón o hyperlink dentro de un formulario.

 Las clases TextField y ChoiceGroup son subclases de Item. Son muy similares a
TextBox y List, con la diferencia que están dentro de un formulario.

 Desde un formulario, se puede controlar los cambios de estado de los controles


tipo Item utilizando la interfaz ItemStateListener.

 Si desea saber más acerca de estos temas, puede consultar las siguientes
páginas.

 http://www.mailxmail.com/curso/informatica/j2me
 http://programacion.com/java/tutorial/ags_j2me/
 http://leo.ugr.es/J2ME/MIDP/enlaces.htm

 Referencia oficial de Java (en inglés)

 http://java.sun.com/javame/reference/apis/jsr118/

CIBERTEC CARRERAS PROFESIONALES


96

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 97

UNIDAD DE
APRENDIZAJE

2
SEMANA

10

MANEJO DE CONTROLES ITEM


LOGRO DE LA UNIDAD DE APRENDIZAJE

• Desarrolla aplicaciones basadas en las clases de la interfaz de alto nivel,


permitiendo la construcción de aplicaciones que realicen un correcto ingreso
de datos y presentación ordenada de información.

• Identifica las necesidades de las aplicaciones móviles comerciales y las aplica


mediante las clases ítems para un mejor manejo de la interfaz de usuario.

TEMARIO

• Elementos de un formulario: Clases DateField, Gauge e ImageItem


• Eventos del teclado: Interfaz ItemCommandListener

ACTIVIDADES PROPUESTAS

• Crea la aplicación especificada en el punto 6, que permite ingresar datos


usando los controles Gauge y DateField.

CIBERTEC CARRERAS PROFESIONALES


98

1. Clase DateField

1.1. Definición
Esta clase nos permite crear objetos de tipo caja de texto especializadas en el
ingreso de valores de tipo fecha y hora.

1.2. Métodos

1.2.1 Constructor
• Definición
public DateField(String etiqueta, int modo)
public DateField(String etiqueta, int modo, TimeZone tz)

• Descripción
Permite crear un control de tipo DateField. Sus parámetros son:
o etiqueta: Etiqueta que se mostrará en la parte superior del
control
o modo: Dato entero que define el tipo de dato que se va a
ingresar. Se puede usar las constantes de la tabla 1-1
o tz: Zona horaria del dato que se va a ingresar

Constante Descripción
DateField.DATE Permite la inserción de valores de tipo Fecha.
DateField.TIME Permite insertar valores de tipo Hora
DateField.DATE_TIME Permite insertar valores de tipo Fecha y Hora.
Tabla 1-1. Constantes para el modo de ingreso de un DateField

1.2.2 getDate()
• Definición
public Date getDate()

• Descripción
Devuelve el dato ingresado, de tipo java.util.Date.

1.2.3 getInputMode()
• Definición
public int getInputMode()

• Descripción
Devuelve el modo de ingreso (ver tabla 1-1).

1.2.4 setDate()
• Definición
public void setDate(Date d)

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 99

• Descripción
Inicializa o modifica el valor del control con el valor de “d”.

1.2.5 setInputMode()
• Definición
public void setInputMode(int modo)

• Descripción
Cambia el modo de ingreso (ver tabla 1-1).

2. Clase Gauge

2.1. Definición

Esta clase nos permite crear objetos similares a indicadores de proceso o barra
de progreso. Es usado para indicar la cantidad de procesamiento que está
realizando la aplicación. Existen los siguientes tipos de Gauge:
2.1.1 Gauge Interactivo:
Puede ser modificado por el usuario. Tiene un valor máximo, y el valor actual
está entre 0 y el valor máximo.
2.1.2 Gauge no interactivo:
Puede ser modificado sólo por la aplicación. Puede ser a su vez:
• Gauge con rango definido:
Tiene un valor máximo, y el valor actual está entre 0 y el valor máximo. Es
usado como barra de estado de un proceso que esta actualizándose
constantemente y del cual se conoce su valor final.
• Gauge indefinido incremental:
No tiene valor máximo. Es usado como barra de estado de un proceso
que esta actualizándose constantemente pero no se conoce su valor final.
• Gauge indefinido continuo:
No tiene valor máximo. Es usado como barra de estado de un proceso
que no esta actualizándose constantemente y no se conoce su valor final,
es decir, sólo se sabe cuándo empieza y cuándo termina.

2.2. Métodos

2.2.1 Constructor
• Definición
public Gauge(String etiqueta, boolean interactivo,
int valorMax, int valorInicial)

CIBERTEC CARRERAS PROFESIONALES


100

• Descripción
Permite crear un control de tipo Gauge. Sus parámetros son:
o etiqueta: Etiqueta que se mostrará en la parte superior del
control
o interactivo: Indica si el usuario puede o no modificar el valor del
control.
o valorMax: Valor máximo del Gauge. Sus valores oscilarían entra
cero (0) y valorMax. Se puede indicar que el control no tiene
valor máximo usando la constante Gauge.INDEFINITE
o valorInicial: Valor inicial del Gauge. Si el valor máximo es
Gauge.INDEFINITE, el valor inicial debe ser uno de los indicados
en la tabla 2-1.

Constante Descripción
Gauge.INCREMENTAL_IDLE Estado ocupado o finalizado de un Gauge incremental
Gauge.INCREMENTAL_UPDATING Estado de actualización de un Gauge incremental
Gauge.CONTINUOUS_RUNNING Estado ocupado o finalizado de un Gauge continuo
Gauge.CONTINUOUS_IDLE Estado de actualización de un Gauge continuo
Tabla 2-1. Valores posibles para el valor inicial de un Gauge

• Ejemplo
El siguiente código crea un Gauge interactivo que va de 0 a 100:
private Gauge gauProgreso = new Gauge(“Progreso”, true, 100, 0);

2.2.2 getValue()
• Definición
public int getValue()

• Descripción
Devuelve valor actual de la barra de progreso. Si es un Gauge
indefinido, puede devolver algunos de los valores de la tabla 2-1.

2.2.3 setValue()
• Definición
public void setValue(int valor)

• Descripción
Cambia el valor actual de la barra de progreso. Si es un Gauge
indefinido, debe cambiarse por algunos de los valores de la tabla 2-1.

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 101

2.2.4 setMaxValue()
• Definición
public void setMaxValue(int valor)

• Descripción
Cambia el valor máximo de la barra de progreso. Si se desea crear
un Gauge indefinido, el valor debe ser la constante Gauge.INDEFINITE.

3. Clase ImageItem

3.1. Definición

La clase ImageItem permite la manipulación de imágenes que podrán ser


incrustados en un formulario. Esta clase al igual que la clase StringItem, permite
simular un objeto de tipo boton o hyperlink. Para más detalle sobre este tema, ir al
punto 4).

3.2. Métodos

3.2.1 Constructor
• Definición
public ImageItem(String etiqueta, Image img, int trazado,
String textoAlterno)
public ImageItem(String etiqueta, Image img, int trazado,
String textoAlterno, int apariencia)

• Descripción
Permite crear un control de tipo ImageItem. Sus parámetros son:
o etiqueta: Texto a mostrar en la parte superior del control
o img: Imagen creada previamente
o trazado: Valor entero que define la alineación en la pantalla. Es
igual a una de las constantes de la tabla 3-1, opcionalmente
combinada con una o varias de las constates de la tabla 3-2,
usando el operador barra vertical (“|”)
o textoAlterno: Texto que se mostrará si la imagen no pudiera ser
mostrada.
o apariencia: Valor entero que indica el modo en que se ve la
imagen. Es igual a una de las constantes de la tabla 3-3.
• Ejemplo
El siguiente fragmento crea un control ImageItem centrado:

CIBERTEC CARRERAS PROFESIONALES


102

Image img = null;


try {
img = Image.createImage(“/imagen.png”);
}
catch(Exception ex) {
}
ImageItem imi = new ImageItem(“Imagen”, img, Item.LAYOUT_CENTER,
“Hola”);

Constante Descripción
Item.LAYOUT_DEFAULT Alineación por defecto.
Item.LAYOUT_CENTER Centrado.
Item.LAYOUT_LEFT Alineado a la izquierda.
Item.LAYOUT_RIGHT Alineado a la derecha.
Tabla 3-1. Valores obligatorios del trazado

Constante Descripción
Item.LAYOUT_NEWLINE_AFTER Inserta una nueva línea después de mostrar la imagen.
Item.LAYOUT_NEWLINE_BEFORE Inserta una nueva línea antes de mostrar la imagen.
Tabla 3-2. Valores opcionales del trazado

Constante Descripción
Item.PLAIN Imagen plana
Item.HYPERLINK Enlace. Ir al punto 5 para más detalle
Item.BUTTON Boton. Ir al punto 5 para más detalle
Tabla 3-3. Valores obligatorios de la apariencia

3.2.2 getAppearanceMode()
• Definición
public int getAppearanceMode()

• Descripción
Devuelve el valor entero que define la apariencia (tabla 3-3).

3.2.3 getImage()
• Definición
public Image getImage()

• Descripción
Devuelve la imagen contenida en el control.

3.2.4 getAltText()
• Definición
public String getAltText()

• Descripción
Devuelve el texto alterno contenido en el control.

3.2.5 setImage()
• Definición
public void setImage(Image img)

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 103

• Descripción
Cambia la imagen por la que se especifica en “img”.

4. Eventos del teclado

4.1. Consideraciones

Adicionalmente a los eventos del teclado producidos por objetos Command


agregados a ventanas, explicados en el capítulo 3, también se pueden agregar
objetos Command a objetos de tipo Item. Adicionalmente, si los controles son de
tipo StringItem o ImageItem, se producirá un efecto similar a tener botones o
hyperlinks dentro del formulario.

4.2. Implementación

La forma de implementar el manejo de los eventos de cambio de estado es el


siguiente:
1. Crear una clase que implemente la interfaz ItemCommandListener y
sobrescribir el método commandAction. Este método es diferente del método
del mismo nombre correspondiente a la interfaz CommandListener.
public class MiClase extends MIDlet implements ItemCommandListener

2. Crear un formulario y controles tipo Item. Si los controles son StringItem o


ImageItem, asignar el valor de la constante Item.BUTTON o Item.HYPERLINK
a su propiedad “Apariencia”. Asimismo, la etiqueta debe ser la cadena vacía.
private Form frm = new Form("Prueba");
private TextField txf = new TextField("Prueba", "", 10, TextField.ANY);
private StringItem sti = new StringItem("", "Aceptar", Item.BUTTON);

3. Crear tantos objetos Command como botones se deseen utilizar. Estos objetos
deben ser de tipo Command.Item.
private Command cmdAceptar = new Command("Aceptar", Command.ITEM, 2);
private Command cmdNuevo = new Command("Nuevo", Command.ITEM, 2);

4. Agregarle al objeto Item los objetos Command correspondientes usando el


método addCommand()
txf.addCommand(cmdNuevo);
sti.addCommand(cmdAceptar);

5. Opcionalmente, indicar si el botón agregado se activará con el botón SELECT,


usando el método setDefaultCommand()
sti.setDefaultCommand(cmdAceptar);

CIBERTEC CARRERAS PROFESIONALES


104

6. Indicarle al objeto Item la referencia al objeto que implementa la interfaz


ItemCommandListener usando el método setItemCommandListener
txf.setItemCommandListener(this);
sti.setItemCommandListener(this);

7. Agregarle los controles Item al formulario


frm.append(txf);
frm.append(sti);

8. Poner la lógica correspondiente en el método commandAction


public void commandAction(Command c, Item i) {
if (c == cmdAceptar && i == sti)
{
/* Poner la logica que se desea realizar*/
}
else if(c == cmdNuevo && i == txf)
{
/* Poner la logica que se desea realizar*/
}
}

5. Modificación de la apariencia

5.1. Consideraciones

Los métodos que se describen a continuación son comunes a todas las


clases de tipo Item, y sirven para modificar el tamaño y el trazado. Tomar en
cuenta lo siguiente:
• Los controles tienen un ancho y alto mínimo, por lo cual los valores que se
indiquen no siempre funcionarán.
• La alineación y el tamaño depende del tipo de control y del texto que se le
haya asignado. Por ejemplo, un TextField con un tamaño máximo de 100
caracteres difícilmente podrá ser reducido.

5.2. Modificación del tamaño

5.2.1 getMinimumHeight()
• Definición
public int getMinimumHeight()

• Descripción
Devuelve el alto mínimo de un control.

5.2.2 getMinimumWidth()
• Definición
public int getMinimumWidth()

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 105

• Descripción
Devuelve el ancho mínimo de un control.

5.2.3 getPreferredHeight()
• Definición
public int getPreferredHeight()

• Descripción
Devuelve el alto actual de un control.

5.2.4 getPreferredWidth()
• Definición
public int getPreferredWidth()

• Descripción
Devuelve el ancho actual de un control.

5.2.5 setPreferredSize()
• Definición
public void setPreferredSize(int ancho, int alto)

• Descripción
Modifica el ancho y alto de un control. Tomar en cuenta que:
o Si ancho < getMinimumWidth(), ancho = getMinimumWidth()
o Si alto < getMinimumHeight(), alto = getMinimumHeight()
o Si alto o ancho = -1, no se modifica.

5.3. Modificación del trazado

5.3.1 getLayout()
• Definición
public int getLayout()

• Descripción
Devuelve un valor entero que define el trazado del control en el
formulario.

5.3.2 setLayout()
• Definición
public void setLayout(int trazado)

• Descripción
Cambia el trazado del control por el valor entero definido en
“trazado”. Este valor se define de la combinación de diferentes

CIBERTEC CARRERAS PROFESIONALES


106

constantes de alineación vertical y horizontal usando con el operados


barra vertical (“|”). Las constantes se definen en las tablas 5-1 a 5-3.

Constante Descripción
Item.LAYOUT_LEFT Alineación a la izquierda
Item.LAYOUT_RIGHT Alineación a la derecha
Item.LAYOUT_CENTER Alineación al centro
Item.LAYOUT_DEFAULT Alineación por defecto
Item.LAYOUT_EXPAND Expandir a todo lo ancho
Item.LAYOUT_SHRINK Comprimir horizontalmente al mínimo
Tabla 5-1. Constantes de alineación horizontal

Constante Descripción
Item.LAYOUT_BOTTOM Alineación hacia abajo
Item.LAYOUT_TOP Alineación hacia arriba
Item.LAYOUT_VCENTER Alineación centrada verticalmente
Item.LAYOUT_VEXPAND Expandir a todo lo alto
Item.LAYOUT_VSHRINK Comprimir verticalmente al mínimo
Tabla 5-2. Constantes de alineación vertical

Constante Descripción
Item.LAYOUT_NEWLINE_AFTER Insertar nueva linea después de mostrar el control
Item.LAYOUT_NEWLINE_BEFORE Insertar nueva linea antes de mostrar el control
Item.LAYOUT_2 Utiliza las politicas de alineación de MIDP 2.0, que, entre
otras cosas, permite poner varios controles en un mismo
renglón.
Tabla 5-3. Constantes de alineación - Otras

6. Ejemplos

6.1. Aplicación NuevoCliente

6.1.1 Enunciado
Construir una aplicación que realice lo siguiente:
• Mostrar un formulario con el título “Nuevo Cliente” y que permita ingresar
los siguientes datos:
o Nombres (Alfanumérico de 40 caracteres)
o Tipo de documento (DNI o RUC)
o Número de documento (Numérico de 11 dígitos)
o Fecha de nacimiento.
o Tipo de negocio (kiosko o bodega)
o Decuento (usar un control Gauge)
• El control de tipo de negocio debe tener un botón “Nuevo Tipo” que carga
una ventana con un mensaje.
• Se debe simular tener un botón “Grabar” dentro del formulario.
• Adicionalmente, debe tener un botón “Salir”
• La figura 6-1 indica cómo deberá verse la pantalla.

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 107

Figura 6-1. Ventana de la aplicación NuevoCliente

6.1.2 Código
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.AlertType;
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.Gauge;
import javax.microedition.lcdui.Item;
import javax.microedition.lcdui.ItemCommandListener;
import javax.microedition.lcdui.ItemStateListener;
import javax.microedition.lcdui.StringItem;
import javax.microedition.lcdui.TextField;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;

public class DatosCliente extends MIDlet implements CommandListener,


ItemCommandListener
{
// Referencia a la pantalla
private Display dsp = Display.getDisplay(this);

CIBERTEC CARRERAS PROFESIONALES


108

// Creación de formularios y sus controles


private Form frmNuevoCliente = new Form("Nuevo Cliente");
private TextField txfNombres = new TextField("Nombres", "", 40,
TextField.ANY);
private String astrTipoDocumento[] = {"DNI", "RUC"};
private ChoiceGroup chgTipoDocumento = new ChoiceGroup("Tipo Doc.",
ChoiceGroup.EXCLUSIVE, astrTipoDocumento, null);
private TextField txfDocumento = new TextField("Num. Doc.", "", 11,
TextField.NUMERIC);
private DateField dtfNacimiento = new DateField("Fecha Nacimiento",
DateField.DATE);
private ChoiceGroup chgTipoNegocio = new ChoiceGroup("Tipo Negocio",
ChoiceGroup.POPUP);
private Gauge gauDescuento = new Gauge("Descuento:", true, 50, 0);

private StringItem stiGrabar = new StringItem("", "Grabar",


StringItem.BUTTON);

// Creación de botones
private Command cmdSalir = new Command("Salir", Command.EXIT, 2);
private Command cmdGrabar = new Command("Grabar", Command.ITEM, 2);
private Command cmdNuevoTipo = new Command("Nuevo Tipo", Command.ITEM, 2);

public DatosCliente() {

// Inicializar tipo de negocio


chgTipoNegocio.append("Kiosko", null);
chgTipoNegocio.append("Bodega", null);

/*
Modifica el alineamiento
*/
// El control chgTipoDocumento se contraen para ir en la misma línea
chgTipoDocumento.setLayout(Item.LAYOUT_SHRINK | Item.LAYOUT_2);
txfDocumento.setLayout(Item.LAYOUT_SHRINK | Item.LAYOUT_2);

// El Gauge se expande para ocupar todo el ancho de la pantalla


gauDescuento.setLayout(Item.LAYOUT_EXPAND | Item.LAYOUT_VEXPAND);

// El boton Grabar se alinea al centro


stiGrabar.setLayout(Item.LAYOUT_CENTER);

// Agregar los controles al formulario


frmNuevoCliente.append(txfNombres);
frmNuevoCliente.append(chgTipoDocumento);
frmNuevoCliente.append(txfDocumento);
frmNuevoCliente.append(dtfNacimiento);
frmNuevoCliente.append(chgTipoNegocio);
frmNuevoCliente.append(gauDescuento);
frmNuevoCliente.append(stiGrabar);

// Agregar botones del formulario


frmNuevoCliente.addCommand(cmdSalir);
frmNuevoCliente.setCommandListener(this);

// Agregar botones del control chgTipoNegocio


chgTipoNegocio.addCommand(cmdNuevoTipo);
chgTipoNegocio.setItemCommandListener(this);

// Agregar botones del control stiGrabar


stiGrabar.addCommand(cmdGrabar);
stiGrabar.setItemCommandListener(this);
stiGrabar.setDefaultCommand(cmdGrabar);

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 109

protected void destroyApp(boolean arg0) {


}

protected void pauseApp() {


}

protected void startApp() throws MIDletStateChangeException {


dsp.setCurrent(frmNuevoCliente);
}

public void commandAction(Command c, Displayable d) {


// TODO Auto-generated method stub

if(c == cmdSalir)
{
destroyApp(false);
notifyDestroyed();
}
}

public void commandAction(Command c, Item i) {


// TODO Auto-generated method stub
if(c == cmdGrabar)
{
// Concatena un mensaje con todos los datos
String strMensaje = "Datos ingresados"
+ "\n\rNombres: " + txfNombres.getString()
+ "\n\rTipo Documento: "
+ chgTipoDocumento.getString(chgTipoDocumento.getSelectedIndex())
+ "\n\rNumeroDocumento: " + txfDocumento.getString()
+ "\n\rFecha Nacimiento: "
+ ((dtfNacimiento.getDate() == null)? "":
dtfNacimiento.getDate().toString())
+ "\n\rTipoNegocio: "
+ chgTipoNegocio.getString(chgTipoNegocio.getSelectedIndex())
+ "\n\rDescuento: " + gauDescuento.getValue();

// Muestra un Alert con todos los mensajes


Alert alt = new Alert("Cliente registrado", strMensaje, null,
AlertType.INFO);
dsp.setCurrent(alt);
}
else if(c == cmdNuevoTipo)
{
// Si se pulso el boton NuevoTipo, mostrar un mensaje informativo
Alert alt = new Alert("Informacion", "No disponible", null,
AlertType.INFO);
dsp.setCurrent(alt);
}
}
}

CIBERTEC CARRERAS PROFESIONALES


110

Resumen

 La clase DateField es una subclase de Item especializada en el ingreso de datos


tipo fecha, hora o fecha/hora.

 La clase Gauge es una subclase de Item que adopta la forma de una barra de
estado, que puede o no ser modificada por el usuario.

 La clase ImageItem es similar a una clase Image, con la diferencia de estar dentro
del formulario. También, puede ser usada para simular un botón o hyperlink dentro
de un formulario.

 Desde un objeto de tipo Item, también se pueden controlar las pulsaciones del
teclado utilizando la interfaz ItemCommandListener.

 Usando los métodos setPreferredSize y setLayout, se puede controlar el tamaño y


la alineación de un control Item, cualquiera que sea.

 Si desea saber más acerca de estos temas, puede consultar las siguientes
páginas:

 http://www.mailxmail.com/curso/informatica/j2me
 http://programacion.com/java/tutorial/ags_j2me/
 http://leo.ugr.es/J2ME/MIDP/enlaces.htm

 Referencia oficial de Java (en inglés)

 http://java.sun.com/javame/reference/apis/jsr118/

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 111

UNIDAD DE
APRENDIZAJE

3
SEMANA

11

ALMACENAMIENTO DE DATOS
LOGRO DE LA UNIDAD DE APRENDIZAJE

• Reconoce la necesidad de almacenar información en un MIDlet, utilizando


memoria persistente en forma de Record Store

• Desarrolla MIDlet que permitan realizar el mantenimiento completo de


registros basado en Record Store.

• Desarrolla MIDlet permita todavía realizar búsquedas u ordenamiento de


registros en un Record Store

• Maneja las comunicaciones vía HTTP.

TEMARIO

• Introducción al almacenamiento de datos


• Manejo de almacenes de datos: Clase RecordStore

ACTIVIDADES PROPUESTAS

• Crea la aplicación especificada en el punto , que permite el ingreso,


visualizacion y eliminación de datos usando RecordStores.

CIBERTEC CARRERAS PROFESIONALES


112

1. Introducción

J2ME proporciona un mecanismo a los MIDlets que les permite almacenar


datos de forma persistente para su futura recuperación. Este mecanismo está
implementado sobre una pequeña base de datos basada en registros que
llamaremos Record Management System o RMS (Sistema de gestión de
registros).
La información será guardada en el dispositivo en una zona de memoria
dedicada para este propósito. La cantidad de memoria, la zona asignada y los
mecanismos de integridad dependerán de cada dispositivo móvil
El concepto que tiene Java Micro Edition para manejar los datos se muestra en la
figura 1-1:

Figura 1-1. Relación del MIDlet con el RMS

Como se muestra en la gráfica, el MIDlet es el que se encarga de acceder al


RMS en el se encontrarán almacenados los RecordStore. Cabe señalar que
puede existir más de un RecordStore por RMS y, a su vez, pueden ser accesados
por más de un MIDlet siempre y cuando estos no se encuentren restringidos por el
MIDlet creador.

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 113

Figura 1-2. Relación del MIDlet con el RecordStore

2. Clase RecordStore

2.1. Definición

La clase RecordStore permite administrar la creación, acceso y eliminación de


los diferentes RecordStore. Para ello, solo necesitamos crear una sola variable, la
cual podrá acceder a todos los registros almacenados en el RMS. Esta clase no
cuenta con un método constructor, por lo que la creación de cada RecordStore
recae sobre el método openRecordStore(). Los registros se almacenan en forma
de arreglo de bytes.

2.2. Métodos

2.2.1 openRecordStore()
• Definición
public static RecordStore openRecordStore(String nombre,
boolean crear)
public static RecordStore openRecordStore(String nombre,
boolean crear, int modo, boolean editar)
public static RecordStore openRecordStore(String nombre,
String vendedor, String midletSuite)

• Descripción
Permite crear un RecordStore. Sus parámetros son:
o nombre: Nombre del RecordStore
o crear: Dato lógico que indica si el RecordStore será creado en
caso no existiera
o modo: Dato entero que puede tener los valores indicados en la
tabla 2-1.

CIBERTEC CARRERAS PROFESIONALES


114

o editar: Dato lógico que indica si el RecordStore podrá ser


modificado
o vendedor: Dato que indica el vendedor del MIDletSuite, al cual
pertenece el RecordStore
o vendedor: Dato que indica el nombre del MIDletSuite, al cual
pertenece el RecordStore

Constante Descripción
RecordStore.AUTHMODE_ANY Acceso desde cualquier MIDlet Suite
RecordStore.AUTHMODE_PRIVATE Acceso desde el MIDlet Suite creador
Tabla 2-1. Constantes de modo de acceso a un RecordStore

2.2.2 deleteRecordStore()
• Definición
public static void deleteRecordStore(String nombre)

• Descripción
Elimina el RecordStore especificado.

2.2.3 listRecordStores()
• Definición
public static String [] listRecordStores()

• Descripción
Devuelve un arreglo con los nombre de los RecordStores
disponibles.

2.2.4 addRecord()
• Definición
public int addRecord(byte [] datos, int inicio, int longitud)

• Descripción
Permite agregar un nuevo registro al RecordStore abierto. Para
ingresar un registro, este debe estar en forma de arreglo de bytes y se
pasara la posición inicial desde donde se insertará el dato y la cantidad
de bytes que ingresarán en el registro. El método devolverá el
identificador del registro ingresado.

2.2.5 setRecord()
• Definición
public void setRecord(int id, byte [] datos, int inicio,
int longitud)

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 115

• Descripción
Permite modificar el registro identificado con el parámetro “id” en el
RecordStore abierto. Para esto, el registro debe ingresar en forma de
arreglo de bytes y se pasará la posición inicial desde donde se insertará
el dato y la cantidad de bytes que ingresarán en el registro.

2.2.6 deleteRecord()
• Definición
public void deleteRecord(int id)

• Descripción
Elimina el registro identificado con el valor parámetro “id”.

2.2.7 getRecord()
• Definición
public byte [] getRecord(int id)

• Descripción
Devuelve el registro identificado con el valor parámetro “id”.

2.2.8 closeRecordStore()
• Definición
public void closeRecordStore()

• Descripción
Cierra el RecordStore.

2.2.9 getNumRecords()
• Definición
public int getNumRecords()

• Descripción
Devuelve la cantidad de registros que se encuentra almacenados en
el RecordStore.

2.2.10 getSize()
• Definición
public int getSize()

• Descripción
Retorna el tamaño de memoria utilizado por el RecordStore.

CIBERTEC CARRERAS PROFESIONALES


116

2.2.11 getSizeAvailable()
• Definición
public int getSizeAvailable()

• Descripción
Retorna el tamaño de memoria disponible.

3. Ejemplos

3.1. Aplicación Agenda

3.1.1 Enunciado
Construir una aplicación que realice lo siguiente:
• Mostrar un menú con el título “Agenda” y las siguientes opciones:
o Agregar, que carga una ventana para agregar nuevos registros
o Buscar, que carga una ventana para buscar y eliminar registros por su
identificador
• La ventana “Agregar” debe permitir el ingreso de 3 datos:
o Nombre (Alfanumérico, 50 caracteres)
o Email (correo electrónico, 50 caracteres)
o Teléfono (teléfono, 14 dígitos)
Además debe tener 3 botones:
o Registrar: Que grabará el registro en un RecordStore, mostrando en
una ventana el resultado de la operación y el identificador del registro
o Menú: Que regresa al menú inicial
o Próximo: Que limpia el valor de los controles
• La ventana “Buscar” debe permitir el ingreso de 1 dato:
o Identificador (Numérico, 3 dígitos)
Además debe tener 3 botones:
o Eliminar: Que eliminará el registro en el RecordStore usando el
identificador ingresado, mostrando en una ventana el resultado de la
operación
o Menú: Que regresa al menú inicial
o Buscar: Que busca el registro en el RecordStore usando el
identificador ingresado, mostrando el valor del registro en cada control,
o mostrando un mensaje indicando que el registro no existe
• La figura 3-1 indica como deberá verse la pantalla.

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 117

Figura 3-1. Ventana de la aplicación Agenda

3.1.2 Código
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.Form;
import javax.microedition.lcdui.Item;
import javax.microedition.lcdui.ItemCommandListener;
import javax.microedition.lcdui.List;
import javax.microedition.lcdui.StringItem;
import javax.microedition.lcdui.TextField;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
import javax.microedition.rms.RecordEnumeration;
import javax.microedition.rms.RecordStore;
import javax.microedition.rms.RecordStoreException;
import javax.microedition.rms.RecordStoreNotOpenException;

public class Agenda extends MIDlet implements CommandListener,


ItemCommandListener
{
// Referencia a la pantalla
private Display dsp = Display.getDisplay(this);

CIBERTEC CARRERAS PROFESIONALES


118

// Creacion de menu
private List lstMenu = new List("Agenda", List.IMPLICIT,
new String [] {"Agregar", "Buscar", "Salir"}, null);

// Creacion de formulario Agregar y sus controles


private Form frmAltas = new Form("Agregar");
private TextField txfNombre = new TextField("Nombre", "", 50,
TextField.ANY);
private TextField txfEmail = new TextField("Email", "", 50,
TextField.EMAILADDR);
private TextField txfTelefono = new TextField("Telefono", "", 14,
TextField.PHONENUMBER);
private StringItem stiRegistrar = new StringItem("", "Registrar",
Item.BUTTON);

// Creacion de formulario Buscar y sus controles


private Form frmBajas = new Form("Buscar");
private TextField txfId = new TextField("Identificador", "", 3,
TextField.NUMERIC);
private StringItem stiNombre = new StringItem("Nombre", "", Item.PLAIN);
private StringItem stiEmail = new StringItem("Email", "", Item.PLAIN);
private StringItem stiTelefono = new StringItem("Telefono", "",
Item.PLAIN);
private StringItem stiEliminar = new StringItem("", "Eliminar",
Item.BUTTON);

// Creacion de botones
private Command cmdMenu = new Command("Menu", Command.BACK, 2);
private Command cmdRegistrar = new Command("Registrar", Command.OK, 2);
private Command cmdProximo = new Command("Proximo", Command.OK, 2);
private Command cmdEliminar = new Command("Eliminar", Command.CANCEL, 2);
private Command cmdBuscar = new Command("Buscar", Command.CANCEL, 2);

// Delimitador usado para separar los campos de cada registro


private final String DELIMITADOR = "%*%";

public Agenda() {
// Para procesamiento de eventos del men
lstMenu.setCommandListener(this);

// Agregar los controles al Agregar


stiRegistrar.addCommand(cmdRegistrar);
stiRegistrar.setDefaultCommand(cmdRegistrar);
stiRegistrar.setItemCommandListener(this);
stiRegistrar.setLayout(Item.LAYOUT_CENTER);
frmAltas.append(txfNombre);
frmAltas.append(txfEmail);
frmAltas.append(txfTelefono);
frmAltas.append(stiRegistrar);
frmAltas.addCommand(cmdMenu);
frmAltas.addCommand(cmdProximo);
frmAltas.setCommandListener(this);

// Agregar los controles al Buscar


stiEliminar.addCommand(cmdEliminar);
stiEliminar.setDefaultCommand(cmdEliminar);
stiEliminar.setItemCommandListener(this);
stiEliminar.setLayout(Item.LAYOUT_CENTER);
frmBajas.append(txfId);
frmBajas.append(stiNombre);
frmBajas.append(stiEmail);
frmBajas.append(stiTelefono);
frmBajas.append(stiEliminar);
frmBajas.addCommand(cmdMenu);
frmBajas.addCommand(cmdBuscar);
frmBajas.setCommandListener(this);

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 119

protected void destroyApp(boolean arg0) {


}

protected void pauseApp() {


}

protected void startApp() throws MIDletStateChangeException {


// Establecer ventana inicial
dsp.setCurrent(lstMenu);
}

public void commandAction(Command c, Displayable d) {


// Procesamiento de eventos
if(c == List.SELECT_COMMAND)
{
// Procesamiento de eventos del menu
switch(lstMenu.getSelectedIndex())
{
case 0:
// Opcion agregar
limpiarControlesAltas();
dsp.setCurrent(frmAltas);
break;
case 1:
// Opcion buscar y eliminar
limpiarControlesBajas();
dsp.setCurrent(frmBajas);
break;
case 2:
// Opcion Salir
destroyApp(false);
notifyDestroyed();
break;
}
}
else if(c == cmdMenu)
{
// Regresar al menu inicial
dsp.setCurrent(lstMenu);
}
else if(c == cmdProximo)
{
// Limpiar controles del formulario frmAltas
limpiarControlesAltas();
}
else if(c == cmdBuscar)
{
// Realizar la busqueda
if(!llenarControlesBajas(Integer.parseInt(txfId.getString())))
{
// Si la busqueda no tuvo exito, mostrar mensaje
Alert altMensaje = new Alert("Error", "Registro no existe", null,
AlertType.ERROR);
dsp.setCurrent(altMensaje);
}
}
}

private boolean llenarControlesBajas(int idRegistro) {


// Metodo que busca un registro y muestra sus datos
RecordStore rs = null;
try
{
// Crear el RecordStore y lee el registro indicado en el parametro
rs = RecordStore.openRecordStore("Agenda", true);
byte abytRegistro[] = rs.getRecord(idRegistro);

// Convierte el registro a una cadena para dividirlo en sus campos

CIBERTEC CARRERAS PROFESIONALES


120

String strRegitro = new String(abytRegistro);


int intIndiceEmail = strRegitro.indexOf(DELIMITADOR)
+ DELIMITADOR.length();
int intIndiceTelefono = strRegitro.indexOf(DELIMITADOR,
intIndiceEmail) + DELIMITADOR.length();
String strNombre = strRegitro.substring(0, intIndiceEmail
- DELIMITADOR.length());
String strEmail = strRegitro.substring(intIndiceEmail,
intIndiceTelefono - DELIMITADOR.length());
String strTelefono = strRegitro.substring(intIndiceTelefono);

// Muestra los datos obtenidos


stiNombre.setText(strNombre);
stiEmail.setText(strEmail);
stiTelefono.setText(strTelefono);

// Devuelve verdadero si la busqueda fue conforme


return true;
}
catch(Exception ex)
{
// Imprime el error en la consola para depuracion
ex.printStackTrace();
}
finally
{
// Cierra el RecordStore
cerrarRecordStore(rs);
}
// Devuelve falso si la busqueda no fue exitosa o hubo un error
return false;
}

private void limpiarControlesAltas() {


// Inicializa los controles del formulario frmAltas
txfNombre.setString("");
txfEmail.setString("");
txfTelefono.setString("");
}

private void limpiarControlesBajas() {


// Inicializa los controles del formulario frmBajas
stiEmail.setText("");
stiNombre.setText("");
stiTelefono.setText("");
}

private void cerrarRecordStore(RecordStore rs)


{
// Cierra el RecordStore pasado como parametro
if(rs != null)
{
try
{
rs.closeRecordStore();
}
catch (Exception ex)
{
// Imprime el error en la consola para depuracion
ex.printStackTrace();
}
}
}

public void commandAction(Command c, Item i) {


// Procesamiento de eventos
RecordStore rs = null;
if(c == cmdRegistrar)

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 121

{
// Grabacion de un registro
try
{
// Se crea una cadena con los valores de todos los campos
String strRegistro = txfNombre.getString() + DELIMITADOR
+ txfEmail.getString() + DELIMITADOR
+ txfTelefono.getString();

// Creacion del RecordStore y adicion del registro


rs = RecordStore.openRecordStore("Agenda", true);
int numRegistro = rs.addRecord(strRegistro.getBytes(), 0,
strRegistro.getBytes().length);

// Mostrar mensaje con el resultado


Alert altMensaje = new Alert("Informacion", "Registro ingresado "
+ numRegistro, null, AlertType.INFO);
dsp.setCurrent(altMensaje);
}
catch(Exception ex)
{
// Imprime el error en la consola para depuracion
ex.printStackTrace();
}
finally
{
// Cerrar RecordStore
cerrarRecordStore(rs);
}
}
else if(c == cmdEliminar)
{
// Eliminacion de un registro
// Esta variable nos indicara si se elimino correctamente o no
boolean blnEliminado = false;

try
{
// Se obtiene el identificador ingresado
int idRegistro = Integer.parseInt(txfId.getString());

// Se abre el RecordStore y se elimina el registro


rs = RecordStore.openRecordStore("Agenda", true);
rs.deleteRecord(idRegistro);

// Se limpian los controles del formulario frmBajas


limpiarControlesBajas();

// Se actualize el valor de la variable


blnEliminado = true;
}
catch(Exception ex)
{
// Imprime el error en la consola para depuracion
ex.printStackTrace();
}
finally
{
// Cerrar RecordStore
cerrarRecordStore(rs);
}

// Se muestra un mensaje de exito o error segun el valor de la


// variable blnEliminado
Alert altMensaje = new Alert("Resultado");
if(blnEliminado)
{
altMensaje.setString("Registro eliminado correctamente");

CIBERTEC CARRERAS PROFESIONALES


122

altMensaje.setType(AlertType.INFO);
}
else
{
altMensaje.setString("Se produjo un error ");
altMensaje.setType(AlertType.ERROR);
}
dsp.setCurrent(altMensaje);
}
}
}

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 123

Resumen

 Para almacenamiento de datos, la plataforma J2ME proporciona una base de


datos basada en registros conocida como RMS. El RMS está conformado por
conjuntos de registros o RecordStores, los cuales almacenan los datos en registros
conteniendo arreglos de bytes.

 Existe un esquema de seguridad que consiste en que sólo puede acceder al


RecordStore el MIDlet que lo creó y los MIDlets pertenecientes al mismo MIDlet
suite. Para que otros MIDlets puedan acceder, el MIDlet creador debe especificar
dicho permiso al momento en que el RecordStore sea creado.

 La forma correcta de usar un RecordStore es abrirlo, realizar alguna de las


operaciones conocidas (agregar, modificar, eliminar y leer) y cerrar.

 Si desea saber más acerca de estos temas, puede consultar las siguientes
páginas:

 http://www.mailxmail.com/curso/informatica/j2me
 http://programacion.com/java/tutorial/ags_j2me/
 http://leo.ugr.es/J2ME/MIDP/enlaces.htm

 Referencia oficial de Java (en inglés)

 http://java.sun.com/javame/reference/apis/jsr118/

CIBERTEC CARRERAS PROFESIONALES


124

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 125

UNIDAD DE
APRENDIZAJE

3
SEMANA

12

MANEJO AVANZADO DE DATOS 1


LOGRO DE LA UNIDAD DE APRENDIZAJE

• Reconoce la necesidad de almacenar información en un MIDlet, utilizando


memoria persistente en forma de Record Store

• Desarrolla MIDlet que permitan realizar el mantenimiento completo de


registros basado en Record Store.

• Desarrolla MIDlet permita todavía realizar búsquedas u ordenamiento de


registros en un Record Store

TEMARIO

• Diseño del esquema de almacenamiento


• Recorrido de un RecordStore: Clase RecordEnumeratio

ACTIVIDADES PROPUESTAS

• Crea la aplicación especificada en el punto 3, que permite el recorrido de un


RecordStore usando la interfaz RecordEnumeration.

CIBERTEC CARRERAS PROFESIONALES


126

1. Estrategia de almacenamiento
Al diseñar la forma de almacenar los datos en un RecordStore, tomar en cuenta
que los datos se almacenan en forma de arreglo de bytes. No existen los tipos de
datos conocidos en una base de datos.
Al grabar los registros se sugiere:
• Convertir los datos a String;
• Concatenar todos los datos, separándolos por un delimitador constante;
• El valor de dicho delimitador es arbitrario, pero es necesario asegurarse que dicho
delimitador no exista en los elementos;
• El dato de tipo String que se haya obtenido se convierte a arreglo de bytes con el
método getBytes(), y dicho valor será el que finalmente se grabe en el
RecordStore.
Al leer los datos, realizar la operación inversa:
• Obtener los datos como arreglo de bytes y convertirlos en String
• Dividir los datos de acuerdo al delimitador constante
• Cada dato obtenido se convierte al tipo que corresponda

2. Clase RecordEnumeration

2.1. Definición

La clase RecordEnumeration se utiliza para recorrer un RecordStore. Posee los


métodos para realizar un recorrido en ambas direcciones. Asimismo, permite
realizar un filtrado para recorrer solamente los registros que cumplan una
condición, y especificar un criterio de ordenamiento para realizar el recorrido.

2.2. Creación

Para obtener crear un objeto de tipo RecordEnumeration, se debe usar el


método enumerateRecords() del objeto RecordStore. La definición del método es
la siguiente:
RecordEnumeration enumerateRecords (RecordFilter rf, RecordComparator rc,
boolean actualizar)

Donde:
• rf: Referencia a un filtro. Usado para recorrer la lista filtrada. Si es null, se
recorrerá el RecordStore sin ningun filtro, es decir, se recorrerá toda la lista.

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 127

• rc: Referencia a un comparador. Usado para recorrer la lista ordenada. Si es


null, se recorrerá el RecordStore sin ningún ordenamiento.
• actualizar: Si es verdadero el RecordStore, se actualizará ante un cambio en
el RecordStore por otro proceso. Si es falso el RecordStore, no reflejará los
cambios. Este último es el que consume menos recursos, por lo que es más
frecuente.

2.3. Métodos

2.3.1 hasNextElement()
• Definición
public bolean hasNextElement()

• Descripción
Devuelve verdadero si existe un elemento siguiente, falso si no
existe, es decir, si se ha llegado al final del RecordStore.

2.3.2 hasPreviousElement()
• Definición
public boolean hasPreviousElement()

• Descripción
Devuelve verdadero si existe un elemento anterior, falso si no existe,
es decir, si se ha llegado al comienzo del RecordStore.

2.3.3 nextRecord()
• Definición
public byte [] nextRecord()

• Descripción
Devuelve un arreglo de bytes conteniendo el siguiente registro en el
RecordStore.

2.3.4 nextRecordId()
• Definición
public int nextRecordId()

• Descripción
Devuelve un identificador del siguiente registro en el RecordStore.

2.3.5 previousRecord()
• Definición
public byte [] previousRecord()

CIBERTEC CARRERAS PROFESIONALES


128

• Descripción
Devuelve un arreglo de bytes conteniendo el registro anterior del
RecordStore.

2.3.6 previousRecordId()
• Definición
public int previousRecordId()

• Descripción
Devuelve un identificador del registro anterior del RecordStore.

2.4. Ejemplos de recorrido de un RecordStore

2.4.1 Recorrido usando nextRecord


Tiene la desventaja que no permite saber el identificador del registro,
que puede ser útil para realizar otras operaciones sobre el RecordStore.
try
{
RecordEnumeration re = rs.enumerateRecords(null, null, false);
while(re.hasNextElement())
{
byte [] datos = re.nextRecord();
/* procesamiento */
}
}
catch(Exception ex)
{
}

2.4.2 Recorrido usando nextRecordId


Esta forma permite conocer el identificador del registro.
try
{
RecordEnumeration re = rs.enumerateRecords(null, null, false);
while(re.hasNextElement())
{
int registro = re.nextRecordId();
byte [] datos = rs.getRecord(registro);
/* procesamiento */
}
}
catch(Exception ex)
{
}

3. Ejemplos

3.1. Aplicación AgendaRMS

3.1.1 Enunciado
Construir una aplicación que realice lo siguiente:

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 129

• Mostrar un formulario con el título “Agregar cita” y que permita ingresar los
siguientes datos:
o Fecha y hora
o Detalle de la cita (Alfanumérico, 100 caracteres)
o Tipo, que puede ser uno de los siguientes: Amigos, Familia, Trabajo,
Personal
Adicionalmente, debe tener 3 botones:
o Salir: para salir de la aplicación
o Agregar: para agregar la cita a un RecordStore y mostrar un mensaje
con el resultado de la operación
o Ver Lista: Para mostrar una lista de los registros ingresados
• La lista de los registros ingresados debe tener dos botones:
o Volver: para regresar a la ventana inicial
o Eliminar: Para eliminar los registros seleccionados y mostrar un
mensaje con el resultado de la operación
• La figura 3-1 indica cómo deberá verse la pantalla.

Figura 3-1. Ventana de la aplicación AgendaRMS

CIBERTEC CARRERAS PROFESIONALES


130

3.1.2 Código
Archivo AgendaRMS.java

import java.util.Date;
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.AlertType;
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.Item;
import javax.microedition.lcdui.ItemCommandListener;
import javax.microedition.lcdui.List;
import javax.microedition.lcdui.StringItem;
import javax.microedition.lcdui.TextField;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
import javax.microedition.rms.RecordEnumeration;
import javax.microedition.rms.RecordStore;

public class AgendaRMS extends MIDlet implements CommandListener,


ItemCommandListener
{
private Display dsp = Display.getDisplay(this);

// Un formulario para agregar las citas


private Form frm = new Form("Agregar cita");
private TextField txfItem = new TextField("Detalle", "", 100,
TextField.ANY);
private DateField dtfCita = new DateField("A las", DateField.DATE_TIME);
private String astrTiposCita[] =
{"Amigos", "Familia", "Trabajo", "Personal"};
private ChoiceGroup chgTipoCita = new ChoiceGroup("Tipo",
ChoiceGroup.EXCLUSIVE, astrTiposCita, null);
private StringItem stiAgregar = new StringItem("", "Agregar", Item.BUTTON);
private StringItem stiSalir = new StringItem("", "Salir", Item.BUTTON);
private Command cmdSalir = new Command("Salir", Command.ITEM, 2);
private Command cmdVerLista = new Command("Ver Lista", Command.OK, 2);
private Command cmdAgregar = new Command("Agregar", Command.ITEM, 2);

// Una lista para ver las citas


private List lst = new List("Citas", List.MULTIPLE);
private Command cmdEliminar = new Command("Eliminar", Command.ITEM, 2);
private Command cmdVolver = new Command("Volver", Command.BACK, 2);

private final String DELIMITADOR = "*/*";

public AgendaRMS() {
// Controles del formulario
stiAgregar.addCommand(cmdAgregar);
stiAgregar.setItemCommandListener(this);
stiAgregar.setDefaultCommand(cmdAgregar);
stiSalir.addCommand(cmdSalir);
stiSalir.setItemCommandListener(this);
stiSalir.setDefaultCommand(cmdSalir);
frm.append(dtfCita);
frm.append(txfItem);
frm.append(chgTipoCita);
frm.append(stiSalir);
frm.append(stiAgregar);

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 131

frm.addCommand(cmdVerLista);
frm.setCommandListener(this);

// Controles de la lista
lst.addCommand(cmdEliminar);
lst.addCommand(cmdVolver);
lst.setCommandListener(this);
}

protected void destroyApp(boolean arg0) {


}

protected void pauseApp() {


}

protected void startApp() throws MIDletStateChangeException {


dsp.setCurrent(frm);
}

public void commandAction(Command c, Displayable d) {


// Codigo para los botones situados en la parte inferior de las ventanas
if (c == cmdVerLista)
{
leerRegistros();
dsp.setCurrent(lst);
}
else if(c == cmdEliminar)
{
int numeroEliminados = eliminarRegistros();
leerRegistros();
Alert alt = new Alert("Resultado", "Registros eliminados "
+ numeroEliminados, null, AlertType.INFO);
dsp.setCurrent(alt, lst);
}
else if(c == cmdVolver)
{
dsp.setCurrent(frm);
}
}

public void commandAction(Command c, Item i) {


// Codigo para los botones situados dentro del formulario
if(c == cmdAgregar)
{
Date date = new Date();
if(dtfCita.getDate() != null
&& !txfItem.getString().equals(""))
{
int numRegistro = agregarCita();
Alert alt = new Alert("Resultado", "Cita grabada numero "
+ numRegistro, null, AlertType.INFO);
dsp.setCurrent(alt,frm);
}
else
{
Alert alt = new Alert("Error", "Datos no validos", null,
AlertType.INFO);
dsp.setCurrent(alt,frm);
}
}
else if(c == cmdSalir)
{
destroyApp(false);
notifyDestroyed();
}
}

private int agregarCita()

CIBERTEC CARRERAS PROFESIONALES


132

{
RecordStore rs = null;
try
{
rs = RecordStore.openRecordStore("Agenda", true);
// <FECHAHORA><D><DETALLE><D><TIPO>
String strRegistro = String.valueOf(dtfCita.getDate().getTime())
+ DELIMITADOR + txfItem.getString()
+ DELIMITADOR + chgTipoCita.getSelectedIndex();

System.out.println(strRegistro);

int numRegistro = rs.addRecord(strRegistro.getBytes(), 0,


strRegistro.getBytes().length);
return numRegistro;
}
catch(Exception ex)
{
}
finally
{
cerrarRecordStore(rs);
}
return -1;
}

private void leerRegistros()


{
// Llenar la lista lst
lst.deleteAll();
RecordStore rs = null;
try
{
rs = RecordStore.openRecordStore("Agenda", true);
RecordEnumeration re = rs.enumerateRecords(null, null, false);
while(re.hasNextElement())
{
int numRegistro = re.nextRecordId();
byte abytRegistro[] = rs.getRecord(numRegistro);
String strRegistro = new String(abytRegistro);
CitaBean cita = new CitaBean(numRegistro, strRegistro,
DELIMITADOR);
System.out.println(strRegistro);
lst.append(numRegistro + ":" + cita.getStringFecha()
+ " " + cita.getDetalle()
+ " " + chgTipoCita.getString(cita.getTipoCita()), null);
}
}
catch(Exception ex)
{
}
finally
{
cerrarRecordStore(rs);
}
}

private int eliminarRegistros()


{
// Metodo que borra registros
RecordStore rs = null;
int contador = 0;
try
{
rs = RecordStore.openRecordStore("Agenda", true);
// Recorre la lista buscando los registros seleccionados
for(int i = 0; i < lst.size(); i ++)
{

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 133

if(lst.isSelected(i))
{
// Obtiene el identificador del registro y lo borra
String strRegistro = lst.getString(i);
String strIdRegistro = strRegistro.substring(0,
strRegistro.indexOf(":"));
int idRegistro = Integer.parseInt(strIdRegistro);
System.out.println(idRegistro);
rs.deleteRecord(idRegistro);
contador ++;
}
}
}
catch(Exception ex)
{
}
finally
{
cerrarRecordStore(rs);
}
return contador;
}

private void cerrarRecordStore(RecordStore rs)


{
try
{
rs.closeRecordStore();
}
catch(Exception ex)
{}
}
}

Archivo CitaBean.java

import java.util.Calendar;
import java.util.Date;

public class CitaBean {


private long id;
private Date fecha;
private String detalle;
private int tipoCita;

public CitaBean(long id, String strRegistro, String strDelimitador) {


// Graba el identificador unico
this.id = id;

// Divide una cadena del tipo


// <FECHA><DELIMITADOR><DETALLE><DELIMITADOR><TIPO>
// Ejemplo:
// 2233434343*/*Ir al dentista*/*3

// Obtiene los indices en la cadena donde comienza cada dato


int indFecha = 0;
int indDetalle = strRegistro.indexOf(strDelimitador)
+ strDelimitador.length();
int indTipoCita = strRegistro.indexOf(strDelimitador, indDetalle)
+ strDelimitador.length();
// Obtiene subcadena de la fecha
long time = Long.parseLong(strRegistro.substring(indFecha,
indDetalle - strDelimitador.length()));
this.fecha = new Date(time);
System.out.println(fecha);

CIBERTEC CARRERAS PROFESIONALES


134

// Obtiene subcadena del detalle


this.detalle = strRegistro.substring(indDetalle,
indTipoCita - strDelimitador.length());
System.out.println(detalle);

// Obtiene subcadena del tipo de cita


this.tipoCita = Integer.parseInt(strRegistro.substring(indTipoCita,
strRegistro.length()));
System.out.println(tipoCita);

}
public long getId()
{
return this.id;
}

public Date getFecha()


{
return this.fecha;
}

public String getStringFecha()


{
Calendar calendar = Calendar.getInstance();
calendar.setTime(this.fecha);

// Se formatea la hora y el minuto para que siempre aparezcan 2 digitos


String strHora =
"0" + String.valueOf(calendar.get(Calendar.HOUR_OF_DAY));
strHora = strHora.substring(strHora.length() - 2);

String strMinuto = "0" + String.valueOf(calendar.get(Calendar.MINUTE));


strMinuto = strMinuto.substring(strMinuto.length() - 2);

return String.valueOf(calendar.get(Calendar.DAY_OF_MONTH))
+ "/" + String.valueOf(calendar.get(Calendar.MONTH))
+ "/" + String.valueOf(calendar.get(Calendar.YEAR))
+ " " + strHora
+ ":" + strMinuto;
}

public String getDetalle()


{
return this.detalle;
}

public int getTipoCita()


{
return this.tipoCita;
}
}

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 135

Resumen

 Debido a que el almacenamiento de datos solo soporta arreglo de bytes, se


sugiere convertir los datos que deseemos grabar a una cadena de tipo String
conteniendo todos los datos separados por un delimitador predeterminado.

 Para recorrer un RecordStore, existe la clase RecordEnumeration, que posee los


métodos para realizar un recorrido en ambas direcciones, dando la posibilidad de
filtrar y ordenar los registros obtenidos.

 Si desea saber más acerca de estos temas, puede consultar las siguientes
páginas:

 http://www.mailxmail.com/curso/informatica/j2me
 http://programacion.com/java/tutorial/ags_j2me/
 http://leo.ugr.es/J2ME/MIDP/enlaces.htm

 Referencia oficial de Java (en inglés)

 http://java.sun.com/javame/reference/apis/jsr118/

CIBERTEC CARRERAS PROFESIONALES


136

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 137

UNIDAD DE
APRENDIZAJE

3
SEMANA

13

MANEJO AVANZADO DE DATOS 2


LOGRO DE LA UNIDAD DE APRENDIZAJE

• Reconoce la necesidad de almacenar información en un MIDlet, utilizando


memoria persistente en forma de RecordStore.

• Desarrolla MIDlet que permitan realizar el mantenimiento completo de


registros basado en Record Store.

• Desarrolla MIDlet permita todavía realizar búsquedas u ordenamiento de


registros en un Record Store.

TEMARIO

• Recorrido filtrado de un RecordStore: Interfaz RecordFilter


• Recorrido ordenado de un RecordStore: Interfaz RecordComparator

ACTIVIDADES PROPUESTAS

• Crea la aplicación especificada en el punto 3, que muestra como recorrer un


RecordStore de una manera filtrada y ordenada, usando las interfaces
RecordFilter y RecordComparator.

CIBERTEC CARRERAS PROFESIONALES


138

Interfaz RecordFilter

3.2. Definición

Es una interfaz usada para crear clases que definan un criterio de filtro. Dicho
criterio puede ser usado al recorrer un RecordStore.

3.3. Implementación

Para realizar un recorrido filtrado de un RecordStore se debe realizar lo


siguiente:
1. Crear una clase que implemente la interfaz RecordFilter. La clase que
implemente la interfaz puede ser el MIDlet.
public class MiClase extends MIDlet implements RecordFilter

2. Sobrescribir el método matches() en la clase que implementa la interfaz. Este


método recibe un arreglo de bytes con el registro. El método debe devolver
verdadero si el registro cumple el filtro y falso si no cumple.
public boolean matches(byte[] arg0)
{
// Implementar la lógica que devuelva verdadero o falso
return true;
}

3. Utilizar dicho objeto cuando se inicialice un objeto RecordEnumeration


RecordEnumeration re = rs.enumerateRecords(this, null, false);

Ejemplo:

Este código filtra todos los registros que comiencen por “A”.

public boolean matches(byte[] arg0)


{
// Convertir a String
String registro = new String(arg0);
// Devuelve verdadero cuando el registro
// comienza por “A”
return registro.startsWith(“A");
}

4. Interfaz RecordComparator

4.1. Definición

Es una interfaz usada para crear clases que definan un criterio de


ordenamiento. Dicho criterio puede ser usado al recorrer un RecordStore.

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 139

4.2. Creación

Para realizar un recorrido ordenado de un RecordStore, se debe realizar lo


siguiente:
1. Crear una clase que implemente la interfaz RecordComparator. La clase que
implemente la interfaz puede ser el MIDlet.
public class MiClase extends MIDlet implements RecordComparator

2. Sobrescribir el método compare() en la clase que implementa la interfaz. Este


método recibe dos arreglos de bytes que son dos registros que van a ser
comparados. El método debe devolver una de las constantes definidas en la
tabla 2-1.
public int compare(byte[] arg0, byte[] arg1)
{
// Poner la logica correspondiente
}

Constante Descripción
RecordComparator.PRECEDES Si el primer registro va antes que el segundo
RecordComparator.FOLLOWS Si el primer registro va después que el segundo
RecordComparator.EQUIVALENT Si ambos registros son equivalentes
Tabla 2-1. Constantes devueltas por el método compare

3. Utilizar dicho objeto cuando se inicialice un objeto RecordEnumeration


RecordEnumeration re = rs.enumerateRecords(null, this, false);

Ejemplo:

Este código ordena alfabéticamente de manera ascendente.

public int compare(byte[] arg0, byte[] arg1)


{
String str0 = new String(arg0);
String str1 = new String(arg1);
int retorno = 0;
if(str0.compareTo(str1) < 0) {
retorno = RecordComparator.PRECEDES;
}
else if(str0.compareTo(str1) > 0) {
retorno = RecordComparator.FOLLOWS;
}
else if(str0.compareTo(str1) == 0) {
retorno = RecordComparator.EQUIVALENT;
}
return retorno;
}

5. Ejemplos

5.1. Aplicación AgendaRMS

5.1.1 Enunciado
Modificar la aplicación del capítulo anterior para que realice lo siguiente:

CIBERTEC CARRERAS PROFESIONALES


140

• Mostrar la lista ordenada por la fecha y hora de manera ascendente


• Agregar un botón “Buscar” que cargue una ventana que realice
búsquedas por detalle. Para esto debe mostrar lo siguiente:
o Un control para ingresar un texto cualquiera
o Un botón “Buscar” que realizará la búsqueda y mostrará los resultados
o Una lista dentro del formulario (ChoiceGroup) para mostrar el resultado
de la busqueda
o Adicionalmente, mostrar un botón “Volver” para regresar a la ventana
principal
• La figura 3-1 indica cómo deberá verse la pantalla.

Figura 3-1. Ventana de la aplicación AgendaRMS

5.1.2 Código

Archivo AgendaRMS.java
import java.util.Date;
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.AlertType;
import javax.microedition.lcdui.ChoiceGroup;
import javax.microedition.lcdui.Command;

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 141

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.Item;
import javax.microedition.lcdui.ItemCommandListener;
import javax.microedition.lcdui.List;
import javax.microedition.lcdui.StringItem;
import javax.microedition.lcdui.TextField;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
import javax.microedition.rms.RecordEnumeration;
import javax.microedition.rms.RecordStore;

public class AgendaRMS extends MIDlet implements CommandListener,


ItemCommandListener {
private Display dsp = Display.getDisplay(this);

// Un formulario para agregar las citas


private Form frm = new Form("Agregar cita");
private TextField txfItem = new TextField("Detalle", "", 100,
TextField.ANY);
private DateField dtfCita = new DateField("A las", DateField.DATE_TIME);
private String astrTiposCita[]
= {"Amigos", "Familia", "Trabajo", "Personal"};
private ChoiceGroup chgTipoCita = new ChoiceGroup("Tipo",
ChoiceGroup.EXCLUSIVE, astrTiposCita, null);
private StringItem stiAgregar = new StringItem("", "Agregar", Item.BUTTON);
private StringItem stiSalir = new StringItem("", "Salir", Item.BUTTON);
private Command cmdSalir = new Command("Salir", Command.ITEM, 2);
private Command cmdVerLista = new Command("Ver Lista", Command.OK, 2);
private Command cmdAgregar = new Command("Agregar", Command.ITEM, 2);
private Command cmdVentanaBusqueda = new Command("Buscar", Command.OK, 2);

// Un formulario para realizar las busquedas


private Form frmBuscar = new Form("Buscar");
private TextField txfDetalle = new TextField("Detalle", "", 40,
TextField.ANY);
private StringItem stiBuscar = new StringItem("", "Buscar", Item.BUTTON);
private Command cmdBuscar = new Command("Buscar", Command.ITEM, 2);
private ChoiceGroup chgBusqueda = new ChoiceGroup("Resultado",
ChoiceGroup.MULTIPLE);

// Una lista para ver las citas


private List lst = new List("Citas", List.MULTIPLE);
private Command cmdEliminar = new Command("Eliminar", Command.ITEM, 2);
private Command cmdVolver = new Command("Volver", Command.BACK, 2);

private final String DELIMITADOR = "*/*";

public AgendaRMS() {
// Controles del formulario
stiAgregar.addCommand(cmdAgregar);
stiAgregar.setItemCommandListener(this);
stiAgregar.setDefaultCommand(cmdAgregar);
stiSalir.addCommand(cmdSalir);
stiSalir.setItemCommandListener(this);
stiSalir.setDefaultCommand(cmdSalir);
frm.append(dtfCita);
frm.append(txfItem);
frm.append(chgTipoCita);
frm.append(stiSalir);
frm.append(stiAgregar);
frm.addCommand(cmdVerLista);
frm.addCommand(cmdVentanaBusqueda);
frm.setCommandListener(this);

CIBERTEC CARRERAS PROFESIONALES


142

// Controles de la lista
lst.addCommand(cmdEliminar);
lst.addCommand(cmdVolver);
lst.setCommandListener(this);

// Controles de la ventana de busqueda


stiBuscar.addCommand(cmdBuscar);
stiBuscar.setItemCommandListener(this);
stiBuscar.setDefaultCommand(cmdBuscar);
frmBuscar.append(txfDetalle);
frmBuscar.append(stiBuscar);
frmBuscar.append(chgBusqueda);
frmBuscar.addCommand(cmdVolver);
frmBuscar.setCommandListener(this);
}

protected void destroyApp(boolean arg0) {


}

protected void pauseApp() {


}

protected void startApp() throws MIDletStateChangeException {


dsp.setCurrent(frm);
}

public void commandAction(Command c, Displayable d) {


// Codigo para los botones situados en la parte inferior de las ventanas
if (c == cmdVerLista)
{
// Recorre el RecordStore y llena la lista
leerRegistros();
dsp.setCurrent(lst);
}
else if(c == cmdEliminar)
{
// Elimina los registros seleccionados
int numeroEliminados = eliminarRegistros();

// Vuelve a recorrer el RecordStore y a llenar la lista


leerRegistros();
Alert alt = new Alert("Resultado", "Registros eliminados "
+ numeroEliminados, null, AlertType.INFO);
dsp.setCurrent(alt, lst);
}
else if(c == cmdVolver)
{
dsp.setCurrent(frm);
}
else if(c == cmdVentanaBusqueda)
{
dsp.setCurrent(frmBuscar);
}
}

public void commandAction(Command c, Item i) {


// Codigo para los botones situados dentro del formulario
if(c == cmdAgregar)
{
// Valida y agrega un registro con los datos ingresados
Date date = new Date();
if(dtfCita.getDate() != null
&& !txfItem.getString().equals(""))
{
int numRegistro = agregarCita();
Alert alt = new Alert("Resultado", "Cita grabada numero "
+ numRegistro, null, AlertType.INFO);

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 143

dsp.setCurrent(alt, frm);
}
else
{
Alert alt = new Alert("Error", "Datos no validos", null,
AlertType.INFO);
dsp.setCurrent(alt,frm);
}
}
else if(c == cmdSalir)
{
destroyApp(false);
notifyDestroyed();
}
else if(c == cmdBuscar)
{
buscarRegistros();
}
}

private void buscarRegistros() {


// Borrar la lista chgBusqueda para posteriormente llenarla
chgBusqueda.deleteAll();
RecordStore rs = null;
try
{
// Crea un objeto de una clase que implementa RecordFilter
ComparadorFiltro cf = new ComparadorFiltro(DELIMITADOR,
txfDetalle.getString(), true);
rs = RecordStore.openRecordStore("Agenda", true);

// Recorre el RecordStore de manera filtrada


RecordEnumeration re = rs.enumerateRecords(cf, null, false);
while(re.hasNextElement())
{
int numRegistro = re.nextRecordId();
byte abytRegistro[] = rs.getRecord(numRegistro);
String strRegistro = new String(abytRegistro);
CitaBean cita = new CitaBean(numRegistro, strRegistro,
DELIMITADOR);
System.out.println(strRegistro);

// Agrega los registros a la lista chgBusqueda


chgBusqueda.append(numRegistro + ":" + cita.getStringFecha()
+ " " + cita.getDetalle(), null);
}
}
catch(Exception ex)
{
}
finally
{
cerrarRecordStore(rs);
}
}

private int agregarCita()


{
// Agrega la cita concatenando todos los campos en un solo dato
RecordStore rs = null;
try
{
rs = RecordStore.openRecordStore("Agenda", true);
// <FECHAHORA><D><DETALLE><D><TIPO>
String strRegistro = String.valueOf(dtfCita.getDate().getTime())
+ DELIMITADOR + txfItem.getString()
+ DELIMITADOR + chgTipoCita.getSelectedIndex();

CIBERTEC CARRERAS PROFESIONALES


144

System.out.println(strRegistro);

int numRegistro = rs.addRecord(strRegistro.getBytes(), 0,


strRegistro.getBytes().length);
return numRegistro;
}
catch(Exception ex)
{
}
finally
{
cerrarRecordStore(rs);
}
return -1;
}

private void leerRegistros()


{
// Borra la lista lst para posteriomente llenarla
lst.deleteAll();
RecordStore rs = null;
try
{
// Crea un objeto de una clase que implementa RecordComparator
ComparadorFiltro cf = new ComparadorFiltro(DELIMITADOR, "", true);
rs = RecordStore.openRecordStore("Agenda", true);

// Recorre el RecordStore de manera ordenada


RecordEnumeration re = rs.enumerateRecords(null, cf, false);
while(re.hasNextElement())
{
int numRegistro = re.nextRecordId();
byte abytRegistro[] = rs.getRecord(numRegistro);
String strRegistro = new String(abytRegistro);
CitaBean cita = new CitaBean(numRegistro, strRegistro,
DELIMITADOR);
System.out.println(strRegistro);

// Agrega el dato a la lista lst


lst.append(numRegistro + ":" + cita.getStringFecha()
+ " " + cita.getDetalle(), null);
}
}
catch(Exception ex)
{
}
finally
{
cerrarRecordStore(rs);
}
}

private int eliminarRegistros()


{
// Metodo que borra registros
RecordStore rs = null;
int contador = 0;
try
{
rs = RecordStore.openRecordStore("Agenda", true);
// Recorre la lista buscando los registros seleccionados
for(int i = 0; i < lst.size(); i ++)
{
if(lst.isSelected(i))
{
// Obtiene el identificador del registro y lo borra
String strRegistro = lst.getString(i);

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 145

String strIdRegistro = strRegistro.substring(0,


strRegistro.indexOf(":"));
int idRegistro = Integer.parseInt(strIdRegistro);
System.out.println(idRegistro);
rs.deleteRecord(idRegistro);
contador ++;
}
}
}
catch(Exception ex)
{
}
finally
{
cerrarRecordStore(rs);
}
return contador;
}

private void cerrarRecordStore(RecordStore rs)


{
try
{
rs.closeRecordStore();
}
catch(Exception ex)
{}
}
}

Archivo CitaBean.java

import java.util.Calendar;
import java.util.Date;

public class CitaBean {

private long id;


private Date fecha;
private String detalle;
private int tipoCita;

public CitaBean(long id, String strRegistro, String strDelimitador) {


// Graba el identificador unico
this.id = id;

// Divide una cadena del tipo


// <FECHA><DELIMITADOR><DETALLE><DELIMITADOR><TIPO>
// Ejemplo:
// 2233434343*/*Ir al dentista*/*3

// Obtiene los indices en la cadena donde comienza cada dato


int indFecha = 0;
int indDetalle = strRegistro.indexOf(strDelimitador)
+ strDelimitador.length();
int indTipoCita = strRegistro.indexOf(strDelimitador, indDetalle)
+ strDelimitador.length();

// Obtiene subcadena de la fecha


long time = Long.parseLong(strRegistro.substring(indFecha,
indDetalle - strDelimitador.length()));
this.fecha = new Date(time);
System.out.println(fecha);
// Obtiene subcadena del detalle
this.detalle = strRegistro.substring(indDetalle,
indTipoCita - strDelimitador.length());
System.out.println(detalle);

CIBERTEC CARRERAS PROFESIONALES


146

// Obtiene subcadena del tipo de cita


this.tipoCita = Integer.parseInt(strRegistro.substring(indTipoCita,
strRegistro.length()));
System.out.println(tipoCita);
}
public long getId()
{
return this.id;
}

public Date getFecha()


{
return this.fecha;
}

public String getStringFecha()


{
Calendar calendar = Calendar.getInstance();
calendar.setTime(this.fecha);

return cerosIzquierda(String.valueOf(calendar.get(Calendar.DAY_OF_MONTH)))
+ "/" + cerosIzquierda(String.valueOf(calendar.get(Calendar.MONTH)+1))
+ "/" + String.valueOf(calendar.get(Calendar.YEAR))
+ " " + cerosIzquierda(String.valueOf(calendar.get(Calendar.HOUR_OF_DAY)))
+ ":" + cerosIzquierda(String.valueOf(calendar.get(Calendar.MINUTE)));

private String cerosIzquierda(String cadena)


{
// Metodo para formatear los digitos de la fecha y hora
// para que siempre tengan dos digitos
String strResultado = "00" + cadena;
return strResultado.substring(strResultado.length() - 2);
}

public String getDetalle()


{
return this.detalle;
}

public int getTipoCita()


{
return this.tipoCita;
}
}

Archivo ComparadorFiltro.java

import javax.microedition.rms.RecordComparator;
import javax.microedition.rms.RecordFilter;

public class ComparadorFiltro implements RecordComparator, RecordFilter {

private String strDelimitador, strFiltro;


private boolean blnAscendente;

public ComparadorFiltro(String strDelimitador, String strFiltro,


boolean blnAscendente) {
this.strDelimitador = strDelimitador;
this.strFiltro = strFiltro;
this.blnAscendente = blnAscendente;
}

public int compare(byte[] arg0, byte[] arg1) {


// Metodo propio de la interfaz RecordComparator
// Debe comparar los registros arg0 y arg1 y devolver un valor que

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 147

// indique cual registro va antes en el ordenamiento o si son iguales


try
{
String strRegistro1 = new String(arg0);
String strRegistro2 = new String(arg1);
// <FECHA><D><DETALLE><D><TIPO>
String strFecha1 = strRegistro1.substring(0,
strRegistro1.indexOf(strDelimitador));
String strFecha2 = strRegistro2.substring(0,
strRegistro2.indexOf(strDelimitador));
long lngFecha1 = Long.parseLong(strFecha1);
long lngFecha2 = Long.parseLong(strFecha2);
if(blnAscendente)
{
if(lngFecha1 < lngFecha2)
return RecordComparator.PRECEDES;
else if(lngFecha1 > lngFecha2)
return RecordComparator.FOLLOWS;
}
else
{
if(lngFecha1 < lngFecha2)
return RecordComparator.FOLLOWS;
else if(lngFecha1 > lngFecha2)
return RecordComparator.PRECEDES;
}
}
catch(Exception ex)
{
ex.printStackTrace();
}
return RecordComparator.EQUIVALENT;
}

public boolean matches(byte[] arg0) {


// Metodo propio de la interfaz RecordFilter
// Debe verificar si el registro arg0 va a ser mostrado
// y devolver un valor Verdadero o Falso que lo indique

// Estructura del registro:


// <FECHA><D><DETALLE><D><TIPO>
String strRegistro = new String(arg0);
int intInicio = strRegistro.indexOf(strDelimitador)
+ strDelimitador.length();
int intFinal = strRegistro.indexOf(strDelimitador, intInicio);
String strDetalle = strRegistro.substring(intInicio, intFinal);
System.out.println("Detalle: " + strDetalle);
return strDetalle.startsWith(strFiltro);
}

CIBERTEC CARRERAS PROFESIONALES


148

Resumen

 Usar la interfaz RecordFilter para crear clases que implementen un criterio de filtro,
el cual luego podrá ser usado al recorrer un RecordStore

 Usar la interfaz RecordComparator para crear clases que implementen un criterio


de ordenamiento, el cual luego podrá ser usado al recorrer un RecordStore

 Si desea saber más acerca de estos temas, puede consultar las siguientes
páginas.

 http://www.mailxmail.com/curso/informatica/j2me
 http://programacion.com/java/tutorial/ags_j2me/
 http://leo.ugr.es/J2ME/MIDP/enlaces.htm

 Referencia oficial de Java (en inglés)

 http://java.sun.com/javame/reference/apis/jsr118/

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 149

UNIDAD DE
APRENDIZAJE

3
SEMANA

14

INTRODUCCIÓN A LAS COMUNICACIONES


LOGRO DE LA UNIDAD DE APRENDIZAJE

• Reconoce la necesidad de almacenar información en un MIDlet, utilizando


memoria persistente en forma de Record Store

• Desarrolla MIDlet que permitan realizar el mantenimiento completo de


registros basado en Record Store.

• Desarrolla MIDlet permita todavía realizar búsquedas u ordenamiento de


registros en un Record Store

• Maneja las comunicaciones vía HTTP.

TEMARIO

• Conectividad HTTP:
o Clase Connector
o Clase HTTPConnection
o Clase InputStream
o Clase OutputStream

ACTIVIDADES PROPUESTAS

• Crea la aplicación especificada en el punto 7, que realiza una conexión HTTP


básica.

CIBERTEC CARRERAS PROFESIONALES


150

1. Introducción
J2ME proporciona un conjunto de clases que pueden ser usados por los MIDlets
para poder comunicarse con cualquier punto de una red a la cual el dispositivo móvil
esté conectado. Generalmente, la red a la que nos conectamos es Internet, y los
puntos en la red son sitios web con quienes podemos comunicarnos usando los
protocolos http/HTTPS.
A continuación, se dan algunos ejemplos del uso de las comunicaciones en
aplicaciones J2ME:
• Validación de usuario y clave antes de ingresar a la aplicación
• Lectura de datos guardados en una base de datos central
• Envío de los datos ingresados en un RecordStore para ser grabados en una base
de datos central
Un aspecto importante, cuando se construye una aplicación de este tipo, es que
la parte correspondiente a la comunicación va siempre en un segundo hilo o proceso.
Esto es porque este tipo de conexión es generalmente lento, y podrían bloquear el
equipo si se usa un solo hilo o proceso. Asimismo, tomar en cuenta que las
conexiones deben cerrarse al finalizar la aplicación.

2. Clase Connector

2.1. Definición

Clase usada para crear los objetos de tipo Connection, que son las que se
usarán para conectarse.

2.2. Métodos

2.2.1 open()
• Definición
public static Connection open(String url)
public static Connection open(String url, int modo)
public static Connection open(String url, int modo,
boolean timeout)

• Descripción
Permite crear un objeto de tipo Connection. Sus parámetros son:
o url: Url del sitio a donde se desea conectarse
o modo: Modo de conexión. Los valores posibles se pueden ver en
la tabla 1-1

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 151

o timeout: Dato lógico que indica si se usan los valores de timeout


del equipo

Constante Descripción
Connection.READ Solo lectura
Connection.WRITE Solo escritura
Connection.READ_WRITE Lectura y escritura
Tabla 1-1. Modos de conexión

3. Clase Connection

3.1. Definición

Clase que manipula la conexión con el sitio de red. De esta interfaz, heredan
varias sub interfaces según el protocolo. De este modo, para conectarse con un
sitio usando el protocolo http, se usara la interfaz HTTPConnection.

4. Clase HTTPConnection

4.1. Definición

Es una conexión de tipo HTTP. Permite conectarse a un sitio Web y realizar


operaciones de lectura y escritura. Debido a que la conexión a un sitio Web puede
ser un proceso lento, es recomendable poner todo el procesamiento dentro de un
hilo diferente del proceso principal.

4.2. Métodos

4.2.1 close()
• Definición
public void close()

• Descripción
Cierra la conexión.

4.2.2 getLength()
• Definición
public long getLength()

• Descripción
Obtiene la longitud de la respuesta del sito web.

4.2.3 getRequestMethod()
• Definición

CIBERTEC CARRERAS PROFESIONALES


152

public String getRequestMethod()

• Descripción
Obtiene el método de comunicación con el sitio web. Los métodos
están datos por las constantes HTTPConnection.GET y
HTTPConnection.POST.

4.2.4 getRequestProperty()
• Definición
public String getRequestMethod(String propiedad)

• Descripción
Obtiene el valor de una propiedad de la consulta HTTP.

4.2.5 getResponseCode()
• Definición
public int getResponseCode()

• Descripción
Obtiene el codigo de respuesta del sitio web. La lista de valores es
grande. A continuación, algunos de ellos:
o HTTPConection.HTTP_OK: Conexión correcta
o HTTPConection.HTTP_NOT_FOUND: Sitio no encontrado
o HTTPConection.HTTP_FORBIDDEN: Sitio prohibido
o HTTPConection.HTTP_INTERNAL_ERROR: Error interno

4.2.6 openInputStream()
• Definición
public InputStream openInputStream()

• Descripción
Obtiene un objeto de tipo InputStream, necesario para leer los datos
del sitio web.

4.2.7 openOutputStream()
• Definición
public OutputStream openOutputStream()

• Descripción
Obtiene un objeto de tipo OutputStream, necesario para escribir los
datos hacia el sitio web.

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 153

4.2.8 setRequestMethod()
• Definición
public void setRequestMethod(String metodo)

• Descripción
Modifica el método de comunicación por el sitio web. Los métodos
están dados por las constantes HTTPConnection.GET y
HTTPConnection.POST.

4.2.9 setRequestProperty()
• Definición
public void setRequestMethod(String propiedad, String valor)

• Descripción
Cambia el valor de una propiedad de la consulta HTTP.

5. Clase InputStream

5.1. Definición

Clase usada para leer datos desde una conexión

5.2. Métodos
5.2.1 close()
• Definición
public void close()

• Descripción
Cierra el flujo de entrada.

5.2.2 read()
• Definición
public int read()
public int read(byte [] datos)
public int read(byte [] datos, int inicio, int longitud)

• Descripción
Lee los datos de respuesta del sitio web. En el primer caso,
devuelve un entero leído del sitio web. En los otros casos, los bytes
leídos se guardan en el arreglo “datos” y se devuelve la cantidad de
bytes. Sus parámetros son:
o datos: Arreglo que contendrá los datos leídos
o inicio: Índice en el arreglo donde se comenzarán a grabar los
datos

CIBERTEC CARRERAS PROFESIONALES


154

o longitud: Cantidad de bytes que se guardarán en el arreglo

6. Clase OutputStream

6.1. Definición

Clase usada para escribir datos hacia una conexión

6.2. Métodos

6.2.1 close()
• Definición
public void close()

• Descripción
Cierra el flujo de salida.

6.2.2 read()
• Definición
public void write(int dato)
public void write(byte [] datos)
public void write(byte [] datos, int inicio, int longitud)

• Descripción
Escribe los datos al sitio web. En el primer caso, escribe el dato
entero especificado. En los otros casos, se escribirán los bytes del
arreglo “datos”. Sus parámetros son:
o datos: Arreglo que contendrá los datos que van a ser escritos
o inicio: Indice en el arreglo donde se comienzan los datos que
van a ser escritos
o longitud: Cantidad de bytes en el arreglo que van a ser escritos

7. Ejemplos

7.1. Aplicación InicioSesionHTTP

7.1.1 Enunciado
Construir una aplicación que realice lo siguiente:
• Mostrar un formulario con el título “Login” y que permita ingresar los
siguientes datos:
o Usuario (alfanumérico, 10 caracteres)

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 155

o Clave (alfanumérico y contraseña, 10 caracteres)


Adicionalmente, los siguientes botones
o Un botón “Aceptar”, que se conectará con un sitio web pasándole
como parámetros el usuario y la clave
o Un botón “Salir” para salir de la aplicacion
• La aplicación debe mostrar el resultado devuelto por el sitio web en un
StringItem llamado “Resultado”.

Figura 7-1. Ventana de la aplicación InicioSesionHTTP

7.1.2 Código

import java.io.InputStream;
import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
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.StringItem;
import javax.microedition.lcdui.TextField;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;

public class InicioSesionHTTP extends MIDlet implements CommandListener,


Runnable {

private Display dsp = Display.getDisplay(this);


private Form frm = new Form("Login");
private TextField txfUsuario = new TextField("Usuario", "", 10,
TextField.ANY);

CIBERTEC CARRERAS PROFESIONALES


156

private TextField txfClave = new TextField("Clave", "", 10,


TextField.ANY | TextField.PASSWORD);
private StringItem stiResultado = new StringItem("Resultado", "",
Item.PLAIN);

private Command cmdAceptar = new Command("Aceptar", Command.OK, 2);


private Command cmdSalir = new Command("Salir", Command.EXIT, 2);

public InicioSesionHTTP()
{
frm.append(txfUsuario);
frm.append(txfClave);
frm.append(stiResultado);
frm.addCommand(cmdAceptar);
frm.addCommand(cmdSalir);
frm.setCommandListener(this);
}

protected void destroyApp(boolean arg0) {


}

protected void pauseApp() {


}

protected void startApp() throws MIDletStateChangeException {


dsp.setCurrent(frm);
}

public void commandAction(Command c, Displayable d) {


// Procesamiento de los botones
if(c == cmdAceptar)
{
// Iniciar un hilo en segundo plano
Thread t = new Thread(this);
t.start();
}
else if(c == cmdSalir)
{
destroyApp(false);
notifyDestroyed();
}
}

public void run() {


// Conexion al sitio web
HttpConnection http = null;
try
{
// Establecer la direccion del sitio web
String strURL = "http://127.0.0.1/ServidorMIDP/inicio.asp?usuario="
+ txfUsuario.getString() + "&clave=" + txfClave.getString();
System.out.println(strURL);

// Conexion al sitio web


http = (HttpConnection) Connector.open(strURL);
if(http.getResponseCode() == HttpConnection.HTTP_OK)
{
// Lectura de los datos devueltos
int lngBytes = (int) http.getLength();
byte abytDatos[] = new byte[lngBytes];
InputStream is = http.openInputStream();
is.read(abytDatos);
is.close();

// Mostrar los datos devueltos


String strDatos = new String(abytDatos);
System.out.println(strDatos);
stiResultado.setText(strDatos);

CARRERAS PROFESIONALES CIBERTEC


NUEVAS TECNOLOGÍAS MÓV ILE S I - LABORATORIO 157

}
System.out.println("fin");
}
catch(Exception ex)
{
// Mostrar los datos devueltos
stiResultado.setText("Error: " + ex.toString());
System.out.println("Error: " + ex.toString());
}
finally
{
// Cerrar la conexion
if (http != null)
{
try
{
http.close();
}catch(Exception ex)
{}
}
}
}
}

CIBERTEC CARRERAS PROFESIONALES


158

Resumen

 La plataforma J2ME proporciona un conjunto de clases para permitir la conexión


vía HTTP con un sitio Web.

 Debido a que la comunicación con un sitio Web es un proceso lento, se


recomienda realizarlo en un hilo diferente del proceso principal.

 Si desea saber más acerca de estos temas, puede consultar las siguientes
páginas.

 http://www.mailxmail.com/curso/informatica/j2me
 http://programacion.com/java/tutorial/ags_j2me/
 http://leo.ugr.es/J2ME/MIDP/enlaces.htm

 Referencia oficial de Java (en inglés)

 http://java.sun.com/javame/reference/apis/jsr118/

CARRERAS PROFESIONALES CIBERTEC

You might also like