Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Vicen Soler i Juan Manuel Fernndez, professors de lEscola Universitria dInformtica de Sabadell.
Programa (I)
Objetivos: Conocer las diferentes implementaciones de Java para dispositivos mviles. Introduccin a la arquitectura J2ME, Presentacin de la arquitectura bsica de Java i como esta se adapta en funcin del dispositivo sobre el que se coloca, se presentan los estndares que hay detrs de esta arquitectura y se catalogan para uso futuro del alumno. Dispositivos. (1'5h)
PDA, PocketPCs, Mobile Devices, PIM
Objetivos: Catalogar los dispositivos mviles, se pretende que el alumno sea crtico a la hora de desarrollar una aplicacin en J2ME para que esta cubra la mayor parte de dispositivos.
Pg: 2
Programa (II)
Objetivos: Evaluar diferentes entornos de desarrollo, se referencia un conjunto amplio de ellos, y se aporta una visin 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 mviles (1h)
CPU Pantalla Memoria
Objetivos: Analizar las caractersticas del entorno donde se ejecuta la aplicacin con el objetivo de evidenciar las sustanciales diferencias de desarrollo que se deben considerar para los dispositivos mviles. Concienciar al alumno de las concesiones necesarias en las aplicaciones J2ME.
Pg: 3
Programa (III)
Objetivos: Mostar la estructura bsica de las aplicaciones para dispositivos mviles, crear una aplicacin bsica y analizarla, ver los problemas de desarrollo, compilacin y deployment de este tipo de aplicaciones. La interfaz de Usuario (6h)
En MIDP En PersonalJava
Objetivos: Presentar los controles disponibles en J2ME y PersonalJava, familiarizando al alumno con las estructuras necesarias para construir aplicaciones usables.
Pg: 4
Programa (IV)
Objetivos: Presentar las diferentes APIs para la gestin de la informacin en los dispositivos mviles en general y en algunos en particular, y como estas deben ser tratadas desde las aplicaciones para un correcto ciclo de vida. Se aborda tambin el almacenamiento externo de esta informacin. Comunicaciones (3h)
Framework de comunicaciones en CLCD Comunicaciones en PocketPC
Objetivos: Introduccin a la intercomunicacin de dispositivos mviles, las restricciones que por sus caractersticas se encuentran es este tipo de dispositivos. WebServices Futuro Objetivos: Integracin de las aplicaciones y los dispositivos en la empresa, y los mecanismos que se encuentran disponibles para poder realizarla. Objetivos: Anlisis del futuro de las aplicaciones Java en los dispositivos mviles, mesa redonda con los alumnos para ver su opinin con respecto a este tipo de dispositivos, y anlisis de tendencias del mercado.
Pg: 5
mbito de Java
Pg: 7
Configuraciones de J2ME
Una configuracin es una combinacin de una mquina virtual Java y de una coleccin de los interfaces de programacin de aplicaciones (APIs) para una determinada clase del dispositivo. Una configuracin proporciona la base para uno o ms perfiles en un dispositivo. Un perfil es un sistema de APIs que dota de ms funcionalidad y se adapta especficamente a las especificaciones de un determinado dispositivo. Una configuracin define un sistema bsico de APIs que se debe estar implementado en todos los dispositivos que soporten la configuracin (dispositivos de baja potencia, con poca cantidad de memoria, etc.). El perfil que se sustenta sobre la configuracin, debe implementar los APIs de la configuracin, y los especficos del perfil (profile), como pueden ser los especficos de un PDA, un telfono mvil, etc. Es importante observar que la configuracin especifica las capacidades de la mquina virtual asociada, pero no impone una maquina virtual particular. Los vendedores de perfiles y configuraciones tienen libertad de proporcionar su propia mquina virtual, siempre que se adapte a la especificacin (Ex. J9VM IBM, KVM SUN).
Pg: 8
Pg: 9
Estas caractersticas definen una variedad amplia de dispositivos, incluyendo pagers, telfonos mviles, y PDAs. El CLDC define una base comn para estos dispositivos en las reas siguientes:
Paquetes de Java base Capacidades de lenguaje Capacidades de la JVM Conectividad e I/O Seguridad Internacionalizacin
No cubre otras reas que puedan ser especificas del dispositivo, por ejemplo el interfaz de usuario, el ciclo de vida de aplicacin, gestin de eventos. Estas reas son cubiertas por los perfiles. La mquina 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 dispondrn de las siguientes caractersticas:
Pg: 10
El CLDC hereda la mayora 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.
Pg: 11
Pg: 12
Cualquier implementacin de CDC deben soportar la entrada-salida del archivo (I/O) (por lo menos en modo read-only) y datagramas.
Pg: 13
Profiles CLDC
Actualmente slo existe un perfil (profile) para la configuracin 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 ms limitados en recursos, como pueden telfonos mviles, y pagers. La ventaja de la eleccin de este perfil, es que aporta la mnima expresin para todos los dispositivos, de este modo una aplicacin que corra sobre este perfil, podr ejecutarse en todos los dispositivos que lo implementen.
Pg: 14
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 gestin del ciclo de vida de la aplicacin. Estos paquetes se denominan javax.microedition.lcdui, javax.microedition.rms, y javax.microedition.midlet, respectivamente.
Pg: 15
El desarrollador puede tambin hacer que el MIDlet entre en estos estados, usando los mtodos notifyPaused, notifyDestroyed, y resumeRequest. MIDP 2.0 se construye sobre MIDP 1.0, es compatible hacia atrs, esto garantiza que las aplicaciones desarrolladas para MIDP 1.0 tambin funcionen en MIDP 2.0. Definido en JSR118, la especificacin final fue lanzada en noviembre de 2002. Asume funcionalidad de CLDC 1.0, aunque tambin 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 generacin de tonos y reproduccin de sonido. javax.microedition.pki. Certificados para las conexiones de red seguras.
Pg: 16
Pg: 17
El Personal Basis Profile fue desarrollado por el JCP como JSR129 http://www.jcp.org/jsr/detail/129.jsp.
Pg: 18
Pg: 19
En cada caso, una propiedad del sistema deber ser puesta a true si la implementacin 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
Pg: 20
javax.microedition.*
Pg: 21
Dispositivos
Por que utilizando Java nos hemos de preocupar de la plataforma? Tal i como se ha discutido en la presentacin anterior J2ME no es totalmente portable, hemos de considerar aspectos como la JVM donde se ejecutara nuestra aplicacin (PersonalJava y MIDP), as como los paquetes opcionales de los que disponga el dispositivo destino. Por norma general se recomienda estructurar la aplicacin en el cdigo funcional comn que se pueda ejecutar independiente de la plataforma, y separarlo de la presentacin de usuario, la persistencia y conectividad, esto puede ser una tarea compleja. Dado que el punto anterior es de difcil cumplimiento, normalmente se escoge la plataforma destino antes de disear la aplicacin, dado que muchas aplicaciones para dispositivos mviles son orientadas a cliente servidor, esto afectara significativamente a diseo y realizacin de la aplicacin. A continuacin vamos a enumerar algunos de los dispositivos mviles ms comunes y sus caractersticas ms significativas. Al seleccionar una plataforma PDA para el desarrollo de Java, hay un gran nmero de factores a considerar. En la consideracin de estos factores, es importante recordar los dos subconjuntos principales de dispositivos, dependiendo del SO: Palm OS y PocketPCs. Estos tienen filosofas totalmente diferentes, a continuacin se enumeran algunas de ellas. Es importante considerar siempre que aunque Java funcionar en ambos dispositivos, la riqueza de la plataforma vara, segn las capacidades del dispositivo, y, por consiguiente, la configuracin. Esto es principalmente debido a las diferencias en filosofa de diseo de las configuraciones de J2ME segn el tipo de dispositivo.
Pg: 22
Palm OS vs PocketPCs
Dispositivos Palm OS
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. Funcionalidad simple. PALM se caracteriza por realizar tareas simples de forma elegante.
PocketPCs
Herencia del PC. El PocketPCs es bsicamente un PC en miniatura.
Rica funcionalidad. Un PocketPC es bsicamente 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. Alta energa de proceso y una vida ms corta de las bateras. Los PocketPCs disponen actualmente de CPUs de 200 MHz a 400 MHz, y sobre 32Mb a 64Mb de RAM.
Energa de proceso baja y larga duracin de la batera. Los dispositivos PALM OS funcionan a con CPUs de 20 MHz o 33 MHz, y tpicamente 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 asemejndose a los PocketPC.
Pg: 23
PocketPC Casio E-200 HP iPaq 3970 Compaq iPaq 3870 Toshiba e740 Media
Mayo Palm OS r $650 $780 $680 $600 $678 Handspring Treo 270 Palm m515 Palm i705 Sony CLIE PEGNR70V Media
En esta seleccin de dispositivos high-end PocketPC y Palm, podemos observar que los PocketPC son entre un 25% y un 50% ms caros que los dispositivos high-end Palm OS.
Pg: 24
Estndar Corporativo
Riqueza de funcionalidad
Pg: 26
Comparativa PDAs
Clasificacin Java vs PDA
PersonalJava est disponible en los dispositivos de PocketPC, mientras que MIDP est disponible en los dispositivos Palm OS. A continuacin se enumeran las implementaciones J2ME actualmente disponibles. PersonalJava se incluye en la tabla aunque no es estrictamente una implementacin J2ME, por el contrario est disponible para casi cada dispositivo PocketPC.
Pg: 27
Java PersonalJava 1.2 PersonalJava 1.2 PersonalJava 1.2 PersonalJava 1.2 PersonalJava 1.2 PersonalJava 1.2 PersonalJava 1.2 CDC/Foundation 1.0 CLDC/MIDP 1.0 CLDC/MIDP 1.0 CLDC/MIDP 1.0 CLDC/MIDP 1.0 PersonalJava 1.1.3
Product Insignia Jeode PDA Edition Insignia Jeode PDA Edition Insignia Jeode PDA Edition Insignia Jeode PDA Edition Insignia Jeode PDA Edition Insignia Jeode PDA Edition Insignia Jeode PDA Edition IBM WebSphere Micro Environment IBM WebSphere Micro Environment IBM WebSphere Micro Environment Esmertec Micro Edition CLDC MIDP for Palm OS 1.0 Sun PersonalJava Runtime Environment for Windows CE 2.11 Version 1.0
Fuente: http://www.palmos.com/dev/tech/hardware/compare.html. [a]: Dependiendo de la versin de Palm OS instalada [b]: Esta versin es la de referencia, en algunos dispositivos puede haberse upgradeado.
Pg: 29
Pg: 30
Pg: 32
Pg: 33
Pg: 34
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 tambin incluye la capacidad de capturar los streams System.out y System.err. Para instalar el entorno MIDP para Palm tan slo es necesario sincronizar el archivo MIDP.prc en el dispositivo.
Pg: 35
En este punto disponemos del cdigo fuente compilado, pero para poder ejecutar este cdigo en una KVM se debe realizar un proceso de preverificacin, este proceso se realiza de la siguiente forma:
Cuando se trabaja con J2SE la mquina virtual Java (JVM) lleva a cabo un proceso de verificacin en tiempo de ejecucin. Esto ocupa ciertos recursos que en dispositivos inalmbricos 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 verificacin de la KVM off-line, el resto ser llevado a cabo como una verificacin 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
Pg: 36
Pg: 37
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 tamao del archivo jar.
Pg: 38
Pg: 39
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 ningn 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.
Pg: 40
Pg: 41
Pg: 42
Pg: 44
Pg: 45
freeram
permanent
Pg: 46
Runtime runtime = Runtime.getRuntime(); runtime.gc(); System.out.println("Total: " + runtime.totalMemory() + " Free: " + runtime.freeMemory());
Destacar que se utiliza el mtodo gc de runtime antes de llamar el mtodo freeMemory. El propsito 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 dinmico interno de Java para stack y nuevos objetos, mientras que freeMemory retorna una aproximacin de la cantidad de memoria disponible para la futura asignacin de objetos. El MIDlet MemoryMIDlet, StaticMemoryMIDlet, y MultipleClassMIDlet cada uno realiza una alocatacin 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);
Pg: 47
Finalmente, MultipleClassMIDlet crea una instancia de LargeClass , una clase con un atributo que referencia a un array de 1000 bytes:
LargeClass largeClass = new LargeClass();
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 nmero de bytes devueltos por freeMemory() se ha registrado antes y despus la asignacin dinmica.
Pg: 48
De la tabla, se observa que un objeto array esttico toma el espacio del mismo heap de Java que se utiliza para asignar objetos dinmicos. Es decir, los objetos estticamente y dinmicamente asignados utilizan el mismo espacio del heap. Segn lo observado previamente, el espacio de heap se restringe a 64 KB en Palm OS 3.X y 4.X.
Pg: 49
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 ingls AMS, El AMS realiza dos grandes funciones:
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 ejecucin.
Como vemos en el diagrama, un MIDlet puede cambiar de estado mediante una llamada a los mtodos MIDlet.startApp(), MIDlet.pauseApp() o MIDlet.destroyApp(). El gestor de aplicaciones cambia el estado de los MIDlets haciendo una llamada a cualquiera de los mtodos anteriores. Un MIDlet tambin puede cambiar de estado por s mismo.
Pg: 51
Pg: 52
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 cdigo que queremos que el MIDlet ejecute cundo se active. */ } public pauseApp(){ /* Aqu incluiremos el cdigo que queremos que el MIDlet ejecute cundo entre en el estado de pausa (Opcional) */ } public destroyApp(){ /* Aqu incluiremos el cdigo que queremos que el MIDlet ejecute cundo sea destruido. Normalmente aqu se liberaran los recursos ocupados por el MIDlet como memoria, etc. (Opcional) */ } }
Pg: 53
Clase MIDlet
public abstract class MIDlet Un MIDlet es una aplicacin realizada usando el perfil MIDP como ya sabemos. La aplicacin 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 mtodos apropiados. Los mtodos de los que dispone esta clase son los siguientes: protected MIDlet() Constructor de clase sin argumentos. Si la llamada a este constructor falla, se lanzara la excepcin SecurityException.
Pg: 54
Pg: 56
Clase MIDletChangeStateException public class MIDletstateChangeException extends Exception Esta excepcin es lanzada cuando ocurre un fallo en el cambio de estado de un MIDlet.
Pg: 57
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(); } }
Pg: 58
Display Canvas
Diplayable Screen
ItemStateListener
List TextBox
Choice
javax.microedition.lcdui.*
Pg: 59
javax.microedition.lcdui.* (Interface)
Pg: 60
Esto indica a la aplicacin que el botn de salida debe aparecer al final de los command's del men dado que le hemos asignado una prioridad baja. Una vez que una aplicacin haya creado sus objetos Command, un objeto que implementa la interfaz CommandListener debe ser asignado para tratar los eventos. Esto se hace con el mtodo setCommandListener, invocado en un objeto derivado de Displayable. El interfaz de CommandListener especifica un mtodo, 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 imgenes, lneas, y crculos. 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 ttulo.
Pg: 61
Debido a que una aplicacin 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 mtodo esttico getDisplay en la clase Display, pasndole una referencia al objeto MIDlet. As pues, para nuestro ejemplo, necesitaremos una referencia al objeto Display:
Display display = null;
Pg: 62
En el mtodo startApp, obtenemos una referencia al Display del MIDlet, y fijamos el Display actual a nuestro Form recin creado:
display = Display.getDisplay(this); display.setCurrent(mainForm);
Dado que hemos fijado el MIDlet para ser el listener del comando exit, necesitamos implementar el mtodo 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(); } }
Pg: 63
Pg: 64
Esto sita la accin en el men Go, si se hubiera definido como Command.SCREEN se hubiera situado en el men Actions y tendra asociado un botn el la pantalla:
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 implementacin 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, provocara que se situara en el submen Options:
protected Command exitCommand = new Command("Salir",Command.HELP, 10);
Pg: 66
Pg: 67
Pg: 68
Para mostrar el Alert, e ir de nuevo al Form principal cuando pase el tiempo, podemos utilizar el mtodo setCurrent que toma un Alert y un Displayable como parmetros.
display.setCurrent(alert, mainForm);
Los nmeros exhibidos en el crculo en la esquina izquierda inferior de la alerta indican el nmero de segundos restantes hasta el cierre de la alerta. Hay dos formas que la alerta no ser reconocida automticamente. 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.
Pg: 69
Pg: 70
Una alerta es una buena herramienta para mostrar una pequea cantidad de informacin, las usaremos en los ejemplos siguientes para mejorar los conocimientos de los Form's. Para crear interfaces de usuario ms sofisticadas, tenemos la posibilidad de aadir objetos derivados de Item en los formularios. Destacar que los derivados de Item slo pueden aparecer en formularios.
Pg: 71
Para este ejemplo, se ha escogido un constructor que permite que las etiquetas sean especificadas como un array de strings. Se escoge no acompaar las opciones de imgenes, indicando el ultimo parmetro del constructor como null. Observar que tambin 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 seleccin cambie. No hay notificacin para el tipo EXCLUSIVE. Se puede aadir un ChoiceGroup a un Form:
Form choiceForm = new Form("Seleccin de pelculas"); choiceForm.append(singleChoice);
Pg: 72
Para obtener las selecciones, un array de flags boleanos es utilizado por el mtodo getSelectedFlags:
boolean[] selections = new boolean[multipleChoice.size()]; multipleChoice.getSelectedFlags(selections);
El flag boleano correspondiente a la seleccin es puesto true si el usuario selecciono la opcin, un cdigo que hara 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 seleccin simple, cuando el usuario presione el botn OK, se mostrara una alerta con las selecciones del usuario de ambos grupos.
Pg: 73
public ChoiceGroupMIDlet() { super(); mainForm.setTitle("ChoiceGroupMIDlet"); mainForm.addCommand(choiceCommand); } public void commandAction(Command c, Displayable d) { if (c == choiceCommand) { Form choiceForm = new Form("Seleccin de pelculas"); ChoiceGroup singleChoice = new ChoiceGroup("Media", ChoiceGroup.EXCLUSIVE, MEDIA, null); ChoiceGroup multipleChoice = new ChoiceGroup("Pelculas", ChoiceGroup.MULTIPLE, MOVIES, null); choiceForm.append(singleChoice); choiceForm.append(multipleChoice);
Pg: 74
Pg: 76
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 debern realizar manualmente:
private Date manana() { Date hoy = new Date(); Date manana = new Date(hoy.getTime()+(24*60*60*1000)); return manana; }
Pg: 77
Pg: 78
Pg: 79
El primer parmetro 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 mtodo getValue del objeto, la forma de dibujo puede variar en funcin 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);
Pg: 80
Pg: 81
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 direccin"); StringItem addressLine1 = new StringItem("Direccin 1", "Sabadell, 67");
Pg: 82
Pg: 83
El ltimo parmetro 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 mtodo getString. El cdigo siguiente muestra cmo un TextField se podra utilizar en una aplicacin:
package com.f2i.jmd.ui; import javax.microedition.lcdui.*; public class TextFieldMIDlet extends BaseUIMIDlet { private Command textFieldCommand = new Command("TextField", Command.SCREEN, 1);
Pg: 84
Hasta ahora hemos utilizado dos subclases de Screen, que son Alert y Form, a continuacin vamos a estudiar los otros dos tipos: List y TextBox
Pg: 86
Como en ChoiceGroup, la seleccin se recupera de la lista usando los mtodos 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 mltiples para un ChoiceGroup.
List list = new List("Pelculas", 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";
Pg: 87
Pg: 88
Pg: 89
El Ticker se muestra en cualquier objeto derivado de Screen, usando el mtodo del setTicker. El MIDlet siguiente es igual que el ChoiceGroupMIDlet, excepto que se ha aadido un Ticker en cada pantalla de la aplicacin.
Pg: 91
Adems de un nombre, cada Record Store tambin posee otros dos atributos:
Nmero de versin: Es un valor entero que se actualiza conforme vayamos insertando, modificando o borrando registros en el Record Store. Podemos consultar este valor invocando al mtodo RecordStore.getVersion(). Marca temporal: Es un entero de tipo long que representa el nmero de milisegundos desde el 1 de enero de 1970 hasta el momento de realizar la ltima modificacin en el Record Store. Este valor lo podemos obtener invocando al mtodo RecordStore.getLastModified().
Pg: 92
Pg: 93
Manipulacin de registros
Pg: 94
Para crear y para abrir un RecordStore nuevo, utilizamos el mtodo esttico openRecordStore sobre un objeto RecordStore:
store = RecordStore.openRecordStore(recordStoreName, true);
El segundo parmetro del openRecordStore es un valor boleano para indicar si deseamos generar una excepcin 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, abrindolo, 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.
Pg: 95
Para cerrar un RecordStore, llamamos simplemente el mtodo closeRecordStore del objeto RecordStore:
store.closeRecordStore();
Observar que cada llamada del mtodo del openRecordStore necesita el correspondiente closeRecordStore. Se debe tener en cuenta que en cada ocasin 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.
Pg: 96
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 mtodo deleteRecordStore lanzar una RecordStoreException. La informacin se almacena en el RecordStore en forma de registros, y cada registro es un array de bytes. Los mtodos para guardar y recuperar registros de un RecordStore deben realizarlo como un array de bytes. Como primera instancia, tener que almacenar la informacin como array de bytes puede parecer un mecanismo incmodo. Sin embargo, con el uso de ByteArrayOutputStream, de ByteArrayInputStream, DataOutputStream y DataInputStream, no es tan complicado como podra parecer. Como ejemplo podemos modificar la aplicacin para ordenar pelculas en videos o DVDs. El objeto bsico podra ser el siguiente:
Pg: 97
Pg: 98
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 definicin de la clase) un DataInputStream. As pues, necesitamos agregar dos mtodos a nuestra clase Movie:
Pg: 99
Utilizaremos un DataOutputStream con un ByteArrayOutputStream por debajo para escribir el objeto a un registro RecordStore. La ventaja de este esquema simple para la serializacin es que no hay necesidad de cambiar la definicin de la clase Movie tanto para almacenar su contenido como mas adelante para enviar este contenido sobre un conexin HTTP. Por tanto en J2SE, la forma de escribir un array de bytes es crear un DataOutputStream con un ByteArrayOutputStream asociado:
Pg: 100
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 fcil 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 mtodo 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 mtodo del readObject en el objeto Movie, se leer el array de bytes del registro, rellenndose el objeto con la informacin de la pelcula guardada es ese registro:
ByteArrayInputStream bis = new ByteArrayInputStream(store.getRecord(recordId)); DataInputStream dis = new DataInputStream(bis); Movie movie = new Movie(); movie.readObject(dis);
Pg: 101
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 mtodo enumerateRecords en el objeto RecordStore:
RecordEnumeration re = store.enumerateRecords(this, this, false);
Pg: 102
Pg: 103
Pg: 104
Pg: 105
Para cada par de registros en el RecordStore (despus de que se ha aplicado el filtro), el correspondiente par de array de bytes se enva al mtodo compare. Como antes, es posible convertir los byte arrays en objetos Movie. Si el ttulo del primer objeto de la pelcula precede lxicograficamente al ttulo del segundo, el mtodo compare retorna RecordComparator.PRECEDES una constante predefinida. Si el ttulo de la primera pelcula sigue al ttulo de la segunda, el mtodo compare retorna RecordComparator.FOLLOWS. Si son iguales, el mtodo retorna RecordComparator.EQUIVALENT. Si no se provee ningn comparador al mtodo enumerateRecords, los registros se clasifican en un orden indefinido.
Pg: 106
RecordStore: Ejemplo
Se adjunta el cdigo de las clases Movie, Serializable y RmsMIDlet, que sirven de demostracin de lo expuesto anteriormente. A continuacin se exponen una pantallas de ejemplo del el cdigo anterior:
Pg: 107
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 mtodos de notificacin provistos por el interfaz sern llamados cuando un registro del RecordStore se aada, se actualice, o se suprima. Para registrar un listener se debe usar el mtodo 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 mtodos 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 cmo trabaja un record listener, podemos ampliar el ejemplo anterior RmsMIDlet para agregar registros de pelculas en un thread diferente ejecutado en background. El objeto de MIDlet se registra como RecordListener, y el correspondiente mtodo 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 definicin de CLDC impone el soporte a threads, por tanto la KVM implementa este soporte.
Pg: 108
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; }
Pg: 109
RecordListener (III)
public void run() { try { // aadir el numero especificado de pelculas en el RecordStore, // pausa entre cada registro aadido 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 (); } } }
Pg: 110
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 continuacin se debe definir un nuevo Command Inicio que ponga en ejecucin 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 mtodos del RecordListener. En este ejemplo, recuperaremos el registro de la pelcula y mostraremos el ttulo del registros agregado o actualizado. Observar que al intentar recuperar el registro afectado en el mtodo recordDeleted fallar, y una excepcin del tipo InvalidRecordIDException se lanzar:
Pg: 111
RecordListener (V)
public void recordAdded(RecordStore store, int recordId) { resultItem.setLabel ("Status:"); resultItem.setText("Pelcula aadida: " + getMovieFromRecord(store, recordId).title); } public void recordChanged(RecordStore store, int recordId) { resultItem.setLabel ("Status:"); resultItem.setText("Pelcula actualizada: " + getMovieFromRecord(store, recordId).title); } public void recordDeleted(RecordStore store, int recordId) { resultItem.setLabel ("Status:"); resultItem.setText("Pelcula eliminada: " + recordId); }
Pg: 112
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; }
Pg: 113
RecordStores en Palm OS
La implementacin de los RecordStores es dependiente del dispositivo, y puede variar entre plataformas. Esta implementacin no esta definida en las especificaciones de MIDP ni en las de CLDC. La implementacin de Palm OS utiliza una base de datos del dispositivo para guardar los RecordStores. Se puede acceder a esta DB de forma idntica 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:
El formato de la base de datos no se especifica ni se soporta, y puede cambiar. Hay maneras soportadas de transferir informacin a y desde un dispositivo.
Los estndares se deben utilizar siempre que sea posible por las siguientes razones:
Los estndares simplifican la migracin de aplicaciones a otras plataformas soportadas. Los estndares facilitan la lectura del cdigo generado por nosotros. Una aplicacin conforme a un estndar es mas fcil que funcione en modelos posteriores. Una aplicacin que siga los estndares tendr ms posibilidades de utilizar las nuevas caractersticas que dispongan las prximas versiones de la plataforma
Si an as se desea acceder directamente a las DB de Palm OS en este link se podr encontrar ms informacin:
http://archives.java.sun.com/cgi-bin/wa?A2=ind0108&L=kvminterest&D=0&H=0&O=T&T=1&P=49045%20.
Pg: 114
Comunicaciones (I)
La principal ventaja de los dispositivos mviles es su posibilidad de conectividad, todo y que esta era en un inicio escasa, se estn realizando grandes progresos a medida que los dispositivos tienen un grado de integracin mayor y los estndares 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 mviles 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 diseadores de CLDC generalizaron las caractersticas de establecimiento de una red de J2SE, proporcionando un marco uniforme para soportar los nuevos dispositivos y los nuevos protocolos que estos pueden requerir.
Pg: 116
Comunicaciones (II)
Connection Connector DatagramConnection InputConnection OutputConnection StreamConnectionNotifier
StreamConnection
ContentConnection
CommConnection
SocketConnection
HttpConnection
SecureConnection javax.microedition.io.*
HttpsConnection
Pg: 117
Comunicaciones (III)
Para el establecimiento bsico 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 bsicas referentes a conectividad en J2SE existe en el CLDC de J2ME. De hecho, el paquete de java.net no existe. Las clases del GCF estn 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 cdigo de una aplicacin es bsicamente el mismo independientemente del protocolo que utilice. Se debe tener en cuenta que los protocolos soportados no estn especificados en el nivel de configuracin. La especificacin de los protocolos pertenece a los perfiles. Esto es consistente con la premisa de que los perfiles especifican las caractersticas que aprovechan de las capacidades del dispositivo. La clase Connector tiene varios mtodos estticos, que se utilizan para crear conexiones. Estos mtodos se resumen a continuacin:
Pg: 118
La forma genrica de abrir una conexin es utilizar el mtodo esttico de Connection tal como sigue
Connector.open("<protocolo>:[<destino>][;<parmetros>]");
Comunicaciones (IV)
static Connection open(String name) static Connection open(String name, int mode) static Connection open(String name, int mode, boolean timeouts) static DataInputStream openDataInputStream(String name) static DataOutputStream openDataOutputStream(String name) static InputStream openInputStream(String name) static OutputStream openOutputStream(String name)
Comunicaciones (V)
El formato de los argumento del mtodo open debe ser conforme con la sintaxis estndar para URIs
El estndar 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 conexin. El argumento opcional < destino > se interpreta en funcin del protocolo. Para conexiones orientadas a red, este parmetro se refiere a una direccin, en formato nombre o IP. Para otros protocolos este argumento se interpreta en funcin del protocolo, si en un futuro se soportan archivos, este argumento contendra el path y el nombre del archivo. Los argumentos opcionales < parmetros > contienen duplas nombre-valor separadas por punto y coma. Por ejemplo, ";nombre1=valor1;nombre2=valor2". Aunque len la especificacin de MIDP se define nicamente el soporte HTTP, HTTP y HTTPS se soportan en la especificacin 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 cdigo desarrollado para Palm ser totalmente portable, dado que todos los dispositivos que implementen MIDP disponen de este protocolo.
Pg: 120
HttpConnection (I)
Para entender el funcionamiento de las APIs de red de MIDP, podemos observar el siguiente ejemplo simple que descarga una pgina desde una conexin 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; }
Pg: 121
HttpConnection (II)
En este ejemplo, utilizamos Connector para abrir una HttpConnection, que se utiliza a continuacin para abrir un stream de entrada de datos. Para descargar los primeros bytes de la pgina del URL especificado, se utiliza el mtodo readFully() para leer todo el array de bytes. Notar que se utiliza el mtodo getLength para crear el array de bytes del tamao necesario. Lo que ocurre en las interioridades de este cdigo es: En primer lugar la conexin HTTP no se realiza cuando se ejecuta el mtodo open de Connector. En este punto se considera que se esta en estado de establecimiento de conexin, la conexin HTTP todava no se ha realizado con el servidor. Se realiza la conexin y los datos se envan y se reciben cuando uno de los mtodos siguientes se llama, causando en HttpConnection una transicin del estado "establecimiento" al estado "conectado": getResponseMessage openInputStream getHeaderFieldInt openOutputStream getHeaderFieldDate openDataInputStream openDataOutputStream getExpiration getDate getLength getLastModified getType getHeaderField getEncoding getHeaderFieldKey getHeaderField getResponseCode
Pg: 122
HttpConnection (III)
Para probar este ejemplo, en el mtodo commandAction de HttpNetworking.java podemos utilizar el cdigo siguiente para establecer la conexin:
public void commandAction(Command c, Displayable d) { try { if (c == getCommand) { resultItem.setLabel("Requesting page..."); resultItem.setText("");
Pg: 123
HttpConnection (IV)
Se puede utilizar NetCat (nc -l -p 80) en el servidor destino para capturar la peticin y enviar una respuesta compatible HTTP, p.ex: Peticin:
" 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 mviles Ao 2004 F2i Sabadell "
Pg: 124
Pg: 125
Pg: 126