Java per a dispositius mòbils. - Associació Sabadell Universitat

Anuncio
S9
Java per a dispositius
mòbils.
Sabadell, del 5 al 6 de juliol de 2007
Vicenç Soler i Juan Manuel Fernández,
professors de l’Escola Universitària
d’Informàtica de Sabadell.
Estius Universitaris 06/07
Java Móvil J2ME
Java en dispositivos móviles
Vicenç Soler
Juan Manuel Fernández
1
Estius Universitaris 06/07
Java Móvil J2ME
Programa (I)
•
Java 2, Micro Edition. (1'5h)
–
•
•
–
•
Objetivos: Conocer las diferentes implementaciones de Java para dispositivos móviles.
Introducción a la arquitectura J2ME, Presentación de la arquitectura básica de Java i
como esta se adapta en función del dispositivo sobre el que se coloca, se presentan los
estándares que hay detrás de esta arquitectura y se catalogan para uso futuro del
alumno.
Dispositivos. (1'5h)
•
–
–
–
–
•
Configuraciones: CDC, CLCD
CDC
CLCD
Profiles: Foundation Profile, Personal Profiles, MID Profile.
JVMs y Paquetes Opcionales
PDA,
PocketPCs,
Mobile Devices,
PIM
Objetivos: Catalogar los dispositivos móviles, se pretende que el alumno sea crítico a la
hora de desarrollar una aplicación en J2ME para que esta cubra la mayor parte de
dispositivos.
Pàg: 2
Estius Universitaris 06/07
Java Móvil J2ME
Programa (II)
•
Entornos de desarrollo (2h)
–
–
–
•
Diferentes entornos IDE.
Instalación del Software para desarrollo.
Instalación y configuración del Emulador de PALM
Objetivos: Evaluar diferentes entornos de desarrollo, se referencia un conjunto amplio
de ellos, y se aporta una visión critica sobre ventajas e inconvenientes de estos,
finalmente se instala un entorno tanto de desarrollo como de test de aplicaciones.
Constricciones para desarrollar aplicaciones es dispositivos móviles (1h)
•
–
–
–
•
CPU
Pantalla
Memoria
Objetivos: Analizar las características del entorno donde se ejecuta la aplicación con el
objetivo de evidenciar las sustanciales diferencias de desarrollo que se deben
considerar para los dispositivos móviles. Concienciar al alumno de las concesiones
necesarias en las aplicaciones J2ME.
Pàg: 3
Estius Universitaris 06/07
Java Móvil J2ME
Programa (III)
•
Estructura básica de un Midlet (3h)
–
–
–
•
Objetivos: Mostar la estructura básica de las aplicaciones para dispositivos móviles,
crear una aplicación básica y analizarla, ver los problemas de desarrollo, compilación y
deployment de este tipo de aplicaciones.
La interfaz de Usuario (6h)
•
–
–
•
Gestor de aplicaciones
Ciclo de vida
Estructura de un Midlet
En MIDP
En PersonalJava
Objetivos: Presentar los controles disponibles en J2ME y PersonalJava, familiarizando al
alumno con las estructuras necesarias para construir aplicaciones usables.
Pàg: 4
Estius Universitaris 06/07
Java Móvil J2ME
Programa (IV)
•
Almacenamiento de Información (3h)
–
–
–
–
•
Objetivos: Presentar las diferentes APIs para la gestión de la información en los dispositivos
móviles en general y en algunos en particular, y como estas deben ser tratadas desde las
aplicaciones para un correcto ciclo de vida. Se aborda también el almacenamiento externo de
esta información.
Comunicaciones (3h)
•
–
–
•
•
•
•
En MIDP
Implementación en Palm OS
Otros contenedores de información
En PersonalJava
Framework de comunicaciones en CLCD
Comunicaciones en PocketPC
Objetivos: Introducción a la intercomunicación de dispositivos móviles, las restricciones que
por sus características se encuentran es este tipo de dispositivos.
WebServices – Futuro
Objetivos: Integración de las aplicaciones y los dispositivos en la empresa, y los mecanismos
que se encuentran disponibles para poder realizarla.
Objetivos: Análisis del futuro de las aplicaciones Java en los dispositivos móviles, mesa
redonda con los alumnos para ver su opinión con respecto a este tipo de dispositivos, y
análisis de tendencias del mercado.
Pàg: 5
Estius Universitaris 06/07
Java Móvil J2ME
Ámbito de Java
Java 2 Micro Edition (J2ME)
Pàg: 6
Estius Universitaris 06/07
Java Móvil J2ME
Java 2, Micro Edition
•
Configuraciones:
– J2ME se define en términos de configuraciones y de perfiles. Una
configuración es un core para la funcionalidad básica, mientras que
un perfil se define sobre una configuración existente. Así, un perfil
proporciona una funcionalidad extendida que explota las
capacidades del dispositivo sobre el que se van a ejecutar las
aplicaciones. También podemos encontrar los paquetes
opcionales, los cuales se definen sobre los perfiles y
configuraciones.
Pàg: 7
Estius Universitaris 06/07
Java Móvil J2ME
Configuraciones de J2ME
•
•
Una configuración es una combinación de una máquina virtual Java y
de una colección de los interfaces de programación de aplicaciones
(APIs) para una determinada clase del dispositivo. Una configuración
proporciona la base para uno o más perfiles en un dispositivo. Un perfil
es un sistema de APIs que dota de más funcionalidad y se adapta
específicamente a las especificaciones de un determinado dispositivo.
Una configuración define un sistema básico de APIs que se debe estar
implementado en todos los dispositivos que soporten la configuración
(dispositivos de baja potencia, con poca cantidad de memoria, etc.). El
perfil que se sustenta sobre la configuración, debe implementar los
APIs de la configuración, y los específicos del perfil (profile), como
pueden ser los específicos de un PDA, un teléfono móvil, etc.
Es importante observar que la configuración especifica las
capacidades de la máquina virtual asociada, pero no impone una
maquina virtual particular. Los vendedores de perfiles y
configuraciones tienen libertad de proporcionar su propia máquina
virtual, siempre que se adapte a la especificación (Ex. J9VM IBM, KVM
SUN).
Pàg: 8
Estius Universitaris 06/07
Java Móvil J2ME
J2ME, CDC & CLDC
– Hay dos configuraciones definidas actualmente en J2ME: la configuración de
dispositivo con conexión limitada (CLDC) y la configuración de dispositivo con
conexión (CDC). La CDC se piensa para PDAs y dispositivos de gama alta y con
conexiones permanentes o semi permanentes. El CLDC se piensa para PDAs y
dispositivos con las conexiones de red intermitentes y con memoria y CPU limitada.
•
A continuación se presenta un esquema de los perfiles definidos para la CDC y
CLDC.
– El personal profile se sitúa sobre el personal basis y el foundation profile los cuales
extiende la configuración CDC.
– El perfil Mobile Information Device (MID) extiende la configuración CLDC, junto con
paquetes opcionales como pueden ser el Personal Information Management (PIM) y
el FileConnection.
Pàg: 9
Estius Universitaris 06/07
Java Móvil J2ME
CLDC vs CDC (I)
• Connected Limited Device Configuration (CLDC)
– El CLDC 1,0 fue definido por JSR30 (Java Specification Request) y lanzado en mayo
de 2000. Apunta los dispositivos con unas características básicas. Un dispositivo de
CLDC:
•
•
•
•
•
es accionado por las baterías,
Pocos recursos de proceso,
Conectividad ad-hoc y de poca velocidad,
128 KB de memoria disponible para la JVM y las bibliotecas de CLDC, y
tiene por lo menos 32 KB disponible para el runtime y la asignación dinámica de objetos.
– Estas características definen una variedad amplia de dispositivos, incluyendo pagers,
teléfonos móviles, y PDAs. El CLDC define una base común para estos dispositivos
en las áreas siguientes:
•
•
•
•
•
•
Paquetes de Java base
Capacidades de lenguaje
Capacidades de la JVM
Conectividad e I/O
Seguridad
Internacionalización
– No cubre otras áreas que puedan ser especificas del dispositivo, por ejemplo el
interfaz de usuario, el ciclo de vida de aplicación, gestión de eventos. Estas áreas son
cubiertas por los perfiles.
– La máquina virtual de Java que proporciona el core de un CLDC cumple las
especificaciones de JVMS y JLS con algunas excepciones. Es decir los perfiles o
aplicaciones que corran sobre CLDC no dispondrán de las siguientes características:
Pàg: 10
Estius Universitaris 06/07
Java Móvil J2ME
CLDC vs CDC (II)
• Connected Limited Device Configuration (CLDC)
– Restricciones referentes a JLS (Java Language Specification)
•
•
•
Sin soporte de coma flotante (ninguna operación de coma flotante, literales de coma flotante, tipos, o
valores).
Sin soporte a la finalización.
Soporte básico de excepciones, el número de las clases de error es limitado.
– Restricciones referentes a JVMS (Java Virtual Machine Specification)
•
•
•
•
•
•
•
•
•
Ningún soporte a coma flotante..
Ningún Interfaz Nativo de Java (JNI).
No se soportan los class-loaders de usuario.
Inexistencia de la API Reflection.
Sin Thread groups ni daemon Threads.
Sin soporte a la finalización.
Sin Weak References.
Método diferente de verificación de classfile
Formato de classfile y cargador (loader) diferente.
– El CLDC hereda la mayoría de sus clases de J2SE, y define algunas clases
especificas de CLDC. Las clases heredadas de J2SE utilizan los nombres comunes
de la clase y del paquete. Las clases especificas usan el prefijo
javax.microedition.
Pàg: 11
Estius Universitaris 06/07
Java Móvil J2ME
CLDC vs CDC (III)
• Connected Limited Device Configuration (CLDC)
– La versión siguiente de CLDC fue definida por JSR139 (Java Specification Request),
que fue aprobado en Marzo de 2003. Los cambios en CLDC 1,1 son los siguientes:
•
•
•
•
•
•
Se agrega la coma flotante. float y double a java.lang , y algunos métodos en otras clases
permiten valores en coma flotante. Las clases afectadas incluyen java.lang.Math,
java.io.DataOutputStream, java.io.DataInputStream, y java.util.Random.
Soporte básico para referencias Weak de J2SE's. Se agrega el paquete java.lang.ref.
Las clases Calendar, Date y TimeZone en java.util son más consistentes con las versiones de
J2SE.
Se ha agregado la clase Error en java.lang.NoClassDefFoundError.
Algunos métodos añadidos a clases existentes, por ejemplo el método intern() a la clase
java.lang.String, y el método toString() a la clase java.util.Date.
La especificación completa de CLDC 1,1 está disponible de http://www.jcp.org/jsr/detail/139.jsp .
• Connected Device Configuration (CDC)
– La CDC es un súper conjunto de CLDC. La CDC incluye todas las APIs definidas por
el CLDC, incluyendo los paquetes java.* y javax.microedition.*. La CDC se
diseña para los dispositivos de más memoria (2 MB o más, disponible para la
plataforma de Java) y una conexión mejor de red (desde 9600 bps en adelante). La
CDC hereda de PersonalJava, por tanto las aplicaciones de PersonalJava que no
utilicen AWT (Abstract Window Toolkit) deberían ser portables a CDC (las
capacidades de AWT se definen en los perfiles del CDC).
Pàg: 12
Estius Universitaris 06/07
Java Móvil J2ME
CLDC vs CDC (IV)
• Connected Device Configuration (CDC)
– Una implementación de CDC debe soportar totalmente JLS y JVMS.
– Los paquetes de la CDC se diseñan para ser un sistema completo de APIs para
apoyar la JVM. Se toman de J2SE 1,3, eliminando los APIs deprecados. El sistema
de paquetes resultante es el siguiente:
• java.io, incluyendo BufferedReader, BufferedWriter, ObjectInputStream, y
ObjectOutputStream
• java.lang
• java.lang.ref
• java.lang.reflect
• java.math
• Clases de java.net de J2SE, incluyendo URL, URLConnection, InetAddress, y
SocketPermission
• java.security encriptación para la serialización de objetos. Sin soportar firma segura de código,
certificados, almacenamiento de claves, JDK 1.1 Identity, e IdentityScope.
• java.security.cert
• java.text, con soporte mínimo para i18n (internationalization)
• java.util, clases de J2SE, incluyendo Array, BitSet, Calendar, LinkedList, Stack,
Vector
• java.util.jar
• java.util.zip
• javax.microedition.io
– Cualquier implementación de CDC deben soportar la entrada-salida
del archivo (I/O) (por lo menos en modo read-only) y datagramas.
Pàg: 13
Estius Universitaris 06/07
Java Móvil J2ME
Profiles CLDC
•
•
•
•
Actualmente sólo existe un perfil (profile) para la configuración
CLDC.
Este profile (MIDP) Mobile Information Device Profile, fue lanzado
por SUN en Octubre de 2001 para los dispositivos PALM.
El ámbito del perfil esta pensado para dispositivos mucho más
limitados en recursos, como pueden teléfonos móviles, y pagers.
La ventaja de la elección de este perfil, es que aporta la mínima
expresión para todos los dispositivos, de este modo una aplicación
que corra sobre este perfil, podrá ejecutarse en todos los
dispositivos que lo implementen.
Pàg: 14
Estius Universitaris 06/07
Java Móvil J2ME
CLCD: MIDP (I)
•
•
La especificación de MIDP define los requisitos adicionales para el dispositivo
destino, más allá de los requisitos necesarios para CLDC. Definido en JSR37, MIDP
impone la necesidad de 128 KB adicionales de memoria permanente para los
componentes de MIDP, 8 KB para los datos persistentes creados y usados por las
aplicaciones, y 32 KB para el Java heap.
La especificación MIDP 1.0 sobre CLDC 1.0, proporcionan funcionalidad en los
apartados siguientes:
–
–
–
–
–
•
MIDP no cubre las áreas siguientes:
–
–
–
•
Gestión de ciclos de vida de la aplicación.
Interfaz de usuario
Almacenamiento persistente
Redes
Timers
APIs A nivel sistema
Instalación y almacenaje de la aplicación
Seguridad más allá de lo especificado en CLDC.
MIDP proporciona nuevas clases en java.lang, java.util, y
javax.microedition.io, y define los nuevos paquetes para el interfaz de
usuario, el almacenamiento persistente, y las extensiones para la gestión del ciclo de
vida de la aplicación. Estos paquetes se denominan
javax.microedition.lcdui, javax.microedition.rms, y
javax.microedition.midlet, respectivamente.
Pàg: 15
Estius Universitaris 06/07
Java Móvil J2ME
CLDC: MIDP (II)
•
Una aplicación MIDP se llama MIDlet. Un MIDlet es parte de un grupo de MIDlets llamado una “suite” de
MIDlet. Las suites de MIDlet pueden compartir recursos, tales como datos persistentes en una base de
datos del Record Management System (RMS) en el dispositivo. Una aplicación de MIDP debe extender
la clase MIDlet e implementar tres de sus métodos definidos como abstractos: startApp, pauseApp, y
destroyApp. Estos métodos son llamados por el sistema cuando se requiere que el MIDlet cambie de
estado. Un MIDlet tiene los estados siguientes:
–
–
–
Pausado. Cuando el sistema requiere que el MIDlet entre en estado pausado, llama el método pauseApp
para permitir liberar los recursos compartidos.
Activo. Se llama el método startApp después de que se cree una instancia del MIDlet, y cada vez que se
abandona el estado pausado.
Destruido. Cuando se invoca destroyApp el MIDlet que debe almacenar su estado y liberar cualquier
recurso que tuviera asignado.
•
El desarrollador puede también hacer que el MIDlet entre en estos estados, usando los métodos
notifyPaused, notifyDestroyed, y resumeRequest.
•
MIDP 2.0 se construye sobre MIDP 1.0, es compatible hacia atrás, esto garantiza que las aplicaciones
desarrolladas para MIDP 1.0 también funcionen en MIDP 2.0. Definido en JSR118, la especificación final
fue lanzada en noviembre de 2002. Asume funcionalidad de CLDC 1.0, aunque también trabajará con
CLDC 1,1.
MIDP 2.0 agrega algunos nuevos paquetes:
•
–
–
–
•
javax.microedition.lcdui.game. Este paquete incluye las clases para crear una infraestructura para
juego. Incluye clases GameCanvas y Sprites.
javax.microedition.media y javax.microedition.media.control. MIDP 2.0 incluye un
subconjunto de Movile Media API (JSR135) y generación de tonos y reproducción de sonido.
javax.microedition.pki. Certificados para las conexiones de red seguras.
Se puede obtener una copia de la especificación de MIDP 2.0, en http://www.jcp.org/jsr/detail/118.jsp .
Pàg: 16
Estius Universitaris 06/07
Java Móvil J2ME
CLDC: Paquetes Opcionales
•
•
•
De igual modo que el profile MIDP, para explotar las características de estos
dispositivos se dispone de paquetes que ofrecen una API Java para acceder a estos
recursos.
En el JSR075 se especifican los paquetes opcionales que se pueden construir sobre
CLDC 1.0 o superiores. Estos son el PIM y FileConnection. Aunque fueron definidos
por el mismo JSR pueden implementarse de forma independiente.
Paquete Opcional de PIM (Personal Information Management)
–
•
El paquete opcional PIM añade el paquete javax.microedition.pim a CLDC. El propósito de
este paquete es proveer al desarrollador el acceso y gestión de la libreta de direcciones, la
lista de tareas y el calendario del PDA.
Paquete Opcional FileConnection
–
El paquete opcional de FileConnection agrega a CLDC 1.0 o superior el paquete
javax.microedition.io.file. Este paquete añade otro tipo de conexión al framework genérico de
conexiones (GCF), y proporciona el acceso al sistema de ficheros del PDA. El sistema de
ficheros puede estar en el propio dispositivo, en tarjetas de memoria tales como
CompactFlash (CF), Secure Digital (SD), Multimedia Card (MMC), SmartMedia (SM), o en
otros sistemas de almacenamiento.
Pàg: 17
Estius Universitaris 06/07
Java Móvil J2ME
CDC Profiles (I)
•
•
•
•
•
•
•
Los dispositivos PoketPC acostumbran a incluir distribuciones de PersonalJava,
formalmente Personal Java es parte de J2SE, se apuntaran las diferencias entre las
implementaciones de PersonalJava y J2ME.
Foundation Profile
El foundation profile fue desarrollado por el JCP como JSR46
http://www.jcp.org/jsr/detail/46.jsp. Puede ser descargado de
http://java.sun.com/j2me/index.jsp.
Una implementación del foundation profile debe soportar los protocolos especificados por
la CDC, y además debe apoyar los sockets y HTTP.
Personal Basis Profile
Este profile proporciona la capacidad para una presentación básica de interfaz de usuario,
pero no tiene soporte para GUI’s de alta funcionalidad. El Personal Basis Profile
proporciona únicamente soporte para componentes ligeros de AWT.
Las principales diferencias entre este profile y las funcionalidades de PersonalJava son:
–
–
–
•
PersonalJava implementa el JDK 1.1.8, mientras que el Personal Basis Profile implementa
JDK 1,3.
Era opcional incluir Remote Method Invocation (RMI) en PersonalJava. En el Personal
Basis Profile, el RMI es soportado por un paquete opcional.
Un volumen importante de APIs deprecadas no se incluye en el Personal Basis Profile.
El Personal Basis Profile fue desarrollado por el JCP como JSR129
http://www.jcp.org/jsr/detail/129.jsp.
Pàg: 18
Estius Universitaris 06/07
Java Móvil J2ME
CDC Profiles (II)
•
•
•
Personal Profile
El personal profile es el camino para la migración hacia J2ME de las aplicaciones de PersonalJava, y fue
desarrollado por el JCP como JSR62. Ester Profile añade al Personal Basis Profile soporte para Web y
entorno para la ejecución de aplicaciones heredadas de PersonalJava. El Personal Profile es el perfil de
la CDC ideado para PDAs. Las aplicaciones escritas para las APIs del Personal Profile son compatibles
hacia arriba con JDK 1.3 de J2SE.
El perfil personal se piensa para aplicaciones que requieren soporte completo de JDK 1.1 AWT (es
decir, componentes GUI complejos). Especifica tres modelos de aplicaciones:
–
–
–
•
Applet. Applet estándares del JDK 1.1.
Xlets. Un Xlet es un interfaz de la gestión del ciclo de vida, similar al MIDlet. Un Xlet define tres métodos. El
sistema hace que el Xlet cambie su estado. Los estados definidos son Destroyed, Paused, y Active.
Aplicaciones. Aplicaciones estándar de Java, definido como clase con un método public static void
main(String[]).
El Personal Profile agrega al Foundation Profile estos paquetes:
–
–
–
–
–
–
–
–
–
–
–
–
java.applet
java.awt
java.awt.color
java.awt.datatransfer
java.awt.event
java.awt.image
java.beans
java.math
java.rmi
java.rmi.registry
javax.microedition.xlet
javax.microedition.xlet.ixc
Pàg: 19
Estius Universitaris 06/07
Java Móvil J2ME
CDC Profiles (III)
•
•
•
Diferencias entre el perfil personal y JDK 1.3
Los paquetes y las clases del Personal Profile son típicamente subconjuntos de los paquetes y de las
clases del JDK 1.3.
Hay un conjunto pequeño de APIs en el Personal Profile que tiene restricciones en su uso. Son:
–
–
–
–
–
–
•
java.awt.AlphaComposite. Aproximación de la regla de SRC_OVER.
java.awt.Component. La implementación puede ignorar las llamadas para fijar el cursor visible.
java.awt.Dialog. La implementación puede limitar el tamaño, puede impedir redimensionar, puede limitar la
localización en la pantalla, y puede no soportar un título visible.
java.awt.Frame. Las mismas restricciones que a Dialog pueden aplicarse a Frame.
java.awt.Graphics2D. Solamente instancias de AlphaComposite se pueden utilizar con setComposite() .
java.awt.TextField. Alguna implementación puede no permitir fijar el carácter de echo.
En cada caso, una propiedad del sistema deberá ser puesta a true si la implementación del Personal
Profile tiene alguna de las restricciones anteriores. Estas propiedades del sistema tienen las siguientes
claves:
–
–
–
–
–
–
–
–
–
–
–
–
java.awt.AlphaComposite.SRC_OVER.isRestricted
java.awt.Component.setCursor.isRestricted
java.awt.Dialog.setSize.isRestricted
java.awt.Dialog.setResizable.isRestricted
java.awt.Dialog.setLocation.isRestricted
java.awt.Dialog.setTitle.isRestricted
java.awt.Frame.setSize.isRestricted
java.awt.Frame.setResizable.isRestricted
java.awt.Frame.setLocation.isRestricted
java.awt.Frame.setState.isRestricted
java.awt.Frame.setTitle.isRestricted
java.awt.TextField.setEchoChar.isRestricted
Pàg: 20
Estius Universitaris 06/07
Java Móvil J2ME
CDC Profiles (IIII)
•
•
•
•
•
Diferencias entre el Personal Profile y PersonalJava
PersonalJava era el Java original para los dispositivos de gama alta y apliances, pero será reemplazado
por el Personal Profile. El Personal Profile es una nueva definición, basada en J2ME. Cuando los
diseñadores del perfil personal comenzaron a definirlo, lo hicieron con JDK 1.3, quitado todos los APIs
deprecados y que consideraron innecesarios para los dispositivos móviles modernos. PersonalJava se
basa en las APIs de JDK 1.1.
Diferencias entre PersonalJava y JDK 1.1.8
PersonalJava 1.2 hereda las APIs de JDK 1.1.8, modifica ligeramente a muchos de ellos, convirtiendo
alguno en opcional, y agrega algunos específicos a PersonalJava. También hereda algún APIs de Java
1.2 para apoyar seguridad en control de acceso y firmas de código. La portabilidad del código sin
modificación de JDK 1.1.8 a PersonalJava es por lo tanto posible pero dependerá de la aplicación.
La mayoría de las ocasiones en que una aplicación no funciona con PersonalJava son ocasionados por
diferencias en las APIs de seguridad. Tal y como se ha comentado anteriormente PersonalJava utiliza
las APIs de seguridad de Java 1.2 en vez de JDK 1.1.8. Sin embargo, existe un gran parecido entre JDK
1.1.8 y PersonalJava 1.2, de modo que el código fuente será bastante portable entre las dos
plataformas.
javax.microedition.*
Pàg: 21
Estius Universitaris 06/07
Java Móvil J2ME
Dispositivos
•
•
•
•
•
•
Por que utilizando Java nos hemos de preocupar de la plataforma?
Tal i como se ha discutido en la presentación anterior J2ME no es totalmente portable,
hemos de considerar aspectos como la JVM donde se ejecutara nuestra aplicación
(PersonalJava y MIDP), así como los paquetes opcionales de los que disponga el
dispositivo destino.
Por norma general se recomienda estructurar la aplicación en el código funcional común
que se pueda ejecutar independiente de la plataforma, y separarlo de la presentación de
usuario, la persistencia y conectividad, esto puede ser una tarea compleja.
Dado que el punto anterior es de difícil cumplimiento, normalmente se escoge la
plataforma destino antes de diseñar la aplicación, dado que muchas aplicaciones para
dispositivos móviles son orientadas a cliente servidor, esto afectara significativamente a
diseño y realización de la aplicación. A continuación vamos a enumerar algunos de los
dispositivos móviles más comunes y sus características más significativas.
Al seleccionar una plataforma PDA para el desarrollo de Java, hay un gran número de
factores a considerar. En la consideración de estos factores, es importante recordar los
dos subconjuntos principales de dispositivos, dependiendo del SO: Palm OS y PocketPCs.
Estos tienen filosofías totalmente diferentes, a continuación se enumeran algunas de ellas.
Es importante considerar siempre que aunque Java funcionará en ambos dispositivos, la
riqueza de la plataforma varía, según las capacidades del dispositivo, y, por consiguiente,
la configuración. Esto es principalmente debido a las diferencias en filosofía de diseño de
las configuraciones de J2ME según el tipo de dispositivo.
Pàg: 22
Estius Universitaris 06/07
Java Móvil J2ME
Palm OS vs PocketPCs
Dispositivos Palm OS
PocketPCs
Herencia de los PIM. Los dispositivos originales
de PALM OS eran PIMs de gama alta con
pantallas grandes y la capacidad de escribir en
vez de mecanografiar.
Herencia del PC. El PocketPCs es básicamente
un PC en miniatura.
Funcionalidad simple. PALM se caracteriza por
realizar tareas simples de forma elegante.
Rica funcionalidad. Un PocketPC es básicamente
un PC con Windows o con Linux (Sharp Zaurus)
con funcionalidades limitadas, esto deja una “look
and feel” de PC al dispositivo. Como ejemplo el
menú de inicio y el sistema de ficheros siguen
siendo igual.
Energía de proceso baja y larga duración de la
batería. Los dispositivos PALM OS funcionan a
con CPUs de 20 MHz o 33 MHz, y típicamente 8
M de la memoria. Los nuevos dispositivos PALM
OS basados en procesadores ARM y XScale
aparecidos en el 2003 aumentan las capacidades
de proceso y de memoria asemejándose a los
PocketPC.
Alta energía de proceso y una vida más corta de
las baterías. Los PocketPCs disponen
actualmente de CPUs de 200 MHz a 400 MHz, y
sobre 32Mb a 64Mb de RAM.
Pàg: 23
Estius Universitaris 06/07
Java Móvil J2ME
Comparativa de precios en USD
Diciembre 2002
PocketPC
Men
or
Mayo Palm OS
r
Men
or
Mayor
Casio E-200
$600
$650
Handspring Treo
270
$500
$700
HP iPaq 3970
$715
$780
Palm m515
$300
$400
Compaq iPaq
3870
$537
$680
Palm i705
$298
$450
Toshiba e740
$550
$600
Sony CLIE PEGNR70V
$510
$600
Media
$601
$678
Media
$402
$538
En esta selección de dispositivos high-end PocketPC y Palm,
podemos observar que los PocketPC son entre un 25% y un
50% más caros que los dispositivos high-end Palm OS.
Pàg: 24
Estius Universitaris 06/07
Java Móvil J2ME
Factores a considerar en la decisión de la
plataforma (I)
•
Coste
–
•
PocketPCs es generalmente más costoso que los dispositivos Palm OS. Tal i como se puede observar en la
tabla anterior.
Estándar Corporativo
–
•
Si hablamos de desarrollos para usuarios corporativos, o para la propia organización, los estándares
corporativos para PDAs afectan claramente a la eleción de la plataforma. Según el grupo tecnológico Winn
(en fecha diciembre de 2002), Palm OS ha sido elegido por el 85% de las compañías que comprende
Fortune 1000.
Fuente: Diez razones de elegir un Handheld Palm, 2002,
http://www.palmsource.com/includes/top_ten_reasons_to_choose_palm_powered.pdf .
Riqueza de funcionalidad
–
•
Desde la perspectiva de un desarrollador de Java, la riqueza funcional de la plataforma depende de si se
tiene acceso a él desde Java. Todos los PDAs tienen funciones estándares de PIM (es decir, libros de
direcciones, notas, listas de la tarea, y calendarios). El paquete opcional de PIM se diseña para permitir el
acceso fácil a las funciones de PIM de un PDA desde Java. PersonalJava no tiene específicamente una API
PIM, sino que proporciona el acceso a la funcionalidad del sistema operativo y las aplicaciones con JNI. Sin
embargo, el grado de accesibilidad con JNI depende de la disponibilidad de una biblioteca del API para
tener acceso a la funcionalidad.
Riqueza del soporte Java
–
El soporte Java es importante si se es desarrollador Java que desea escribir aplicaciones para PDAs.
Aunque PersonalJava es más rico en APIs de Java y más cercano a J2SE que MIDP y los paquetes
opcionales de CLDC, PersonalJava carece el APIs para tener acceso a las características especificas de un
PDA.
Pàg: 25
Estius Universitaris 06/07
Java Móvil J2ME
Factores a considerar en la decisión
de la plataforma (II)
•
Soporte Wireless
–
•
Market Share - Actual y tendencia
–
•
Aunque ambos dispositivos son capaces de operar wireless, tanto con soporte WiFi y
Bluetooth, la disponibilidad de estas características para aplicaciones Java es limitado.
Tomará un cierto tiempo hasta que las APIs Java maduren y para que los vendedores
agreguen estas APIs a sus máquinas virtuales de Java (VMs) en los PDAs.
En los años 90, el Palm OS era el sistema operativo
dominante para PDA en el mercado. Desde entonces,
Microsoft ha desafiado esa hegemonía con cierto éxito.
En 2002, los PocketPCs eran una alternativa fuerte con
crecimiento en cuota de mercado. La tendencia desde
entonces es un crecimiento de PocketPC en detrimento
de Palm OS.
Donde estará el vendedor / fabricante del dispositivo en dos años?
–
La mayoría de los fabricantes de PDAs tendrán a corto plazo nuevos modelos basados en la
CPU de Intel XScale. Esto provocara una clara disminución de las diferencias Hardware
entre dispositivos Palm OS y PocketPC, como ejemplo destacar que Palm OS v5 es
funcionalmente idéntico a las versiones anteriores, pero sin las limitaciones que tenían sus
predecesores.
Pàg: 26
Estius Universitaris 06/07
Java Móvil J2ME
Comparativa PDAs
•
Clasificación Java vs PDA
– PersonalJava está disponible en los dispositivos de PocketPC,
mientras que MIDP está disponible en los dispositivos Palm OS. A
continuación se enumeran las implementaciones J2ME
actualmente disponibles. PersonalJava se incluye en la tabla
aunque no es estrictamente una implementación J2ME, por el
contrario está disponible para casi cada dispositivo PocketPC.
•
Comparación de dispositivos Palm OS
– Los dispositivos Palm estan evolucionando rápidamente, tanto a
nivel Hardware como SO. También existen nuevos fabricantes que
crean dispositivos que ejecutan Palm OS, a continuación se
muestra una tabla con una selección de los dispositivos producidos
por Palm Inc. y con licencias de Palm OS.
Pàg: 27
Estius Universitaris 06/07
Java Móvil J2ME
Clasificación Java vs PDA
Operating
System
CPU
Device
Java
Product
PocketPC 2002
StrongARM
HP iPaq 3800 series
PersonalJava 1.2
Insignia Jeode PDA Edition
PocketPC 2002
Intel XScale
Toshiba GENIO e550G
PersonalJava 1.2
Insignia Jeode PDA Edition
Lineo's Embedix
Linux
StrongARM
Sharp Zaurus SL-5500
PersonalJava 1.2
Insignia Jeode PDA Edition
Windows CE 3.0
StrongARM
HHP Dolphin 7400
PersonalJava 1.2
Insignia Jeode PDA Edition
PocketPC 2002
StrongARM
NEC PocketGear
PersonalJava 1.2
Insignia Jeode PDA Edition
Windows CE 3.0
StrongARM
Samsung NEXiO S150
PersonalJava 1.2
Insignia Jeode PDA Edition
PocketPC 2002
Intel XScale
Fujitsu Pocket LOOX
PersonalJava 1.2
Insignia Jeode PDA Edition
PocketPC 2002
StrongARM
Compaq iPaq as a
reference platform
CDC/Foundation 1.0
IBM WebSphere Micro
Environment
PocketPC 2002
StrongARM
Compaq iPaq as a
reference platform
CLDC/MIDP 1.0
IBM WebSphere Micro
Environment
Palm OS
68K
Palm III, Palm V, Palm Vx
as a reference platform
CLDC/MIDP 1.0
IBM WebSphere Micro
Environment
Palm OS
68K
Various
CLDC/MIDP 1.0
Esmertec Micro Edition CLDC
Palm OS 3.5.x
68 K
Various; capable of
running 3.5.x
CLDC/MIDP 1.0
MIDP for Palm OS 1.0
Windows CE 2.11
MIPS or SH3
IBM Workpad Z50,
Compaq Aero 2100, HP
Jornada 430 SE, and Oth.
PersonalJava 1.1.3
Sun PersonalJava Runtime
Environment for Windows
CE 2.11 Version 1.0
Pàg: 28
Estius Universitaris 06/07
Java Móvil J2ME
Comparación de dispositivos Palm OS
Device
Total
RAM
Dynamic
Heap[a]
Palm
OS[b]
CPU Type
CPU
Speed
Palm IIIx
4 MB
128 KB
3.1
Dragonball EZ
16 MHz
Palm V
2 MB
128 KB
3.1
Dragonball EZ
16 MHz
Palm VII
2 MB
128 KB
3.2.0/3.2.
5
Dragonball/Dragonball
EZ
16 MHz
Palm VIIx
8 MB
256 KB
3.5
Dragonball EZ
20 MHz
Palm i705
8 MB
Handspring Visor
2 MB
128 KB
3.1
Dragonball EZ
16 MHz
Handspring Visor Edge
8 MB
256 KB
3.5.2
Dragonball VZ
33 MHz
IBM WorkPad
(Original)
4 MB
96 KB
3.0
Dragonball EZ
16 MHz
Qualcomm pdQ 1900
2 MB
128 KB
3.02
Dragonball EZ
16 MHz
Sony CLIE PEG-S500c
8 MB
256 KB
3.5
Dragonball EZ
20 MHz
Supra eKey
2 MB
128 KB
3.1
Dragonball EZ
16 MHz
Symbol SPT1740
2/4/8 MB
128 KB
3.2
Dragonball
16 MHz
TRG TRGpro
8 MB
128 KB/256 KB
3.3/3.5.1
Dragonball EZ
16 MHz
•
•
•
4.1
Fuente: http://www.palmos.com/dev/tech/hardware/compare.html.
[a]: Dependiendo de la versión de Palm OS instalada
[b]: Esta versión es la de referencia, en algunos dispositivos puede haberse upgradeado.
Pàg: 29
Estius Universitaris 06/07
Java Móvil J2ME
Preparando el entorno de desarrollo
•
A continuación se enumerara el software necesario para el
desarrollo de las aplicaciones de ejemplo de este curso.
Las herramientas utilizadas están disponibles de forma
libre o con mínimo coste, se han evitado los IDEs
comerciales por las siguientes razones:
– Aprender a programar en una nueva plataforma es más eficiente
contra más elemental es el entorno de desarrollo, la utilización de
un IDE a menudo oculta aspectos fundamentales de la
programación y el deployment de la aplicación. Siempre se esta a
tiempo de utilizar un IDE, cuando se entiendan los mecanismos de
construcción de aplicaciones en la plataforma.
– Se dispone de mayor libertad de programación, se pueden realizar
cosas que a menudo no son posibles con un IDE.
– El objetivo de este curso es demostrar que cualquiera puede
desarrollar aplicaciones Java para PDAs. Las herramientas
costosas no son de momento necesarias.
Pàg: 30
Estius Universitaris 06/07
Java Móvil J2ME
Las herramientas que utilizaremos son:
•
Un editor de textos, como TextPad ( http://www.textpad.com/ ) o
UltraEdit ( http://www.ultraedit.com/ ). El editor de textos debería poder
destacar la sintaxis Java y XML de modo que el código fuente sea fácil
de leer.
•
Java SDK ( http://java.sun.com/j2se/downloads.html ). Utilizaremos
1.1.8 (para compilar código fuente de PersonalJava) y 1.4 (para el
resto).
•
Emulador de Palm ( http://www.palmos.com/dev/tools/emulator/ ).
•
Sun's J2ME Wireless Toolkit (
http://java.sun.com/products/j2mewtoolkit/download.html ).
•
MIDP de Sun para Palm (
http://java.sun.com/products/midp4palm/index.html ). Aunque es libre
descargar para propósitos de desarrollo personal, se debe observar
que MIDP para Palm no es libre para distribuir comercialmente.
Pàg: 31
Estius Universitaris 06/07
Java Móvil J2ME
Configurando el emulador de Palm OS (I)
•
•
•
El emulador de Palm OS (POSE) es una parte esencial en un toolkit de
desarrollo PDA Java. Antes de descargar una aplicación en el PDA es
recomendable realizar un test en el entorno POSE. Esto implica un bucle de
programación - prueba - corrección mucho más rápido.
POSE está disponible para Windows, MacOS, y Unix. También es necesaria
una ROM de Palm OS para cargar en el emulador. Se incluyen dos ROMs una
correspondiente a una PDA Ibm C3, y otra a una PDA Palm m505, si se
dispone de un dispositivo Palm OS puede descargarse la ROM del dispositivo al
PC con el software incluido.
Cuando se ejecuta el emulador de Palm OS, aparece una pantalla similar a
esta.
Seleccionamos New para crear una nueva
sesión del emulador tal y como se observa
en el siguiente grafico.
Pàg: 32
Estius Universitaris 06/07
Java Móvil J2ME
Configurando el emulador de Palm OS (II)
•
En este momento ya dispondremos de un entorno de emulación totalmente funcional.
Pàg: 33
Estius Universitaris 06/07
Java Móvil J2ME
J2ME Wireless Toolkit
•
J2ME Wireless Toolkit de Sun (J2MEWTK) es un conjunto de
herramientas para desarrollar aplicaciones para la plataforma
CLDC/MIDP. Funciona en Windows, Solaris, y Linux, y
proporciona un entorno de emulación para diversos
dispositivos. También es capaz de utilizar POSE para emular
dispositivos Palm. El J2MEWTK permite cualquier editor de
textos para corregir los archivos fuente.
•
La JVM proporcionada por J2MEWTK es KVM, una máquina
virtual compacta que comprende los dispositivos con menos de
un mega de memoria. Dirigirse a
http://java.sun.com/products/cldc/wp/KVMwp.pdf para más
información sobre KVM.
•
Se debe instalar J2ME Wireless Toolkit en el directorio por
defecto.
Pàg: 34
Estius Universitaris 06/07
Java Móvil J2ME
MIDP para Palm OS
•
Si se escoge un entorno genérico de desarrollo MIDP para Palm será necesaria una
utilidad para convertir la aplicación MIDP (JAR/JAD) en un PRC (ejecutable para
Palm), esto es realizado por la suite MIDP de Sun.
–
•
Incluido en el MIDP para Palm:
–
–
–
•
Destacar que J2MEWTK también incluye esta funcionalidad, pero no incluye MIDP
para Palm. J2MEWTK produce el archivo JAD y lo convierte a PRC solamente cuando
se utiliza conjuntamente con el emulador de Palm. Un JAD es un archivo de
parámetros para definir valores predefinidos de un MIDlet, y valores definidos por el
usuario. El conversor de MIDP para Palm permite que el desarrollador convierta
cualquier conjunto JAD/JAR en un PRC.
Una utilidad para convertir un MIDP estándar JAD/JAR en un PRC para descargar en
el dispositivo.
Una implementación de KVM y de las bibliotecas de CLDC/MIDP para Palm.
Algunos aplicaciones java de ejemplo.
MIDP para Palm ocupa unos 590 KB de memoria y funciona en los dispositivos
siguientes:
–
–
Palm OS 3.5.x.
Disponer por lo menos de 4 MB de memoria total.
•
MIDP para Palm también incluye la capacidad de capturar los streams System.out
y System.err.
•
Para instalar el entorno MIDP para Palm tan sólo es necesario sincronizar el archivo
MIDP.prc en el dispositivo.
Pàg: 35
Estius Universitaris 06/07
Java Móvil J2ME
Ejecutar aplicaciones java en Palm (I)
•
•
Como norma general para la creación de cualquier aplicación para Palm
deberemos seguir los siguientes pasos:
Compilación de la aplicación:
–
–
–
–
•
El compilador utilizado será versión 1.1, se ha de tener en cuenta que tanto MIDP como CLDC están basado en el bytecode de
Java 1.1.
Los parámetros para una compilación básica:
<directorio de jdk 1.1>\bin\javac.exe -d <directorio de salida del class> -classpath <path de midp>\midpapi.zip;<cualquier otro
necesario> <fichero a compilar>
Ex: c:\jdk1.1.8\bin\javac.exe -d .\tmp -classpath C:\WTK104\lib\midpapi.zip Clase.java
En este punto disponemos del código fuente compilado, pero para poder ejecutar
este código en una KVM se
debe realizar un proceso de preverificación,
este proceso se realiza de la siguiente forma:
–
–
–
Cuando se trabaja con J2SE la máquina
virtual Java (JVM) lleva a cabo un proceso
de verificación en tiempo de ejecución. Esto
ocupa ciertos recursos que en dispositivos
inalámbricos son relativamente escasos. Debido
a las restricciones de estos dispositivos se ha
creado en J2ME un proceso denominado preverification
consistente en llevar a cabo parte de la verificación de
la KVM off-line, el resto será llevado a cabo como una
verificación normal.
<directorio de JME Wireless Toolkit>\bin\preverify.exe -d <directorio de salida del class> -classpath <path de
midp>\midpapi.zip;<cualquier otro necesario> <path de las clases>
Ex: c:\WTK104\bin\preverify.exe -d .\class -classpath c:\WTK104\lib\midpapi.zip;.\tmp .\tmp
Pàg: 36
Estius Universitaris 06/07
Java Móvil J2ME
Ejecutar aplicaciones java en Palm (II)
•
Como hemos indicado, para construir un "ejecutable" Palm (PRC) se ha de
disponer de una dupla (JAR/JAD). para crear el JAR que nos sirva de base
al PRC a partir de .class, necesitaremos un archivo especial (manifest) que
describirá la aplicación midlet. Concretamente:
–
–
–
–
•
El nombre de la aplicación, el icono a utilizar, y el nombre de la clase de la aplicación.
Vendedor e información de la versión.
Versión de J2ME requerida.
Ej:
MIDlet-1: TestSimple, , com.f2i.jmd.SimplestMIDlet
MIDlet-Name: TestSimple
MIDlet-Vendor: Antoni Ros
MIDlet-Version: 1.0
MicroEdition-Configuration: CLDC-1.0
MicroEdition-Profile: MIDP-1.0
Atributos requeridos para el archivo manifest:
Pàg: 37
Estius Universitaris 06/07
Java Móvil J2ME
Ejecutar aplicaciones java en Palm (III)
•
Atributos opcionales del archivo manifest:
•
Con el archivo manifest anterior, debemos ejecutar
–
–
•
<directorio de jdk 1.1>\bin\jar.exe cvfm <archivo de salida.jar> <archivo manifest a utilizar> <clases y recursos a
incluir en el jar>
Ex: c:\jdk1.1.8\bin\jar.exe cvfm .\jar\Simple.jar .\resources\SimplestMIDlet.mft .\class
En este punto ya disponemos de el fichero JAR, solo falta crear el JAD
correspondiente, un archivo JAD describe el paquete JAR, entre otros campos puede
incluir los siguientes:
MIDlet-Version: 1.0
MIDlet-Vendor: Antoni Ros
MIDlet-Jar-URL: ../jar/Simple.jar
MIDlet-Jar-Size: 2056
MIDlet-Name: TestSimple
–
Se debe tener en cuanta que generalmente entre diferentes minor versions de nuestros midlets el único dato que
variara en el archivo jad será el tamaño del archivo jar.
Pàg: 38
Estius Universitaris 06/07
Java Móvil J2ME
Ejecutar aplicaciones java en Palm (IV)
•
Atributos requeridos para el archivo jad:
•
Atributos opcionales para el archivo jad:
•
En este instante es posible crear el archivo PRC correspondiente.
–
–
<directorio de jdk 1.1>\jre\bin\java.exe" -classpath “<directorio donde se ha instalado el
midp4palm>\midp4palm1.0\Converter\Converter.jar" com.sun.midp.palm.database.MakeMIDPApp -jad <archivo jad a utilizar> type Data -o <archivoprc a construir> <archivo jar>
Ex: "C:\Program Files\j2sdk_nb\j2sdk1.4.2\jre\bin\java.exe" -classpath "C:\Documents and Settings\toni\Mis documentos\Curso
Java\Software a llevar\midp4palm-1_0\midp4palm1.0\Converter\Converter.jar" com.sun.midp.palm.database.MakeMIDPApp -jad
.\resources\Simple.jad -type Data -o .\prc\Simple.prc .\jar\Simple.jar
Pàg: 39
Estius Universitaris 06/07
Java Móvil J2ME
Ejecutar aplicaciones java en Palm (V)
•
En el punto anterior se utiliza la aplicación MakeMIDPApp que acompaña al paquete
MIDP de Sun para Palm, esta aplicación esta sita en Converter.jar. Las opciones
para MakeMIDPApp es:
Uso: Java com.sun.midp.palm.database.MakeMIDPApp [ - opciones ] < archivo JAR >
donde las opciones incluyen:
-v
-verbose
-icon <file>
Verbose output (-v -v gives even more information)
Same as –v
File containing icon for application. Must be in
bmp, pbm, or bin (Palm Resource) format.
-smallicon <file> Same as –smallicon
-name <name>
Short name of application, seen in the launcher
-longname <name>
Long name for the application, seen in beaming, etc.
-creator <crid>
Creator ID for the application
-type <type>
File type for application (default is appl)
-outfile <outfile> Name of file to create on local disk; this is the
file that is downloaded to the Palm
-o <outfile>
Same as –outfile
-version <string>
Change version
-help
Print this message
-jad <file>
Specify a file for JAD, MIDlet Suite Packaging
•
Palm recomienda que los desarrolladores para Palm utilicen un identificador único
"Creator ID". Este campo es un identificador de 4 caracteres y se puede obtener en
http://dev.palmos.com/creatorid/
–
–
Si no se especifica ningún identificador de creador el software asigna uno arbitrario.
En este punto ya se dispone de un archivo PRC que puede ser transferido al dispositivo y ejecutado.
Pàg: 40
Estius Universitaris 06/07
Java Móvil J2ME
Ejecutar aplicaciones java en PocketPC
•
Al no disponer de ningún emulador de PocketPC con un soporte Java adecuado para PC en
el momento del curso no podremos llevar a la practica los pasos aquí detallados. El deploy
de una aplicación de PocketPC es más simple que en Palm, principalmente por que todos
estos dispositivos utilizan PersonalJava 1.2, que es equivalente a JDK 1.1.8.
•
Para instalar una aplicación en un PocketPC basta con crear el jar correspondiente,
sincronizarlo con la carpeta seleccionada del dispositivo, y crear el acceso directo.
•
Dado que la gran mayoría de PocketPC actuales utilizan Jeode JVM como implementación
de PersonalJava, se enumeran los pasos para crear una aplicación Java en un PocketPC
– Compilación de la aplicación:
• <directorio de jdk 1.1>\bin\javac.exe -d <directorio de salida del class> -classpath <
directorio de jdk 1.1 >\lib\classes.zip;<cualquier otro necesario> <fichero a
compilar>
– Creación del jar contenedor, en este caso el fichero manifest no cumple ningún objetivo,
por tanto prescindimos de el:
• <directorio de jdk 1.1>\bin\jar.exe cvf <archivo de salida.jar> <clases y recursos a
incluir en el jar>
– Creación de un fichero de texto que también se sincronizara con el PocketPC y hará la
función de acceso directo.
• 18#"\Windows\evm.exe" <command line options> <class name>
• Donde evm es el ejecutable Jeode JVM, las opciones son equivalentes a las de la
ejecución de una jvm en un PC.
Pàg: 41
Estius Universitaris 06/07
Java Móvil J2ME
Constricciones al desarrollar para
dispositivos móviles
•
•
•
•
Aunque Palm IIIx tiene una capacidad computacional y casi 4 veces la memoria que el
primer Mac de Apple y superior al primer PC, debemos considerar estos dispositivos
como "limitados" en comparación con la vastedad de recursos de una computadora de
sobremesa actual. Por tanto no debemos aplicar las premisas estándares de diseño de
software cuando diseñemos aplicaciones para estos dispositivos.
Aunque enumeraremos las limitaciones de Palm, las premisas que se expongan son
también validas para los PocketPC, todo y que la capacidad de estos es superior a las
tradicionales Palm.
A medida de que las computadoras son más potentes, el software realiza más trabajo,
los recursos hardware han experimentado un crecimiento sorprendente, y para las
aplicaciones estos pueden ser virtualizados de forma que no existan constricciones. Esta
potencia permite realizar software más elegante, fácil de mantener y que permiten
cambios de diseño en tiempo de desarrollo. Este soporte a cambios aislados significa
que otras partes de la aplicación no están afectadas; esto, a su vez, significa que los
componentes que apoyan la funcionalidad existente no necesitan modificarse. Esto
permite a la aplicación soportar los cambios de una forma más fiable y más ordenada, a
pesar de la naturaleza imprevisible de los cambios futuros.
En un dispositivo móvil, sin embargo, estos principios de diseño pueden no ser
aplicables en un entorno limitado. En un dispositivo móvil, las prioridades del diseño
cambian. Los recursos limitados se deben asignar de forma que se consiga la máxima
funcionalidad. La velocidad de ejecución, del uso de memoria, y tamaño de la pantalla es
más importante que un diseño elegante propio de una perspectiva orientada a objetos y
que permita que los cambios sean aislados.
Pàg: 42
Estius Universitaris 06/07
Java Móvil J2ME
Limitaciones en capacidad de proceso
•
•
•
•
Un PC de escritorio dispone de una fuente de alimentación ilimitada, que le permite
funcionar a máxima velocidad y disipar cantidades grandes de calor. Un dispositivo Palm,
por otra parte, es un dispositivo portable con la electricidad provista por baterías de 1,5 V.
Los diseñadores de Palm eligieron una CPU de bajo consumo para funcionar de forma que
se maximizará la vida de la batería. Aunque ésta era la decisión adecuada para un
dispositivo portable pequeño, significa que el software para Palm se debe desarrollar con
una visión bien clara de la cantidad de proceso que necesitara.
Otro factor importante es que las tareas realizadas en PDAs se deben hacer muy
rápidamente. El usuario de PDA desea realizar tareas simples que terminen rápidamente; el
usuario no desea esperar al dispositivo para acabar tareas muy largas de cómputo. Los
aplicaciones de Palm son (y deben ser) muy usables (en tiempo de respuesta) como
mínimo tanto como un PC de escritorio que realice una tarea media. Si partimos de la
premisa que un PC de escritorio es por lo menos 10 veces más potente que un PDA,
podemos afirmar que para mantener el mismo nivel de usabilidad, las aplicaciones de una
PDA necesita limitarse a las tareas que son 10 veces más simples.
Dado que estamos utilizando el mismo lenguaje que utilizamos con éxito en aplicaciones de
PC, se acostumbra a caer en el error de desarrollar aplicaciones de la misma forma. En
nuestras aplicaciones de escritorio nos aprovechamos de la potencia barata y hemos
empleado bibliotecas extensas y ricas de clases para producir aplicaciones simples y
elegantes. Utilizamos parsers XML para los archivos de configuración y para detokenizar
mensajes pasados como documentos XML; esto proporciona una compresión superior de
los mensajes, pero no somos conscientes de la cantidad de proceso necesaria para realizar
estas funciones.
En el desarrollo de aplicaciones para PDA hemos de recordar que la aproximación de
desarrollo para PC no se puede aplicar sin considerar las diferencias de plataforma, y
particularmente la disponibilidad de recursos. Una meta del diseño para cualquier aplicación
en PDAs es sacar tanto trabajo como sea posible a otra computadora, que puede ser un PC
de escritorio o un servidor.
Pàg: 43
Estius Universitaris 06/07
Java Móvil J2ME
Limitaciones en el tamaño De Pantalla
•
Diseñar para la simplicidad y la facilidad de uso es un aspecto importante del diseño
de una aplicación, sin importar la tecnología o el medio. Una pantalla con una gran
cantidad de controles o de información exhibida implica que el usuario tardara más
en absorber esta información, destacar que el numero de botones en una pantalla
implica más tiempo de aprendizaje de la aplicación.
•
Para más pautas de cómo diseñar aplicaciones para Palm y conformes con otras
aplicaciones, se recomienda la lectura de "Palm OS Programmer's Companion"
documento número 3004-003. Este documento es parte
del kit del desarrollo de software para Palm OS.,
•
En MIDP de Palm, un Form no se limita a un tamaño
particular al añadir Items. Por ejemplo, se desean agregar
20 StringItems en un Form, nada impedirá hacerlo, pero
en pantalla solo se mostraran los 11 primeros, será
necesario realizar scroll para visualizar el resto.
•
Aunque es posible agregar más artículos de los que pueden
ser vistos en un Form, no se recomienda. Se realiza una
aplicación mas intuitiva si se evita el scrolling. Para el
ejemplo anterior una lista seria una buena aproximación.
Pàg: 44
Estius Universitaris 06/07
Java Móvil J2ME
Limitaciones en la capacidad de memoria (I)
•
Para argumentar por que Palm es un dispositivo limitado en memoria veremos
como se organiza la memoria en este dispositivo.
•
Para entender la organización de la
memoria en MIDP de Palm OS, debemos
ver como esta organizada esta, para
realizar este paso se debe ejecutar la
aplicación developer incluido en el suite,
y seleccionar show en developer
preferences
•
Esto nos mostrara una pantalla similar
a la presentada
•
Las descripciones que se muestran
corresponden a MIDP de Sun para Palm y
no a la organización de memoria para
aplicaciones no Java.
Pàg: 45
Estius Universitaris 06/07
Java Móvil J2ME
Limitaciones en la capacidad de memoria (II)
Tipo
Descripción
ROM
El tamaño de la imagen ROM en este dispositivo.
RAM
El tamaño combinado de RAM en este dispositivo. Palm OS divide la RAM en dos
áreas lógicas: dinámica y almacenaje. Ambas áreas siguen idénticas después de
apagar el dispositivo, pero un reset libera el área dinámica.
freeram
El tamaño combinado del heap de almacenaje y dinámico del dispositivo:
El “heap dinámico" se refiere a la RAM para alocatación dinámica como stack,
alocataciones dinamicas de la aplicación y del sistema. En Palm OS 3.5 con MB 4
o más, el espacio dinámico es de 256 KB. Este espacio se libera si no está
utilizada actualmente para las asignaciones dinámicas.
el “heap almacenamiento" es el resto de la RAM. Puede haber mas de un heap de
almacenamiento, estos se utilizan para almacenar datos permanentes, tales
como bases de datos.
En todas las versiones de Palm OS hasta la 4.0, el chunk máximo de RAM de
almacenamiento que se puede obtener por las aplicaciones es un poco menor de
64 o 128 KB (Depende de la versión). Este tamaño se incrementa en la versión
5.0
freeheap
El tamaño de la memoria disponible en el heap de almacenamiento.
maxheapchunk
El tamaño del chunk mayor de almacenamiento.
javafreeheap
La cantidad de memoria disponible en el heap de Java. Esta es el área del heap
dinámico que utiliza Java al asignar nuevos objetos y stack de aplicación, el valor
máximo es poco menor de 64 KB
permanent
La cantidad de memoria asignada internamente por el KVM.
Pàg: 46
Estius Universitaris 06/07
Java Móvil J2ME
Limitaciones en la capacidad de memoria (III)
•
Para ver cuanta memoria está disponible para el desarrollador, podemos escribir una sencilla
aplicación. Hay dos métodos en la clase runtime que son útiles para trabajar con la memoria
disponible. Son totalMemory y freeMemory. El fragmento siguiente del código demuestra cómo
determinar la memoria disponible dentro de un MIDlet:
Runtime runtime = Runtime.getRuntime();
runtime.gc();
System.out.println("Total: " + runtime.totalMemory() +
" Free: " + runtime.freeMemory());
•
•
•
Destacar que se utiliza el método gc de runtime antes de llamar el método freeMemory. El
propósito de esta llamada es obligar a la JVM a limpiar los objetos no utilizados y no liberador por
el garbage collector porque la cantidad de memoria no es suficientemente baja para dispararlo.
La cantidad de memoria devuelta por freeMemory puede ser diferente de la cantidad de memoria
reportada por javafreeheap. Esto es porque el javafreeheap corresponde con el heap dinámico
interno de Java para stack y nuevos objetos, mientras que freeMemory retorna una aproximación
de la cantidad de memoria disponible para la futura asignación de objetos.
El MIDlet MemoryMIDlet, StaticMemoryMIDlet, y MultipleClassMIDlet cada uno realiza
una alocatación de memoria diferente. MemoryMIDlet asigna un nuevo array de 1000 bytes.
Runtime runtime = Runtime.getRuntime();
runtime.gc();
beforeFree = runtime.freeMemory();
largeArray = new byte[1000];
runtime.gc();
afterFree = runtime.freeMemory();
System.out.println("Total: " + runtime.totalMemory() +
" Free (before): " + beforeFree +
" Free (after): " + afterFree);
Pàg: 47
Estius Universitaris 06/07
Java Móvil J2ME
Limitaciones en la capacidad de memoria (IV)
•
StaticMemoryMIDlet hace lo mismo, pero también tiene un array estático de 2000 bytes:
•
Finalmente, MultipleClassMIDlet crea una instancia de LargeClass , una clase con un
atributo que referencia a un array de 1000 bytes:
static byte[] largeStaticArray = new byte[2000];
LargeClass largeClass = new LargeClass();
donde LargeClass se define como:
package com.javamovil.small;
public class LargeClass {
private byte[] byteArray = new byte[1000];
public String method1(String s1, String s2) {
return s1+s2;
}
public String method2(String s1, String s2) {
return s1+s2;
}
}
•
El número de bytes devueltos por freeMemory() se ha registrado antes y después la asignación
dinámica.
Pàg: 48
Estius Universitaris 06/07
Java Móvil J2ME
Limitaciones en la capacidad de memoria (V)
MIDlet
Bytes
Consumidos
en cargar el
Midlet
Bytes que se
consumirán en el
proceso del
comando "Allocate"
Alocatación hecha
MemoryMIDlet
4396
1016
Allocatar un array de 1000 bytes
StaticMemoryMIDlet
6412
1016
Allocatar un array de 1000 bytes
MultipleClassMIDlet
4392
1032
Allocatar una nueva instancia de
LargeClass
•
De la tabla, se observa que un objeto array estático toma el espacio del
mismo heap de Java que se utiliza para asignar objetos dinámicos. Es
decir, los objetos estáticamente y dinámicamente asignados utilizan el
mismo espacio del heap. Según lo observado previamente, el espacio de
heap se restringe a 64 KB en Palm OS 3.X y 4.X.
Pàg: 49
Estius Universitaris 06/07
•
Estructura básica de un Midlet (I)
El Gestor de Aplicaciones
–
El gestor de aplicaciones o AMS (Application Management System) es el software
encargado de gestionar los MIDlets. Este software reside en el dispositivo y es el que nos
permite ejecutar, pausar o destruir nuestras aplicaciones J2ME. A partir de ahora nos
referiremos a él con las siglas de sus iniciales en inglés AMS, El AMS realiza dos grandes
funciones:
•
•
•
Java Móvil J2ME
Por un lado gestiona el ciclo de vida de los MIDlets.
Por otro, es el encargado de controlar los estados por los que pasa el MIDlet mientras está en la
memoria del dispositivo, es decir, en ejecución.
Ciclo de vida de un MIDlet
–
–
–
–
–
–
–
El ciclo de vida de un MIDlet pasa por 5 fases: descubrimiento,
instalación, ejecución, actualización y borrado.
Estas fases son aplicables principalmente a las aplicaciones
para teléfonos móviles, con servicios asociados y generalmente
de pago para la instalación de aplicaciones en el dispositivo.
Descubrimiento: Etapa que permite descargar aplicaciones
de diversas formas, servicios de pago, conexión directa, etc.
Instalación: Etapa que se encarga del deploy de la aplicación
dejándola dispuesta para su uso.
Ejecución: A continuación analizaremos con más detalle esta fase.
Actualización: Ciclo de vida del MIDlet, detectando si es una nueva
instalación o la actualización de un MIDlet existente.
Borrado: Deben de controlarse los errores y garantizar el correcto borrado
del o de los MIDlets
Pàg: 50
Estius Universitaris 06/07
Java Móvil J2ME
Estructura básica de un Midlet (II)
•
Estados de un MIDlet
–
Un MIDlet durante su ejecución pasa por 3 estados diferentes, estos tres estados son:
•
•
•
–
Activo: El MIDlet está actualmente en ejecución.
Pausa: El MIDlet no está actualmente en ejecución. En este estado el MIDlet no debe usar ningún
recurso compartido. Para volver a pasar a ejecución tiene que cambiar su estado a Activo. A este
estado se llegaría por ejemplo si mientas se esta ejecutando la aplicación se recibe un mensaje, una
llamada, una alarma, etc.
Destruido: El MIDlet no está en ejecución ni puede
transitar a otro estado. Además se liberan todos los
recursos ocupados por el MIDlet.
Como vemos en el diagrama, un MIDlet puede
cambiar de estado mediante una llamada a los
métodos MIDlet.startApp(),
MIDlet.pauseApp() o MIDlet.destroyApp().
El gestor de aplicaciones cambia el estado de
los MIDlets haciendo una llamada a cualquiera
de los métodos anteriores.
Un MIDlet también puede cambiar de estado por
sí mismo.
Pàg: 51
Estius Universitaris 06/07
Java Móvil J2ME
Estructura básica de un Midlet (III)
– Ahora vamos a ver por los estados que pasa un MIDlet durante una ejecución
típica y cuáles son las acciones que realiza tanto el AMS como el MIDlet. En
primer lugar, se realiza la llamada al constructor del MIDlet pasando éste al
estado de “Pausa” durante un corto período de tiempo. El AMS por su parte crea
una nueva instancia del MIDlet. Cuándo el dispositivo está preparado para
ejecutar el MIDlet, el AMS invoca al método MIDlet.startApp() para entrar en el
estado de “Activo”. El MIDlet entonces, ocupa todos los recursos que necesita
para su ejecución. Durante este estado, el MIDlet puede pasar al estado de
“Pausa” por una acción del usuario, o bien, por el AMS 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.
Pàg: 52
Estius Universitaris 06/07
Java Móvil J2ME
Estructura de un MIDlet
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 el 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, etc. (Opcional)
*/
}
}
Pàg: 53
Estius Universitaris 06/07
Java Móvil J2ME
El paquete javax.microedition.midlet (I)
•
El paquete javax.microedition.midlet define las aplicaciones MIDP y su
comportamiento con respecto al entorno de ejecución. Como ya sabemos, una
aplicación creada usando MIDP es un MIDlet.
•
Clase MIDlet
– public abstract class MIDlet
– Un MIDlet es una aplicación realizada usando el perfil MIDP como ya
sabemos. La aplicación debe extender esta clase para que el AMS
pueda gestionar sus estados y tener acceso a sus propiedades. El
MIDlet puede por sí mismo realizar cambios de estado invocando a los
métodos apropiados. Los métodos de los que dispone esta clase son
los siguientes:
– protected MIDlet()
– Constructor de clase sin argumentos. Si la llamada a este constructor
falla, se lanzaría la excepción SecurityException.
Pàg: 54
Estius Universitaris 06/07
Java Móvil J2ME
El paquete
javax.microedition.midlet (II)
– protected abstract void destroyApp(boolean incondicional) throws
–
–
–
–
–
–
–
–
MIDletstateChangeException
Indica la terminación del MIDlet y su paso al estado de “Destruido”. En el estado de
“Destruido” el MIDlet debe liberar todos los recursos y salvar cualquier dato en el
almacenamiento persistente que deba ser guardado. Este método puede ser llamado desde
los estados “Pausa” o “Activo”.
Si el parámetro ‘incondicional’ es false, el MIDlet puede lanzar la excepción
MIDletstateChangeException para indicar que no puede ser destruido en este momento. Si
es true, el MIDlet asume su estado de destruido independientemente de como finalice el
método.
public final String getAppProperty(String key)
Este método proporciona al MIDlet un mecanismo que le permite recuperar el valor de las
propiedades desde el AMS. Las propiedades se consiguen por medio de los archivos
manifest y JAD. 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.
public final void notifyDestroyed()
Este método es utilizado por un MIDlet para indicar al AMS que ha entrado en el estado de
“Destruido”. En este caso, todos los recursos ocupados por el MIDlet deben ser liberados
por éste de la misma forma que si se hubiera llamado al método MIDlet.destroyApp(). El
AMS considerará que todos los recursos que ocupaba el MIDlet están libres para su uso.
public final void notifyPaused()
Se notifica al AMS que el MIDlet no quiere estar “Activo” y que ha entrado en el estado de
“Pausa”. Este método sólo debe ser invocado cuándo el MIDlet esté en el estado “Activo”.
Una vez invocado este método, el MIDlet puede volver al estado “Activo” llamando al
método MIDlet.startApp(), o ser destruido llamando al método MIDlet.destroyApp(). Si la
aplicación es pausada por sí misma, es necesario llamar al método MIDlet.resumeRequest()
para volver al estado “Activo”.
Pàg: 55
Estius Universitaris 06/07
Java Móvil J2ME
El paquete javax.microedition.midlet (III)
– protected abstract void pauseApp()
– Indica al MIDlet que entre en el estado de “Pausa”. Este método sólo debe ser llamado
cuándo el MIDlet esté en estado “Activo”. 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.
– public final void resumeRequest()
– Este método proporciona un mecanismo a los MIDlets mediante el cual pueden indicar
al AMS su interés en pasar al estado de “Activo”. El AMS, en consecuencia, es el
encargado de determinar qué aplicaciones han de pasar a este estado llamando al
método MIDlet.startApp().
– protected abstract void startApp() throws
MIDletstateChangeException
– Este método indica al MIDlet que ha entrado en el estado “Activo”. Este método sólo
puede ser invocado cuándo el MIDlet está en el estado de “Pausa”. 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.
– A través de los métodos anteriores se establece una comunicación entre el AMS y el
MIDlet. Por un lado tenemos que 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.
Pàg: 56
Estius Universitaris 06/07
Java Móvil J2ME
El paquete javax.microedition.midlet (IV)
•
Clase MIDletChangeStateException
– public class MIDletstateChangeException extends Exception
– Esta excepción es lanzada cuando ocurre un fallo en el cambio de estado de
un MIDlet.
Pàg: 57
Estius Universitaris 06/07
Java Móvil J2ME
Mi primer MIDlet
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class HolaMundo extends MIDlet {
private Display display;
private Form screen;
public HolaMundo() {
display=Display.getDisplay(this);
screen = new Form("HolaJME");
StringItem strItem = new StringItem(" ","Hola mundo");
screen.append(strItem);
}
public void startApp() throws MIDletStateChangeException{
display.setCurrent(screen);
}
public void pauseApp(){
}
public void destroyApp(boolean unconditional){
display=null;
screen=null;
notifyDestroyed();
}
}
Pàg: 58
Estius Universitaris 06/07
La interfaz de usuario (I)
Object
Ticker
CommandListener
AlertType
Font
Graphics
ItemStateListener
Java Móvil J2ME
Command
Image
Item
Display
Diplayable
Canvas
Screen
Form
Alert
List
TextBox
ChoiceGroup
DateField
java.lang.*
Gauge
ImageItem
StringItem
javax.microedition.lcdui.*
Choice
TextField
javax.microedition.lcdui.* (Interface)
Pàg: 59
Estius Universitaris 06/07
Java Móvil J2ME
La interfaz de usuario: Displayable
•
Displayable es la clase padre de Screen y Canvas, estas proporcionan las
funciones básicas del interfaz de usuario de una aplicación. Displayable puede
tener un número de comandos, que son objetos visuales usados para iniciar una
cierta acción en la aplicación. Un comando se puede implementar de varias formas;
boton, item del menú, ... . Un comando tiene una etiqueta, un tipo, y una prioridad.
La etiqueta es un string usado para distinguir el comando en la interfaz de usuario. El
tipo del comando proporciona la implementación del MIDP para tratar este comando.
Los tipos del comando son: BACK, CANCEL, EXIT, HELP, ITEM, OK, SCREEN, y
STOP. Dando a un comando un tipo CANCEL, por ejemplo, el desarrollador deja al
MIDP el tratamiento de la información que se pudiera haber introducido que será, a
priori cancelada. Observe que para los tipos del comando con excepción de
SCREEN, la implementación de MIDP puede modificar la etiqueta por una mas
apropiada para el dispositivo. A Command se le puede dar una prioridad, que
proporciona otra característica de MIDP referente al orden con que este comando se
debe exhibir respecto a otros comandos en la misma pantalla. Un número más bajo
indica una prioridad más alta. Por ejemplo, para crear un nuevo comando que
representa una acción para salir de la aplicación, escribiríamos lo siguiente:
Pàg: 60
Estius Universitaris 06/07
Java Móvil J2ME
La interfaz de usuario: Command
Command exitCommand = new Command("Exit", Command.EXIT, 10);
•
Esto indica a la aplicación que el botón de salida debe aparecer al final de los
command's del menú dado que le hemos asignado una prioridad baja.
•
Una vez que una aplicación haya creado sus objetos Command, un objeto que
implementa la interfaz CommandListener debe ser asignado para tratar los
eventos. Esto se hace con el método setCommandListener, invocado en un objeto
derivado de Displayable. El interfaz de CommandListener especifica un método,
el commandAction, al que se le pasa el comando que es activado, y el objeto
Displayable a el cual pertenece.
•
La diferencia entre un Screen y Canvas es que el primero se utiliza como base para
construir un interfaz de usuario basado en formularios, mientras que el segundo se
utiliza para dibujar imágenes, líneas, y círculos. El curso se va a centrar en interfaces
de usuario generados a partir de Screen.
•
Hay cuatro tipos de Screen: Alarm, Form, List, y TextBox. Cualquiera de ellos
puede tener agregados objetos Command, tal i como pueden tener un título.
Pàg: 61
Estius Universitaris 06/07
Java Móvil J2ME
La interfaz de usuario: Form (I)
•
Una Form es un tipo especial de Screen, en el que se pueden colocar Item’s.
Un Item es un control simple del interfaz de usuario, En un Form se pueden
colocar varios Items. Las subclases de Item son botones de múltiple o simple
selección, controles de fecha y de hora, control de barra, control de imagen,
control de sting, y control de entrada de texto.
Para crear un Form vacio:
Form mainForm = new Form("BaseUIMIDlet");
•
Recordemos crear el comando exit, para poder abandonar el MIDlet:
Command exitCommand = new Command("Salir", Command.EXIT, 10);
•
Debido a que una aplicación puede tener varios objetos Displayable (es decir,
muchas instancias de Form's, Alert's, List's, TextBox'es, y Canvas'es), y
debido a que únicamente se puede ocupar el display con un objeto
Displayable, necesitamos una forma de especificar qué Displayable debe
ser visible. Esto se hace con la clase Display. Con un objeto Display,
podemos descubrir que Displayable es actualmente visible, y podemos fijar
que Displayable se hará visible. Cada MIDlet tiene un Display. Para obtener
una referencia a el, utilizaremos el método estático getDisplay en la clase
Display, pasándole una referencia al objeto MIDlet.
Así pues, para nuestro ejemplo, necesitaremos una referencia al objeto Display:
Display display = null;
Pàg: 62
Estius Universitaris 06/07
Java Móvil J2ME
La interfaz de usuario: Form (II)
•
En el constructor del MIDlet, agregamos el comando exit y fijamos el MIDlet para
ser el listener de este comando:
mainForm.addCommand(exitCommand);
mainForm.setCommandListener(this);
•
En el método startApp, obtenemos una referencia al Display del MIDlet, y
fijamos el Display actual a nuestro Form recién creado:
display = Display.getDisplay(this);
display.setCurrent(mainForm);
•
Dado que hemos fijado el MIDlet para ser el listener del comando exit,
necesitamos implementar el método commandAction para tomar las acciones
apropiadas cuando suceda el evento del comando exit. A modo de ejemplo:
public void commandAction(Command c, Displayable d) {
if (c == exitCommand) {
destroyApp(false);
notifyDestroyed();
}
}
Pàg: 63
Estius Universitaris 06/07
Java Móvil J2ME
La interfaz de usuario: Form (III)
•
En el código siguiente se observa un ejemplo que agrupa lo visto anteriormente.
Dado que vamos a intentar que todos los ejemplos tengan el mismo
comportamiento básico, la clase de BaseUIMIDlet también proporcionará la clase
base para todos los ejemplos de la interfaz de usuario.
package com.f2i.jmd.ui;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class BaseUIMIDlet extends MIDlet
implements CommandListener {
protected Form mainForm = new Form("BaseUIMIDlet");
protected Command exitCommand = new Command("Salir",
Command.EXIT, 10);
protected Display display = null;
protected static final String[] MOVIES = {"Gladiator",
"The Patriot",
"A Few Good Men"};
protected Command okCommand = new Command("OK",
Command.SCREEN, 1);
protected Command backCommand = new Command("Atras",
Command.SCREEN, 2);
Pàg: 64
Estius Universitaris 06/07
Java Móvil J2ME
La interfaz de usuario: Form (IV)
public BaseUIMIDlet() {
mainForm.addCommand(exitCommand);
mainForm.setCommandListener(this);
}
public void startApp() {
display = Display.getDisplay(this);
display.setCurrent(mainForm);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
public void commandAction(Command c, Displayable d) {
if (c == exitCommand) {
destroyApp(false);
notifyDestroyed();
}
}
}
Pàg: 65
Estius Universitaris 06/07
Java Móvil J2ME
La interfaz de usuario: Form (V)
•
En el ejemplo anterior el comando salir se ha implementado como:
•
Esto sitúa la acción en el menú Go, si se hubiera definido como
Command.SCREEN se hubiera situado en el menú Actions y tendría asociado un
botón el la pantalla:
protected Command exitCommand = new Command("Salir",Command.EXIT, 10);
protected Command exitCommand = new Command("Salir",Command.SCREEN, 10);
•
Algunas implementaciones de MIDP pueden, sobrescribir la etiqueta definida para
un command por la de defecto del dispositivo, esto no es así en la implementación
de Palm. Destacar que el tipo de comando obligara a que este aparezca en un
determinado submenú de opciones, p.ex. Si se define como Command.HELP,
provocaría que se situara en el submenú Options:
protected Command exitCommand = new Command("Salir",Command.HELP, 10);
Pàg: 66
Estius Universitaris 06/07
Java Móvil J2ME
La interfaz de usuario: Form (VI)
•
Como se menciono previamente, la implementación de MIDP determina
cómo se dibujan los objetos de comando, dependiendo de las
capacidades del dispositivo. En un dispositivo Palm usando el MIDP de
Sun, los objetos Command de tipo SCREEN se dibujan como botones en
el fondo de la pantalla. Si hay muchos Command's, o sus etiquetas
hicieran los botones demasiado grandes para situarlos a lo largo de la
pantalla, los Command's restantes se colocan como entradas de menú en
el menú de Actions.
•
En el ejemplo siguiente, se crearan seis Command's, todos ellos del tipo
SCREEN, con igual prioridad, y los agregamos al Form anterior.
Observar que crearemos una subclase de BaseUIMIDlet, esto lo
realizaremos para todos los ejemplos, de modo que obtengamos el
mismo comportamiento fundamental (y ahorremos un poco de trabajo).
Pàg: 67
Estius Universitaris 06/07
Java Móvil J2ME
La interfaz de usuario: Form (VII)
package com.f2i.jmd.ui;
import javax.microedition.lcdui.*;
public class CommandMIDlet extends BaseUIMIDlet {
public Command command1Command = new Command("1",
1);
public Command command2Command = new Command("2",
1);
public Command command3Command = new Command("3",
1);
public Command command4Command = new Command("4",
1);
public Command command5Command = new Command("5",
1);
public Command command6Command = new Command("6",
1);
public CommandMIDlet() {
super();
mainForm.setTitle("CommandMIDlet");
mainForm.addCommand(command1Command);
mainForm.addCommand(command2Command);
mainForm.addCommand(command3Command);
mainForm.addCommand(command4Command);
mainForm.addCommand(command5Command);
mainForm.addCommand(command6Command);
}
}
Pàg: 68
Command.SCREEN,
Command.SCREEN,
Command.SCREEN,
Command.SCREEN,
Command.SCREEN,
Command.SCREEN,
Estius Universitaris 06/07
Java Móvil J2ME
La interfaz de usuario: Alert (I)
•
•
Un Alert es una pantalla que presenta texto y opcionalmente una imagen.
Típicamente, un Alert se utiliza para presentar una información para el usuario
o para indicar que una acción urgente se debe tomar. Un Alert puede tener un
time-out, o esperar a que el usuario la reconozca.
Para crear un Alert y para fijar su temporización (a cinco segundos, por
ejemplo), el código seria:
Alert alert = new Alert("Alerta");
alert.setTimeout(5000);
alert.setString("Esta es una alerta que se mostrara por 5 segundos");
•
Para mostrar el Alert, e ir de nuevo al Form principal cuando pase el tiempo,
podemos utilizar el método setCurrent que toma un Alert y un
Displayable como parámetros.
display.setCurrent(alert, mainForm);
•
•
Los números exhibidos en el círculo en la esquina izquierda inferior de la alerta
indican el número de segundos restantes hasta el cierre de la alerta.
Hay dos formas que la alerta no será reconocida automáticamente. La primera es
si el texto de la alarma es demasiado grande para ser mostrado en una pantalla.
En este caso, sin importar el valor del temporizador de la alerta, esta
permanecerá en pantalla hasta que el usuario la cierre.
Pàg: 69
Estius Universitaris 06/07
Java Móvil J2ME
La interfaz de usuario: Alert (II)
•
•
•
•
Para forzar una alarma a ser reconocida, se debe usar el valor de temporizador FOREVER, como en
el siguiente ejemplo:
Alert alert = new Alert("AlertaSiempre");
alert.setTimeout(Alert.FOREVER);
alert.setString("Texto de la alerta");
display.setCurrent(alert, mainForm);
En esta alerta queda en manos de MIDP dibujar el botón "Done".
Una alerta puede también tener un tipo, que indica la naturaleza de la alerta. Las opciones son
CONFIRMATION, WARNING, INFO, ERROR, y ALARM. El tipo de la alerta afecta al icono exhibido en la
misma.
El AlertType también se puede utilizar para reproducir un sonido que acompañe la alerta. Este
esta limitado a las capacidades del dispositivo.
AlertType.WARNING.playSound(display);
Pàg: 70
Estius Universitaris 06/07
Java Móvil J2ME
La interfaz de usuario: Alert (II)
•
•
Una alerta es una buena herramienta para mostrar una pequeña cantidad de
información, las usaremos en los ejemplos siguientes para mejorar los
conocimientos de los Form's.
Para crear interfaces de usuario más sofisticadas, tenemos la posibilidad de
añadir objetos derivados de Item en los formularios. Destacar que los derivados
de Item sólo pueden aparecer en formularios.
Pàg: 71
Estius Universitaris 06/07
Java Móvil J2ME
La interfaz de usuario: ChoiceGroup (I)
•
Un ChoiceGroup se utiliza para obtener una sola selección o selecciones múltiples
de un grupo de opciones. La implementación de MIDP determina como se dibuja
el objeto. En dispositivos Palm, los grupos de una única selección se dibujan
como listas de una sola selección, mientras que los grupos de selección múltiple
se dibujan como cajas de selección.
Los grupos de única selección se crean:
protected static final String[] MEDIA = {"DVD", "VHS"};
ChoiceGroup singleChoice = new ChoiceGroup("Media",ChoiceGroup.EXCLUSIVE,
MEDIA, null);
•
•
Para este ejemplo, se ha escogido un constructor que permite que las etiquetas
sean especificadas como un array de strings. Se escoge no acompañar las
opciones de imágenes, indicando el ultimo parámetro del constructor como null.
Observar que también existe el tipo IMPLICIT. La única diferencia entre
EXCLUSIVE e IMPLICIT es que es posible registrar un objeto de
CommandListener para el tipo IMPLICIT, y se notifica cuando la selección
cambie. No hay notificación para el tipo EXCLUSIVE.
Se puede añadir un ChoiceGroup a un Form:
Form choiceForm = new Form("Selección de películas");
choiceForm.append(singleChoice);
Pàg: 72
Estius Universitaris 06/07
Java Móvil J2ME
La interfaz de usuario: ChoiceGroup (II)
•
Para obtener la selección del usuario se debe añadir al command listener del formulario un
código como el siguiente:
int i = singleChoice.getSelectedIndex();
String mediaSelected = singleChoice.getString(i);
•
Para selecciones múltiples se debe utilizar MULTIPLE como tipo:
ChoiceGroup multipleChoice = new ChoiceGroup("Películas", ChoiceGroup.MULTIPLE, MOVIES,
null);
•
Para obtener las selecciones, un array de flags boleanos es utilizado por el método
getSelectedFlags:
boolean[] selections = new boolean[multipleChoice.size()];
multipleChoice.getSelectedFlags(selections);
•
El flag boleano correspondiente a la selección es puesto true si el usuario selecciono la
opción, un código que haría lo descrito seria:
String movieSelected = new String();
boolean[] selections = new boolean[multipleChoice.size()];
multipleChoice.getSelectedFlags(selections);
for (int j=0; j<selections.length; j++)
if (selections[j])
movieSelected += multipleChoice.getString(j) +
" on " + mediaSelected + "\n";
•
Colocando todo lo anterior en el MIDlet ChoiceGroupMIDlet mostrará un formulario con un
grupo de selección simple, cuando el usuario presione el botón OK, se mostrara una alerta
con las selecciones del usuario de ambos grupos.
Pàg: 73
Estius Universitaris 06/07
Java Móvil J2ME
La interfaz de usuario: ChoiceGroup (III)
package com.f2i.jmd.ui;
import javax.microedition.lcdui.*;
public class ChoiceGroupMIDlet extends BaseUIMIDlet {
protected static final String[] MEDIA = {"DVD", "VHS"};
protected Command choiceCommand =
new Command("Choice", Command.SCREEN, 1);
public ChoiceGroupMIDlet() {
super();
mainForm.setTitle("ChoiceGroupMIDlet");
mainForm.addCommand(choiceCommand);
}
public void commandAction(Command c, Displayable d) {
if (c == choiceCommand) {
Form choiceForm = new Form("Selección de películas");
ChoiceGroup singleChoice = new ChoiceGroup("Media",
ChoiceGroup.EXCLUSIVE, MEDIA, null);
ChoiceGroup multipleChoice = new ChoiceGroup("Películas",
ChoiceGroup.MULTIPLE, MOVIES, null);
choiceForm.append(singleChoice);
choiceForm.append(multipleChoice);
Pàg: 74
Estius Universitaris 06/07
Java Móvil J2ME
La interfaz de usuario: ChoiceGroup (IV)
choiceForm.addCommand(okCommand);
choiceForm.addCommand(backCommand);
choiceForm.addCommand(exitCommand);
choiceForm.setCommandListener(this);
display.setCurrent(choiceForm);
}
else if (c == okCommand) {
Form choiceForm = (Form)d;
ChoiceGroup singleChoice =
(ChoiceGroup)(choiceForm.get(0));
ChoiceGroup multipleChoice =
(ChoiceGroup)(choiceForm.get(1));
// Obtener la selección
int i = singleChoice.getSelectedIndex();
String mediaSelected = singleChoice.getString(i);
// get the movie selection
String movieSelected = new String();
boolean[] selections = new boolean[multipleChoice.size()];
multipleChoice.getSelectedFlags(selections);
for (int j=0; j<selections.length; j++)
if (selections[j])
movieSelected += multipleChoice.getString(j) +
" on " + mediaSelected + "\n";
Pàg: 75
Estius Universitaris 06/07
Java Móvil J2ME
La interfaz de usuario: ChoiceGroup (V)
// Mostrar el resultado
Alert alert = new Alert(“Selección");
alert.setString(movieSelected);
alert.setTimeout(5000);
alert.setType(AlertType.INFO);
display.setCurrent(alert, mainForm);
}
else if (c == backCommand) {
display.setCurrent(mainForm);
}
else {
super.commandAction(c, d);
}
}
}
Pàg: 76
Estius Universitaris 06/07
Java Móvil J2ME
La interfaz de usuario: DateField (I)
•
La clase DateField provee una forma de mostrar y entrar fechas y horas, se muestra un
código de ejemplo:
DateField startDateField = new DateField("Fecha de vencimiento", DateField.DATE_TIME);
startDateField.setDate(new Date());
mainForm.append(startDateField);
•
La fecha y hora que se muestra va fijada en un objeto Date, en el ejemplo anterior se utiliza el
los datos actuales del dispositivo, para fijar unos datos se puede utilizar lo siguiente:
DateField returnDateField = new DateField("Fecha de vuelta", DateField.DATE_TIME);
Calendar calendar = Calendar.getInstance();
calendar.setTime(tomorrow());
calendar.set(Calendar.HOUR, 10);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.AM_PM, Calendar.PM);
returnDateField.setDate(calendar.getTime());
mainForm.append(returnDateField);
•
Dado que MIPD no dispone de tipos para calculo de fechas estos se deberán realizar
manualmente:
private Date manana() {
Date hoy = new Date();
Date manana = new Date(hoy.getTime()+(24*60*60*1000));
return manana;
}
Pàg: 77
Estius Universitaris 06/07
Java Móvil J2ME
La interfaz de usuario: DateField (II)
package com.f2i.jmd.ui;
import javax.microedition.lcdui.*;
import java.util.*;
public class DateFieldMIDlet extends BaseUIMIDlet {
public DateFieldMIDlet() {
super();
mainForm.setTitle("DateFieldMIDlet");
DateField startDateField = new DateField("Fecha de vencimiento", DateField.DATE_TIME);
startDateField.setDate(new Date());
mainForm.append(startDateField);
DateField returnDateField = new DateField("Fecha de vuelta", DateField.DATE_TIME);
Calendar calendar = Calendar.getInstance();
calendar.setTime(manana());
calendar.set(Calendar.HOUR, 10);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.AM_PM, Calendar.PM);
returnDateField.setDate(calendar.getTime());
mainForm.append(returnDateField);
}
Pàg: 78
Estius Universitaris 06/07
Java Móvil J2ME
La interfaz de usuario: DateField (III)
private Date manana() {
Date hoy = new Date();
Date manana = new Date(hoy.getTime()+(24*60*60*1000));
return manana;
}
public void commandAction(Command c, Displayable d) {
super.commandAction(c, d);
}
}
Pàg: 79
Estius Universitaris 06/07
Java Móvil J2ME
La interfaz de usuario: Gauge (I)
•
Gauge se utiliza para mostrar y editar un valor en un rango, el código para su
creación seria:
Gauge gauge = new Gauge("Valor", true, 20, 5);
gaugeForm.append(gauge);
•
•
El primer parámetro especifica la etiqueta, el segundo es un boleano que indica si
es editable, el tercero el valor final, y el último el inicial.
El valor puede ser recuperado con el método getValue del objeto, la forma de
dibujo puede variar en función de que el Gauge sea editable.
package com.f2i.jmd.ui;
import javax.microedition.lcdui.*;
import java.lang.Integer;
public class GaugeMIDlet extends BaseUIMIDlet {
protected Gauge gauge1;
protected Gauge gauge2;
public GaugeMIDlet() {
super();
mainForm.setTitle("GaugeMIDlet");
gauge1 = new Gauge("Valor 1", true, 20, 5);
mainForm.append(gauge1);
gauge2 = new Gauge("Valor 2", false, 20, 5);
mainForm.append(gauge2);
Pàg: 80
Estius Universitaris 06/07
Java Móvil J2ME
La interfaz de usuario: Gauge (II)
mainForm.addCommand(okCommand);
mainForm.setCommandListener(this);
}
public void commandAction(Command c, Displayable d) {
if (c == okCommand) {
int valor=gauge1.getValue();
Integer valin = new Integer(valor);
Alert alert = new Alert("Valor selecionado");
alert.setString("El Valor es " + valin.toString());
alert.setTimeout(5000);
alert.setType(AlertType.INFO);
display.setCurrent(alert, mainForm);
gauge2.setValue(valor);
}
else {
super.commandAction(c, d);
}
}
}
Pàg: 81
Estius Universitaris 06/07
Java Móvil J2ME
La interfaz de usuario: StringItem (I)
•
Un StringItem es un Item utilizado para Mostar texto estático en un Form. Esta
formado por una etiqueta y el texto en si. Este no se puede editar por el usuario:
StringItem addressLine1 = new StringItem("Dirección 1", "Sabadell, 67");
stringItemForm.append(addressLine1);
•
Ejemplo:
package com.f2i.jmd.ui;
import javax.microedition.lcdui.*;
public class StringItemMIDlet extends BaseUIMIDlet {
private Command stringItemCommand =
new Command("StringItem", Command.SCREEN, 1);
public StringItemMIDlet() {
super();
mainForm.setTitle("StringItemMIDlet");
mainForm.addCommand(stringItemCommand);
}
public void commandAction(Command c, Displayable d) {
if (c == stringItemCommand) {
Form stringItemForm = new Form("Detalles de dirección");
StringItem addressLine1 =
new StringItem("Dirección 1", "Sabadell, 67");
Pàg: 82
Estius Universitaris 06/07
Java Móvil J2ME
La interfaz de usuario: StringItem (II)
StringItem addressLine2 =
new StringItem("Dirección 2", "Barcelona");
StringItem postcode = new StringItem("Código Postal", "08003");
stringItemForm.append(addressLine1);
stringItemForm.append(addressLine2);
stringItemForm.append(postcode);
stringItemForm.addCommand(backCommand);
stringItemForm.addCommand(exitCommand);
stringItemForm.setCommandListener(this);
display.setCurrent(stringItemForm);
}
else if (c == backCommand) {
display.setCurrent(mainForm);
}
else {
super.commandAction(c, d);
}
}
}
Pàg: 83
Estius Universitaris 06/07
Java Móvil J2ME
La interfaz de usuario: TextField (I)
•
Un elemento TextField es similar en aspecto a un StringItem, excepto que
un TextField permite al usuario modificar o introducir el texto. Un TextField
puede también aplicar filtros al texto que se introduce; el filtro se considera una
mascara de entrada. Para crear un TextField con el contenido del texto
inicializado, utilizan al constructor siguiente:
TextField addressLine1 = new TextField("Dirección 1", "Sabadell, 67", 20,
TextField.ANY);
•
El último parámetro pasado al constructor es donde las mascaras de entrada
pueden ser especificados. Las mascaras disponibles son ANY, EMAILADDR,
NUMERIC, PASSWORD, PHONENUMBER, y URL. En cada caso, únicamente la
entrada indicada por la mascara será aceptada por el campo. Cuando el usuario
ha acabado de modificar o incorporar del texto, el texto del campo puede ser
recuperado llamando el método getString. El código siguiente muestra cómo
un TextField se podría utilizar en una aplicación:
package com.f2i.jmd.ui;
import javax.microedition.lcdui.*;
public class TextFieldMIDlet extends BaseUIMIDlet {
private Command textFieldCommand =
new Command("TextField", Command.SCREEN, 1);
Pàg: 84
Estius Universitaris 06/07
Java Móvil J2ME
La interfaz de usuario: TextField (II)
public TextFieldMIDlet() {
super();
mainForm.setTitle("TextFieldMIDlet");
mainForm.addCommand(textFieldCommand);
}
public void commandAction(Command c, Displayable d) {
if (c == textFieldCommand) {
Form textFieldForm = new Form("Confirme su dirección");
TextField addressLine1 = new TextField("Dirección 1",
"Sabadell, 67", 20, TextField.ANY);
TextField addressLine2 = new TextField("Dirección 2",
"Barcelona", 20, TextField.ANY);
TextField postcode = new TextField("Código Postal",
"08003", 5, TextField.NUMERIC);
textFieldForm.append(addressLine1);
textFieldForm.append(addressLine2);
textFieldForm.append(postcode);
textFieldForm.addCommand(okCommand);
textFieldForm.addCommand(backCommand);
textFieldForm.addCommand(exitCommand);
textFieldForm.setCommandListener(this);
display.setCurrent(textFieldForm);
}
Pàg: 85
Estius Universitaris 06/07
Java Móvil J2ME
La interfaz de usuario: TextField (III)
else if (c == okCommand) {
Form textFieldForm = (Form)d;
TextField addressLine1 = (TextField)(textFieldForm.get(0));
TextField addressLine2 = (TextField)(textFieldForm.get(1));
TextField postcode = (TextField)(textFieldForm.get(2));
// display the result
Alert alert = new Alert("Dirección entrada");
alert.setString("La dirección es:\n" +
addressLine1.getString() + "\n" +
addressLine2.getString() + "\n" +
postcode.getString());
alert.setTimeout(5000);
alert.setType(AlertType.INFO);
display.setCurrent(alert, mainForm);
}
else if (c == backCommand) {
display.setCurrent(mainForm);
}
else {
super.commandAction(c, d);
}
}
}
•
Hasta ahora hemos utilizado dos subclases de Screen, que son Alert y Form, a
continuación vamos a estudiar los otros dos tipos: List y TextBox
Pàg: 86
Estius Universitaris 06/07
Java Móvil J2ME
La interfaz de usuario: List (I)
•
•
La lista es un tipo de Screen que permite al usuario seleccionar elementos. Tanto
List como ChoiceGroup se basan en el mismo interfaz. La principal diferencia
es el ámbito de utilización, un ChoiceGroup siempre se deberá utilizar dentro de
un formulario. List soporta los mismos tipos, todo y que la implementación no
tiene por que ser la misma que en ChoiceGroup, recordémoslos: IMPLICIT,
EXCLUSIVE, y MULTIPLE.
La creación se realizaría del siguiente modo:
List list = new List("Películas", List.EXCLUSIVE, MOVIES, null);
•
Como en ChoiceGroup, la selección se recupera de la lista usando los métodos
getSelectedIndex y getString:
int i = list.getSelectedIndex();
String movieSelected = list.getString(i);
•
Una lista MULTIPLE se crea de forma similar, y las selecciones se recuperan de
la misma manera que las selecciones múltiples para un ChoiceGroup.
List list = new List("Películas", List.MULTIPLE, MOVIES, null);
String movieSelected = new String();
boolean[] selections = new boolean[list.size()];
list.getSelectedFlags(selections);
for (int i=0; i<selections.length; i++)
if (selections[i])
movieSelected += list.getString(i) + "\n";
Pàg: 87
Estius Universitaris 06/07
Java Móvil J2ME
La interfaz de usuario: List (II)
•
Seria interesante construir un código que pusiera en practica los dos tipos de lista,
utilizando la lista de películas de BaseUIMIDlet, de forma similar a como se ha ido
realizando en los apartados anteriores, el resultado debería ser algo similar a:
Pàg: 88
Estius Universitaris 06/07
Java Móvil J2ME
La interfaz de usuario: TextBox
•
El TextBox es un tipo de pantalla que permite la entrada de texto en formato
libre. En un dispositivo Palm se visualiza como una pantalla de Memo. El
TextBox utiliza el mismo concepto de mascaras de entrada que TextField. El
modo de creación seria:
TextBox textBox = new TextBox("Películas", "", 20, TextField.ANY);
•
Para recuperar el contenido:
String movieSelected = textBox.getString();
Pàg: 89
Estius Universitaris 06/07
Java Móvil J2ME
La interfaz de usuario: Ticker
•
Por último vamos a analizar la clase Ticker, los objetos Ticker son como
letreros con información que se desplaza. Un objeto Ticker se crea del
siguiente modo:
Ticker ticker = new Ticker("Información: Llevese 2 películas al precio de
1...");
•
El Ticker se muestra en cualquier objeto derivado de Screen, usando el
método del setTicker. El MIDlet siguiente es igual que el ChoiceGroupMIDlet,
excepto que se ha añadido un Ticker en cada pantalla de la aplicación.
Ticker en el formulario principal, en la demostración de ChoiceGroup y en un Alert
Pàg: 90
Estius Universitaris 06/07
Java Móvil J2ME
Almacenamiento de información (I)
•
Dado que un PDA no se puede conectar siempre con un servidor de el
cual recuperar la información, almacenar la información en el dispositivo
local es muy importante. A continuación exploraremos los métodos
disponibles para almacenar información.
•
MIDP proporciona unas APIs simples de base de datos de sistema para
almacenar la información en el dispositivo. El sistema de APIs se llama
"Record Management System" (RMS). Estas APIs incluye métodos para
crear, para actualizar, para buscar, y para suprimir bases de datos.
•
La implementación de la base de datos se deja en manos de la
correspondiente implementación de MIDP en el dispositivo. En los
dispositivos Palm, la base de datos del RMS se implementa como una
DB de Palm OS.
•
A continuación estudiaremos la API RMS para almacenar información.
Pàg: 91
Estius Universitaris 06/07
Java Móvil J2ME
Almacenamiento
de información (II)
Las propiedades de estos almacenes de registros son:
•
1.
2.
3.
4.
5.
•
Cada Record Store está compuesto por cero o más registros.
Un nombre de Record Store es sensible a mayúsculas y minúsculas y está formado por
un máximo de 32 caracteres UNICODE.
Dentro de una suite no pueden coexistir dos Record Stores con el mismo nombre.
Si una suite de MIDlets es borrada del dispositivo MID, todos los RecordStores
pertenecientes a esa suite se borrarán.
Es posible que un MIDlet acceda a un Record
Además de un nombre, cada Record Store también posee otros dos atributos:
–
–
Número de versión: Es un valor entero que se actualiza conforme vayamos insertando,
modificando o borrando registros en el Record Store. Podemos consultar este valor
invocando al método RecordStore.getVersion().
Marca temporal: Es un entero de tipo long que representa el número de milisegundos
desde el 1 de enero de 1970 hasta el momento de realizar la última modificación en el
Record Store. Este valor lo podemos obtener invocando al método
RecordStore.getLastModified().
Pàg: 92
Estius Universitaris 06/07
Java Móvil J2ME
Métodos generales de RecordStore
Pàg: 93
Estius Universitaris 06/07
Java Móvil J2ME
Manipulación de registros
Pàg: 94
Estius Universitaris 06/07
Java Móvil J2ME
Uso de RecordStore (I)
•
La API RMS se encuentra en el paquete javax.microedition.rms del MIDP.
La clase central del paquete es RecordStore, que representa un almacén RMS.
La clase de RecordStore se utiliza para realizar todas las operaciones en los
registros. Las operaciones disponibles para el desarrollador son:
–
–
–
–
Crear, Abrir, Cerrar o Suprimir un RecordStore.
Agregue un nuevo registro, suprima un registro, iterar sobre los registros. Filtros y
comparadores pueden desarrollarse para clasificar y filtrar los registros según lo
deseado.
Obtenga la información sobre un RecordStore, número de registros, tamaño, la
cantidad de memoria restante para el RecordStore, su nombre, el tiempo que la ultima
modificación, y el número de veces que se ha modificado (es decir, la versión).
Vincular un "listener" para recibir una notificación cuando se modifica un registro.
•
Para crear y para abrir un RecordStore nuevo, utilizamos el método estático
openRecordStore sobre un objeto RecordStore:
•
El segundo parámetro del openRecordStore es un valor boleano para indicar si
deseamos generar una excepción si no existe el RecordStore. Si el valor es
true, openRecordStore creará un nuevo RecordStore si no puede
encontrar uno existente con el nombre facilitado, abriéndolo, y retornando una
referencia al objeto. Se retorna una referencia al objeto, por lo que mas de un
MIDlet de la misma suite puede acceder al RecordStore.
store = RecordStore.openRecordStore(recordStoreName, true);
Pàg: 95
Estius Universitaris 06/07
Java Móvil J2ME
Uso de RecordStore (II)
•
•
Si únicamente se desea abrir un RecordStore se puede utilizar false
en este parámetro. En este caso, una excepción de tipo
RecordStoreNotFoundException se lanzaría si no existiese el
RecordStore.
Para obtener información sobre el RecordStore, los siguientes
métodos de la clase de RecordStore se pueden utilizar:
StringBuffer result = new StringBuffer();
result.append("Nombre: " + store.getName() + "\n");
result.append("Registros: " + store.getNumRecords() + '\n');
result.append("Tamaño: " + store.getSize() + " bytes\n");
result.append("Bytes disponibles: " + store.getSizeAvailable() + "
bytes\n");
result.append("Versión: " + store.getVersion() + "\n");
•
Para cerrar un RecordStore, llamamos simplemente el método
closeRecordStore del objeto RecordStore:
store.closeRecordStore();
•
Observar que cada llamada del método del openRecordStore necesita
el correspondiente closeRecordStore. Se debe tener en cuenta que
en cada ocasión que se llama a openRecordStore se incrementa un
contador de referencia, por tanto es necesario realizar
closeRecordStore para decrementar este contador. El RecordStore
no se cierra realmente hasta que el contador es cero.
Pàg: 96
Estius Universitaris 06/07
Java Móvil J2ME
Uso de RecordStore (III)
•
Para eliminar totalmente un RecordStore, utilizamos el método
deleteRecordStore:
RecordStore.deleteRecordStore(recordStoreName);
•
Dado que un RecordStore se puede compartir por los MIDlets de una
suite, puede ser posible que otro MIDlet está teniendo acceso al
RecordStore que estamos intentando suprimir. En ese caso, el
método deleteRecordStore lanzará una RecordStoreException.
•
La información se almacena en el RecordStore en forma de registros,
y cada registro es un array de bytes. Los métodos para guardar y
recuperar registros de un RecordStore deben realizarlo como un array
de bytes. Como primera instancia, tener que almacenar la información
como array de bytes puede parecer un mecanismo incómodo. Sin
embargo, con el uso de ByteArrayOutputStream, de
ByteArrayInputStream, DataOutputStream y
DataInputStream, no es tan complicado como podría parecer. Como
ejemplo podemos modificar la aplicación para ordenar películas en
videos o DVDs. El objeto básico podría ser el siguiente:
Pàg: 97
Estius Universitaris 06/07
Java Móvil J2ME
Uso de RecordStore: Ejemplo
package com.f2i.jmd.persistence.rms;
import java.io.*;
public class Movie {
public String title;
public String actors;
public long yearReleased;
public Movie() {
}
public Movie(String title, String actors, long yearReleased) {
this.title = title;
this.actors = actors;
this.yearReleased = yearReleased;
}
public String toString() {
StringBuffer result = new StringBuffer(title);
result.append(", estrenado ");
result.append(yearReleased);
result.append(", estrellas ");
result.append(actors);
return result.toString();
}
}
Pàg: 98
Estius Universitaris 06/07
Java Móvil J2ME
Uso de RecordStore: Serialización (I)
•
•
El perfil MID no define un esquema para serialización. Vamos a definir un
esquema simple de serialización para almacenar objetos en RMS que después
también podría ser utilizado para enviar estos objetos sobre una red.
Para el esquema simple de serialización, definimos un interfaz que tenga dos
métodos:
package com.f2i.jmd.persistence.rms;
import java.io.*;
public abstract interface Serializable {
public void writeObject(DataOutputStream dos) throws IOException;
public void readObject(DataInputStream dis) throws IOException;
}
•
Los objetos que implementen este interfaz deben definir una forma especifica de
guardar el estado del objeto hacia un DataOutputStream, y de recuperar de
(implementar serializable a la definición de la clase) un DataInputStream. Así
pues, necesitamos agregar dos métodos a nuestra clase Movie:
Pàg: 99
Estius Universitaris 06/07
Java Móvil J2ME
Uso de RecordStore: Serialización (II)
public void writeObject(DataOutputStream dos) throws IOException {
dos.writeUTF(title);
dos.writeUTF(actors);
dos.writeLong(yearReleased);
}
public void readObject(DataInputStream dis) throws IOException {
title = dis.readUTF();
actors = dis.readUTF();
yearReleased = dis.readLong();
}
•
•
Utilizaremos un DataOutputStream con un ByteArrayOutputStream por
debajo para escribir el objeto a un registro RecordStore. La ventaja de este
esquema simple para la serialización es que no hay necesidad de cambiar la
definición de la clase Movie tanto para almacenar su contenido como mas
adelante para enviar este contenido sobre un conexión HTTP.
Por tanto en J2SE, la forma de escribir un array de bytes es crear un
DataOutputStream con un ByteArrayOutputStream asociado:
Pàg: 100
Estius Universitaris 06/07
Java Móvil J2ME
Uso de RecordStore: Serialización (III)
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
•
Una vez se haya creado el DataOutputStream, podemos enviarlo al objeto
Movie para que se guarde a si mismo:
movie.writeObject(dos);
•
//Escribe el objeto en el Stream
Dado que DataOutputStream tiene un ByteArrayOutputStream asociado,
es fácil obtener el contenido del stream en forma de un array de bytes:
byte[] ba = bos.toByteArray();
•
Para guardar este array en el RecordStore, utilizamos el método addRecord
en el objeto RecordStore:
store.addRecord(ba, 0, ba.length);
•
Para recuperar un objeto del RecordStore, utilizamos un DataInputStream
con un ByteArrayInputStream asociado. Llamando el método del
readObject en el objeto Movie, se leerá el array de bytes del registro,
rellenándose el objeto con la información de la película guardada es ese registro:
ByteArrayInputStream bis = new
ByteArrayInputStream(store.getRecord(recordId));
DataInputStream dis = new DataInputStream(bis);
Movie movie = new Movie();
movie.readObject(dis);
Pàg: 101
Estius Universitaris 06/07
Java Móvil J2ME
RecordEnumeration
•
Para recuperar un conjunto de registros del RecordStore, RMS proporciona el
interfaz RecordEnumeration. RecordEnumeration proporciona la capacidad
de avanzar y retroceder sobre los registros del RecordStore. Para obtener un
RecordEnumeration, se debe llamar el método enumerateRecords en el
objeto RecordStore:
RecordEnumeration re = store.enumerateRecords(this, this, false);
Pàg: 102
Estius Universitaris 06/07
Java Móvil J2ME
RecordEnumeration: Filtros (I)
•
El primer parámetro proporciona la capacidad de aplicar un filtro en la enumeración. El filtro es
un objeto que implementa el interfaz RecordFilter, esto implica que dispone de un método
matches. El método matches retorna true si el registro se incluirá en la enumeración.
Como ejemplo, si se desearan todas las películas con el título que comenzara con "The" se
desarrollaría un método matches como sigue:
public boolean matches(byte[] candidate)
{
boolean result = true;
Movie movie = null;
try {
ByteArrayInputStream bis = new ByteArrayInputStream(
candidate);
DataInputStream dis = new DataInputStream(bis);
movie = new Movie();
movie.readObject(dis);
}
catch (Exception e) {
System.out.println(e);
e.printStackTrace();
}
result = movie.title.startsWith("The");
return result;
}
Pàg: 103
Estius Universitaris 06/07
Java Móvil J2ME
RecordEnumeration: Filtros (II)
•
•
•
El método matches se llama para cada registro en el RecordStore,
proporcionando un array de bytes al método para que pueda validar la
condición del filtro. En el ejemplo anterior, se lee el objeto Movie del
DataInputStream (con el ByteArrayInputStream asociado) y se
prueba si su título comienza con los caracteres "The". Si es así se
retorna true y el registro se incluye en la enumeración.
Si no se provee ningún objeto para el filtro todos los registros del
RecordStore se incluyen en la enumeración.
El segundo parámetro del método enumerateRecords proporciona la
capacidad de especificar un orden en la enumeración. Si un objeto
implementa la interfaz RecordComparator se especifica como el
segundo parámetro, el método compare del interfaz se llamara para
cada par de registros en el RecordStore. Por ejemplo, si se deseara
clasificar los registros por orden alfabético del títulos de la película, se
debería desarrollar un método compare similar al siguiente:
Pàg: 104
Estius Universitaris 06/07
Java Móvil J2ME
RecordEnumeration: Ordenación (I)
public int compare(byte[] rec1, byte[] rec2)
{
Movie movie1 = null;
Movie movie2 = null;
try {
ByteArrayInputStream bis1 =
new ByteArrayInputStream(rec1);
DataInputStream dis1 = new DataInputStream(bis1);
movie1 = new Movie();
movie1.readObject(dis1);
ByteArrayInputStream bis2 =
new ByteArrayInputStream(rec2);
DataInputStream dis2 = new DataInputStream(bis2);
movie2 = new Movie();
movie2.readObject(dis2);
}
catch (Exception e) {
System.out.println(e);
e.printStackTrace();
}
// ordenar por titulo
int result = movie1.title.compareTo(movie2.title);
Pàg: 105
Estius Universitaris 06/07
Java Móvil J2ME
RecordEnumeration: Ordenación (II)
if (result < 0) {
return RecordComparator.PRECEDES;
}
else if (result > 0) {
return RecordComparator.FOLLOWS;
}
else {
return RecordComparator.EQUIVALENT;
}
}
•
•
Para cada par de registros en el RecordStore (después de que se ha aplicado
el filtro), el correspondiente par de array de bytes se envía al método compare.
Como antes, es posible convertir los byte arrays en objetos Movie. Si el título del
primer objeto de la película precede léxicograficamente al título del segundo, el
método compare retorna RecordComparator.PRECEDES una constante
predefinida. Si el título de la primera película sigue al título de la segunda, el
método compare retorna RecordComparator.FOLLOWS. Si son iguales, el
método retorna RecordComparator.EQUIVALENT.
Si no se provee ningún comparador al método enumerateRecords, los registros
se clasifican en un orden indefinido.
Pàg: 106
Estius Universitaris 06/07
Java Móvil J2ME
RecordStore: Ejemplo
•
•
Se adjunta el código de las clases Movie, Serializable y RmsMIDlet, que sirven de
demostración de lo expuesto anteriormente.
A continuación se exponen una pantallas de ejemplo del el código anterior:
Pàg: 107
Estius Universitaris 06/07
Java Móvil J2ME
RecordListener (I)
•
La API RMS incluye la capacidad de definir un objeto record listener, que seguirá la
actividad del RecordStore. Un objeto que implementa la interfaz RecordListener se
puede agregar como listener a un RecordStore, y los métodos de notificación
provistos por el interfaz serán llamados cuando un registro del RecordStore se añada,
se actualice, o se suprima. Para registrar un listener se debe usar el método
addRecordListener en el objeto RecordStore:
store.addRecordListener(this);
•
A partir de ese momento y hasta que se cierre el RecordStore, el objeto referido por
this será notificado cuando el RecordStore cambie. Tres métodos separados se
definen en el interfaz de RecordListener:
public void recordAdded(RecordStore store, int recordId);
public void recordChanged(RecordStore store, int recordId);
public void recordDeleted(RecordStore store, int recordId);
•
•
Para demostrar cómo trabaja un record listener, podemos ampliar el ejemplo anterior
RmsMIDlet para agregar registros de películas en un thread diferente ejecutado en
background. El objeto de MIDlet se registra como RecordListener, y el
correspondiente método es invocado cada vez el thread agrega un nuevo registro a
Movie.
[NOTA] Palm OS no soporta de forma nativa los threads en background. Sin embargo,
la definición de CLDC impone el soporte a threads, por tanto la KVM implementa este
soporte.
Pàg: 108
Estius Universitaris 06/07
Java Móvil J2ME
RecordListener (II)
•
En primer lugar se creara el thread referenciado:
package com.f2i.jmd.persistence.rms;
import java.io.*;
import javax.microedition.rms.*;
public class RmsThread extends Thread {
int count = 0;
Movie[] movies = null;
RecordStore store = null;
public RmsThread(int count, Movie[] movies,
RecordStore store) {
this.count = count;
this.movies = movies;
this.store = store;
}
Pàg: 109
Estius Universitaris 06/07
Java Móvil J2ME
RecordListener (III)
public void run() {
try {
// añadir el numero especificado de películas en el RecordStore,
// pausa entre cada registro añadido
for (int i=0; i<count; i++) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
Movie movie = movies[i % movies.length];
// escribir el objeto en el stream
movie.writeObject(dos);
byte[] ba = bos.toByteArray();
store.addRecord(ba, 0, ba.length);
// esperamos sobre 1 segundo
sleep(1000);
}
store.closeRecordStore();
}
catch (Exception e) {
e.printStackTrace ();
}
}
}
Pàg: 110
Estius Universitaris 06/07
Java Móvil J2ME
RecordListener (IV)
•
•
Esta clase derivada de thread inserta un nuevo registro y queda en pausa por un
segundo, repitiendo este proceso un determinado numero de veces.
A continuación se debe definir un nuevo Command Inicio que ponga en ejecución
el thread.
Command startCommand = new Command("Inicio", Command.SCREEN, 1);
...
mainForm.addCommand(startCommand);
...
if (c == startCommand) {
store = RecordStore.openRecordStore(recordStoreName, true);
store.addRecordListener(this);
RmsThread thread = new RmsThread(5, movies, store);
thread.start();
}
•
Por último, es necesario implementar los métodos del RecordListener. En este
ejemplo, recuperaremos el registro de la película y mostraremos el título del
registros agregado o actualizado. Observar que al intentar recuperar el registro
afectado en el método recordDeleted fallará, y una excepción del tipo
InvalidRecordIDException se lanzará:
Pàg: 111
Estius Universitaris 06/07
Java Móvil J2ME
RecordListener (V)
public void recordAdded(RecordStore store, int recordId) {
resultItem.setLabel ("Status:");
resultItem.setText("Película añadida: " +
getMovieFromRecord(store, recordId).title);
}
public void recordChanged(RecordStore store, int recordId) {
resultItem.setLabel ("Status:");
resultItem.setText("Película actualizada: " +
getMovieFromRecord(store, recordId).title);
}
public void recordDeleted(RecordStore store, int recordId) {
resultItem.setLabel ("Status:");
resultItem.setText("Película eliminada: " + recordId);
}
Pàg: 112
Estius Universitaris 06/07
Java Móvil J2ME
RecordListener (VI)
•
Ahora es necesario implementar el correspondiente getMovieFromRecord
como sigue:
Movie getMovieFromRecord(RecordStore store, int recordId) {
Movie movie = new Movie();
try {
ByteArrayInputStream bis =
new ByteArrayInputStream(store.getRecord(recordId));
DataInputStream dis = new DataInputStream(bis);
movie.readObject(dis);
}
catch (Exception e) {
System.out.println(e);
e.printStackTrace();
}
return movie;
}
Pàg: 113
Estius Universitaris 06/07
Java Móvil J2ME
RecordStores en Palm OS
•
La implementación de los RecordStores es dependiente del dispositivo, y
puede variar entre plataformas. Esta implementación no esta definida en las
especificaciones de MIDP ni en las de CLDC. La implementación de Palm OS
utiliza una base de datos del dispositivo para guardar los RecordStores.
Se puede acceder a esta DB de forma idéntica a otras DB de Palm, por ejemplo
para sincronizar los datos, simplemente seria necesario crear un driver de acceso,
pero esto no se recomienda por la siguientes razones:
•
–
–
•
Los estándares se deben utilizar siempre que sea posible por las siguientes
razones:
–
–
–
–
•
El formato de la base de datos no se especifica ni se soporta, y puede cambiar.
Hay maneras soportadas de transferir información a y desde un dispositivo.
Los estándares simplifican la migración de aplicaciones a otras plataformas soportadas.
Los estándares facilitan la lectura del código generado por nosotros.
Una aplicación conforme a un estándar es mas fácil que funcione en modelos
posteriores.
Una aplicación que siga los estándares tendrá más posibilidades de utilizar las nuevas
características que dispongan las próximas versiones de la plataforma
Si aún así se desea acceder directamente a las DB de Palm OS en este link se
podrá encontrar más información:
http://archives.java.sun.com/cgi-bin/wa?A2=ind0108&L=kvminterest&D=0&H=0&O=T&T=1&P=49045%20.
Pàg: 114
Estius Universitaris 06/07
Java Móvil J2ME
Otras Bases de Datos para Java
•
Si una aplicación necesitara mas de lo aportado por RMS de MIDP se podrían
adquirir productos de terceros como los que se exponen a continuación. Ambos
productos descritos proveen una aplicación MIDP de bases de datos compatible
JDBC.
•
•
PointBase
PointBase Micro es una implementación de un subconjunto de la API JDBC que
se encuentra en J2SE, preparado pata para trabajar en un entorno MIDP. El
lenguaje utilizado es SQL estándar. El archivo JAR ocupa menos de 45 KB. La
base de datos puede residir integramente en el dispositivo, o sincronizarse con el
producto PointBase UniSync.
Para más información sobre PointBase Micro: http://www.pointbase.com/
•
•
•
•
ReqwirelessDB
ReqwirelessDB proporciona el acceso a cualquier base de datos JDBC estándar
desde una aplicación MIDP. Se proporciona la API JDBC para uso de la
aplicaciones MIDP, y un servlet para el servidor donde reside la DB a la que se
desea acceder.
Para más información sobre Reqwireless: http://www.reqwireless.com/
Pàg: 115
Estius Universitaris 06/07
Java Móvil J2ME
Comunicaciones (I)
•
•
•
•
La principal ventaja de los dispositivos móviles es su posibilidad de conectividad,
todo y que esta era en un inicio escasa, se están realizando grandes progresos a
medida que los dispositivos tienen un grado de integración mayor y los
estándares de conectividad van evolucionando.
CLDC define un conjunto de APIs de conectividad llamado Generic Connection
Framework (GCF). Este conjunto de APIs es suficiente para establecer redes de
bajo nivel entre dispositivos móviles y con sistemas de mayor potencia.
MIDP utiliza GCF para establecer un conjunto de clases que soportan streams y
esto se amplia hasta soportar conexiones HTTP 1.1 en el caso de MIDP 1.0 y
HTTPS en el caso de MIDP 2.0.
Sin poder compararse con el framework ofrecido por J2SE en java.net,
principalmente debido a los problemas inherentes de las restricciones de
memoria, y las necesidades del dispositivo. Los diseñadores de CLDC
generalizaron las características de establecimiento de una red de J2SE,
proporcionando un marco uniforme para soportar los nuevos dispositivos y los
nuevos protocolos que estos pueden requerir.
Pàg: 116
Estius Universitaris 06/07
Java Móvil J2ME
Comunicaciones (II)
Connector
Connection
DatagramConnection
InputConnection OutputConnection StreamConnectionNotifier
StreamConnection
ContentConnection
CommConnection
HttpConnection
HttpsConnection
SocketConnection
SecureConnection
javax.microedition.io.*
javax.microedition.io.* (Interface) MIDP 1.0 javax.microedition.io.* (Interface) MIDP 2.0
Pàg: 117
Estius Universitaris 06/07
Java Móvil J2ME
Comunicaciones (III)
•
•
•
Para el establecimiento básico de una red, J2SE incluye clases tales como
socket, HttpURLConnection, DatagramSocket, MulticastSocket,
ServerSocket, InetAddress, URL, y URLConnection en el paquete
java.net. Generalmente, cada protocolo es manejado por una clase diferente.
Por ejemplo, los datagramas son implementados por la clase DatagramSocket,
y las conexiones HTTP son manejadas por la clase HttpURLConnection. Sin
embargo, en el CLDC de J2ME, las clases para el establecimiento de una red son
absolutamente diferentes. Ninguna de las clases básicas referentes a
conectividad en J2SE existe en el CLDC de J2ME. De hecho, el paquete de
java.net no existe. Las clases del GCF están situadas en un paquete
especifico del CLDC, llamado javax.microedition.io. En el GCF, la clase
Connector maneja todos los protocolos de establecimiento de una red
soportados en el dispositivo. El resultado es que el código de una aplicación es
básicamente el mismo independientemente del protocolo que utilice.
Se debe tener en cuenta que los protocolos soportados no están especificados en
el nivel de configuración. La especificación de los protocolos pertenece a los
perfiles. Esto es consistente con la premisa de que los perfiles especifican las
características que aprovechan de las capacidades del dispositivo.
La clase Connector tiene varios métodos estáticos, que se utilizan para crear
conexiones. Estos métodos se resumen a continuación:
Pàg: 118
Estius Universitaris 06/07
Java Móvil J2ME
Comunicaciones (IV)
•
La forma genérica de abrir una conexión es utilizar el método estático de
Connection tal como sigue
Connector.open("<protocolo>:[<destino>][;<parámetros>]");
•
Pero también se pueden utilizar las siguientes variantes:
static Connection open(String name)
Crea y abre una conexión, usando una
URL.
static Connection open(String name, int
mode)
Crea y abre una conexión, usando una
URL y un modo (leer, escribir, o
leer/escribir).
static Connection open(String name, int
mode, boolean timeouts)
Crea y abre una conexión, usando una
URL, un modo, y un flag para lanzar
excepciones por timeout.
static DataInputStream
openDataInputStream(String name)
Crea y abre un input stream de datos
para la conexión.
static DataOutputStream
openDataOutputStream(String name)
Crea y abre un output stream de datos
para la conexión.
static InputStream openInputStream(String
name)
Crea y abre un input stream para la
conexión.
static OutputStream
openOutputStream(String name)
Crea y abre un output stream para la
conexión.
Pàg: 119
Estius Universitaris 06/07
Java Móvil J2ME
Comunicaciones (V)
•
El formato de los argumento del método open debe ser conforme con la sintaxis
estándar para URIs
–
•
•
•
•
El estándar para URIs se define en RFC2396, que se puede encontrar en
http://www.ieft.org/rfc/rfc2396.txt
El argumento < protocolo > corresponde al protocolo (http/file/...) que se utilizará
para la conexión.
El argumento opcional < destino > se interpreta en función del protocolo. Para
conexiones orientadas a red, este parámetro se refiere a una dirección, en
formato nombre o IP. Para otros protocolos este argumento se interpreta en
función del protocolo, si en un futuro se soportan archivos, este argumento
contendría el path y el nombre del archivo.
Los argumentos opcionales < parámetros > contienen duplas nombre-valor
separadas por punto y coma. Por ejemplo, ";nombre1=valor1;nombre2=valor2".
Aunque len la especificación de MIDP se define únicamente el soporte HTTP,
HTTP y HTTPS se soportan en la especificación MIDP 2.0 de J2ME, así como
otros modos (socket, serversocket, comm, datagram) pero esto es de forma
experimental. Para dispositivos Palm con la JVM de SUN únicamente se dispone
del obligado HTTP, esto tiene la ventaja que cualquier código desarrollado para
Palm será totalmente portable, dado que todos los dispositivos que implementen
MIDP disponen de este protocolo.
Pàg: 120
Estius Universitaris 06/07
Java Móvil J2ME
HttpConnection (I)
•
Para entender el funcionamiento de las APIs de red de MIDP, podemos observar el siguiente
ejemplo simple que descarga una página desde una conexión HTTP.
private String getPage(String url) throws IOException {
HttpConnection c = null;
String result = null;
try {
c = (HttpConnection)Connector.open(url);
DataInputStream dis = c.openDataInputStream();
byte[] buffer = new byte[(int)c.getLength()];
dis.readFully(buffer);
result = new String(buffer);
}
catch (Exception e) {
Alert alert = new Alert("Error");
alert.setString(e.toString());
alert.setTimeout(Alert.FOREVER);
display.setCurrent(alert, mainForm);
System.out.println(e.getMessage());
}
finally {
if(c != null)
c.close();
}
return result;
}
Pàg: 121
Estius Universitaris 06/07
Java Móvil J2ME
HttpConnection (II)
•
•
En este ejemplo, utilizamos Connector para abrir una HttpConnection, que
se utiliza a continuación para abrir un stream de entrada de datos. Para descargar
los primeros bytes de la página del URL especificado, se utiliza el método
readFully() para leer todo el array de bytes. Notar que se utiliza el método
getLength para crear el array de bytes del tamaño necesario.
Lo que ocurre en las interioridades de este código es: En primer lugar la conexión
HTTP no se realiza cuando se ejecuta el método open de Connector. En este
punto se considera que se esta en estado de establecimiento de conexión, la
conexión HTTP todavía no se ha realizado con el servidor. Se realiza la conexión
y los datos se envían y se reciben cuando uno de los métodos siguientes se
llama, causando en HttpConnection una transición del estado "establecimiento" al
estado "conectado":
•getResponseMessage
•openInputStream
•getHeaderFieldInt
•openOutputStream
•getHeaderFieldDate
•openDataInputStream
•openDataOutputStream •getExpiration
•getDate
•getLength
•getLastModified
•getType
•getHeaderField
•getEncoding
•getHeaderFieldKey
•getHeaderField
•getResponseCode
Pàg: 122
Estius Universitaris 06/07
Java Móvil J2ME
HttpConnection (III)
•
Para probar este ejemplo, en el método commandAction de HttpNetworking.java podemos
utilizar el código siguiente para establecer la conexión:
public void commandAction(Command c, Displayable d) {
try {
if (c == getCommand) {
resultItem.setLabel("Requesting page...");
resultItem.setText("");
String result = getPage(
"http://localhost/fichero.html");
resultItem.setLabel("Received...");
resultItem.setText(result);
}
else if (c == exitCommand) {
destroyApp(false);
notifyDestroyed();
}
}
catch (Exception e) {
e.printStackTrace();
resultItem.setLabel("Error:");
resultItem.setText(e.toString());
}
}
Pàg: 123
Estius Universitaris 06/07
Java Móvil J2ME
HttpConnection (IV)
•
•
Se puede utilizar NetCat (nc -l -p 80) en el servidor destino para capturar la
petición y enviar una respuesta compatible HTTP, p.ex:
Petición:
"
GET /fichero.html HTTP/1.1
Host: localhost:80
Content-Length: 0
"
•
Respuesta:
"
HTTP/1.1 200 OK
Content-Length: 54
Content-Type: text/html
Java en dispositivos móviles
Año 2004
F2i Sabadell
"
Pàg: 124
Estius Universitaris 06/07
Java Móvil J2ME
Acceso a Internet desde un dispositivo
Palm
•
•
–
–
–
•
–
–
–
•
Vamos a realizar un inciso en el curso sobre Java, para ver las posibilidades de conexión de
los dispositivos móviles, y concretamente de Palm para obtener un acceso a Internet.
Opciones:
Cradle con conexión serie o Bluetooth
Conexión por Inflarojos o USB
Disponibilidad de conexiones WireLess
Para la primera opción la conexión entre el dispositivo el PC y Internet pasa por establecer un
túnel PPP, esto debe realizar mediante software, en el caso de bluetooth utilizando el
dispositivo serie virtual, todo y que es posible establecer también una pasarela mediante una
red bluetooth y "ICS" las posibilidades son:
Instalar el software http://www.mochasoft.dk/home.html
Establecer un servicio RAS en Windows 2000, XP, NT que permita al dispositivo acceder
a un servicio de pasarela: http://bwinton.latte.ca/Palm/ppp.html
Para establecer una red bluetooth y compartir la conexión a Internet mediante ICS:
http://www.whizoo.com/bt_setup/
Para establecer una conexión por Infrarrojos o USB se debe realizar lo mismo que en los
puntos anteriores, es decir, es necesario un servicio PPP, que puede ser RAS o el software
de mochasoft pero con un driver de virtualización a puerto serie del puerto de infrarrojos
(http://www.ircomm2k.de/) o del USB
Pàg: 125
Estius Universitaris 06/07
Java Móvil J2ME
Acceso a Internet desde un dispositivo
•
•
El tercer caso es mucho mas simple, dado que los dispositivos Palm
dotados de una interfase wireless incorporan un stack Tcp/Ip y esto
facilita enormemente la conectividad, simplemente debemos configurar
nuestro dispositivo de acuerdo con la topología de nuestra red.
Para dispositivos móviles es mucho más sencillo, y por supuesto mas
caro, consiste en establecer una conexión a través del ISP
correspondiente, abonando para ello las cuotas de conexión. Los
dispositivos Palm también ofrecen la posibilidad de establecer una
conexión por infrarrojos, bluetooth, o un cable especifico a un teléfono
móvil para crear una conexión PPP con el correspondiente ISP.
Pàg: 126
Descargar