desarrollo para j2me

35
El objetivo de esta práctica es aprender a utilizar un entorno de desarrollo para J2ME, el J2ME Wireless Toolkit, con el que vamos a realizar las prácticas de J2ME en el laboratorio. J2ME Wireless Toolkit es un sencillo IDE para el desarrollo de MIDlets, que nos permite compilar, preverificar y ejecutar el código en emuladores de teléfonos móviles y pagers. En esta primera práctica realizaremos nuestro primer MIDlet, el HelloWorld. Y veremos un breve introducción a los componentes de interfaz de usuario que proporciona MIDP. J2ME WIRELESS TOOLKIT En este primer apartado veremos cómo funciona el J2ME Wireless Toolkit, a través de uno de los ejemplos proporcionados en su instalación. KToolBar Para arrancar el J2ME Wireless Toolkit en vuestro ordenador, teclead en la línea de comandos: En los laboratorios docentes de Ingeniería Telemática el WTK22 se encuentra instalado en Windows. La herramienta de desarrollo del WTK22 se denomina ktoolbar y podeis ejecutarla desde: Inicio -> Programas -> J2ME Wireless Toolkit 2.2 -> KToolbar Os aparecerá un ventana como la siguiente:

Upload: marlon-baltazar-aranda

Post on 23-Nov-2015

41 views

Category:

Documents


0 download

TRANSCRIPT

El objetivo de esta prctica es aprender a utilizar un entorno de desarrollo para J2ME, el J2ME Wireless Toolkit, con el que vamos a realizar las prcticas de J2ME en el laboratorio.J2ME Wireless Toolkit es un sencillo IDE para el desarrollo de MIDlets, que nos permite compilar, preverificar y ejecutar el cdigo en emuladores de telfonos mviles y pagers.En esta primera prctica realizaremos nuestro primer MIDlet, el HelloWorld. Y veremos un breve introduccin a los componentes de interfaz de usuario que proporciona MIDP.

J2ME WIRELESS TOOLKIT

En este primer apartado veremos cmo funciona el J2ME Wireless Toolkit, a travs de uno de los ejemplos proporcionados en su instalacin.KToolBarPara arrancar el J2ME Wireless Toolkit en vuestro ordenador, teclead en la lnea de comandos:En los laboratorios docentes de Ingeniera Telemtica el WTK22 se encuentra instalado en Windows. La herramienta de desarrollo del WTK22 se denominaktoolbary podeis ejecutarla desde:Inicio -> Programas -> J2ME Wireless Toolkit 2.2 -> KToolbarOs aparecer un ventana como la siguiente:

Abrir un proyecto

Un proyecto est asociado a un MIDlet suite. El proyecto contiene los ficheros fuentes, los binarios y otros recursos asociados al MIDlet suite, as como el fichero JAD (descriptor) y el manifiesto. Cuando se crea un nuevo proyecto,nombre_proyecto, los ficheros asociados se crean en el directorioapps/nombre_proyecto, con la siguiente estructura de directorios:srcContiene los ficheros fuente

resContiene recursos asociados con el MIDlet

binContiene el JAR, JAD y el manifiesto

libContiene libreras externas en formato JAR o ZIP

Para abrir un proyecto ya existente debemos seleccionar en el menFile -> Open Projecto hacer click sobreOpen Project, nos aparecer la siguiente ventana:

En ella vemos los proyectos que se incluyen con la instalacin del J2ME Wireless Toolkit, seleccionamos, por ejemplo, el degamesy hacemos click sobre el botnOpen Project. En la consola de ktoolbar nos aparecer el mensaje deProject "games" loaded. A partir de este momento ser el proyecto con el que estaremos trabajando.Propiedades del MIDlet suiteTanto el fichero JAD, como el manifiesto se construyen a partir de las propiedades o atributos del MIDlet suite. Desde el J2ME Wireless Toolkit, podemos ver, modificar y aadir nuevas propiedades. Para ello desde el menProject -> Settings...o haciendo click enSettings.... En las diferentes lengetas aparecen los atributos obligatorios,Required, los opcionales,Optionaly tambin los definidos por el usario,User Defined, (recordad que estos atributos se incluyen en el JAD y su nombre no empieza por "MIDlet-"). En la ltima lengetaMIDletsse indican los MIDlets incluidos en el MIDlet suite, en este caso son tres que se corresponden con tres juegos:TilePuzzle,WormGamey elPushPuzzle.Compilar un proyectoDesde el J2ME Wireless Toolkit se puede compilar y preverificar todos los MIDlets incluidos en el MIDlet suite que estamos desarrollando, as como crear los ficheros JAD y JAR correspondientes. Para ello ir al menProject -> Buildo hacer click en el botnBuild.Ejecutar en un dispositivoPor ltimo, ejecutaremos este MIDlet suite en un emulador de un dispositivo, el J2ME Wireless Toolkit nos proporciona cinco emuladores:DefaultColorPhone,DefaultGrayPhone,MediaControlSkinyQwertyDevice, que podemos seleccionar desde la pantalla principal en la lista de seleccin deDevice:.

Vamos a elegir elDefaultColorPhone, y ejecutamos la aplicacin, para ello seleccionar en el menProject -> Runo hacer click enRun.

Podeis seleccionar uno de los tres juegos y ver cmo se ejecuta, recordad que es un emulador de un telfono y tu mano es el ratn.

Ahora ya sabeis que podeis hacer con este entorno, as que empezaremos a desarrollar nuestra primera aplicacin J2ME, el tpico HelloWorld, pero esta vez en MIDP.

CONSEJO:Ver el cdigo fuente de los MIDlet suite de ejemplo, os podrn ayudar para realizar la prctica final.

MIDlet HelloWorld

Creacin del proyecto HelloWorldHaced click enNew Projectaparecer una ventana como la de la imagen, en la que introducireis el nombre de proyecto,HelloWorldy el nombre del MIDlet,HelloWorld.

Al pulsarCreate Project, en la consola del KToolBar aparecer mensajes indicando donde debeis almacenar los ficheros de la aplicacin.

El cdigo de nuestro primer MIDlet es el siguiente (HelloWorld.java)// Incluye la superclase de MIDletimport javax.microedition.midlet.*;// Incluye las libreras de interfaz de usuario de MIDPimport javax.microedition.lcdui.*;

/* * 1. Todos los MIDlets deben extender la clase MIDlet. * 2. CommandListener es el interfaz de gestin de envento del * API de alto nivel de MIDP. Lo veremos con detalle en * prcticas posteriores */public class HelloWorld extends MIDlet implements CommandListener{

// Componentes de UI del MIDlet private Display display; private TextBox mainScreen = null; private Command exit = new Command("exit", Command.EXIT, 2);

// Constructor sin parametros public HelloWorld() { display = Display.getDisplay(this); mainScreen = new TextBox("Text Box", "Hello World CR", 512,0); mainScreen.addCommand(exit); mainScreen.setCommandListener(this);

} // Implementa el metodo startApp() public void startApp() { display.setCurrent(mainScreen); }

// Implementa el metodo pauseApp() public void pauseApp() { }

// Implementa el metodo destroyApp() public void destroyApp(boolean unconditional) {

}

/* * Implementa el metodo correspondiente del interfaz * CommandListener */ public void commandAction(Command c, Displayable s) { if (c == exit) { destroyApp(false); notifyDestroyed(); } }}Debereis colocarlo en el directorio de fuentes correspondiente del proyecto (vuestroapps/src/HelloWorldlocal) y compiladlo. Recordad que la parte de compilacin, que desde el Wireless Toolkit realizais con slo apretar un botn involucra los siguientes pasos:1. Compilacin.2. Preverificacin.3. Creacin del manifiesto MANIFEST.MF (/HelloWorld/bin/MANIFEST.MF)4. MIDlet-1: HelloWorld, HelloWorld.png, HelloWorld5. MIDlet-Name: HelloWorld6. MIDlet-Vendor: Computacion en Red7. MIDlet-Version: 1.08. MicroEdition-Configuration: CLDC-1.09. MicroEdition-Profile: MIDP-1.010. Creacin del fichero JAD (/HelloWorld/bin/HelloWorld.JAD)11. MIDlet-1: HelloWorld, HelloWorld.png, HelloWorld12. MIDlet-Jar-Size: 126513. MIDlet-Jar-URL: HelloWorld.jar14. MIDlet-Name: HelloWorld15. MIDlet-Vendor: Computacion en Red16. MIDlet-Version: 1.017. date: 17/04/2002

Como podeis comprobar, he cambiado algunos de los valores por defecto de las propiedades del MIDlet suite y he definido una nueva propiedaddate, que aparece el fichero JAD.

IMPORTANTE:Es necesario actualizar en losSettings...la propiedadMIDlet-Jar-Sizeal tamao correspondiente.

CONSEJO:dentro del directoriobindel proyecto se crea un scriptbuild.shen el que podeis ver las llamadas en lnea de comandos que es necesario realizar en cada uno de los pasos anteriores.

Por ltimo, ejecutadlo en alguno de los emuladores y comprobad el resultado.

Ejercicio 1:Modificad el HelloWorld anterior para que obtenga el valor de una propiedad definida por vosotros y que la escriba por pantalla, por ejemplo, definid el nombre de la persona a la que se saluda. Para obtener el nombre de la propiedad utilizad el mtodogetAddPropertyde la clasejavax.microedition.midlet.MIDlet

Introduccin a UI en MIDP

Para finalizar la clase de hoy veremos, en el apartado siguiente, algunas clases bsicas de interfaz de usuario (UI) de MIDP, incluidas todas ellas en el paquetejavax.microedition.lcduiDisplayable y DisplayEn J2ME, un objetoDisplayablecontiene la informacin que va a ser visualizada, y un objetoDisplaygestiona qu objetoDisplayablese mostrar al usuario.En MIDP existen tres categoras deDisplayable:1. Screencon estructura predefinida:Alert,ListyTextBox, que encapsulan componentes de interfaz complejos y que las aplicaciones no pueden enriquecer con nuevos componentes.

2. Screengenrica:Form, las aplicaciones pueden llenar este tipo de pantalla con texto, imgenes u otros componentes de interfaz de usuario.

3. Canvas, las aplicaciones tienen control total sobre la aparicin de componentes en el display y puede acceder directamente a eventos de bajo nivel.

La claseDisplayproporciona los mtodos que nos permiten controlar la visualizacin de los objetosDisplayabley obtener propiedades del display (si soporta color o no, nmero de colores,...).Slo existe una instancia del objetoDisplaypor MIDlet, y la aplicacin obtiene una referencia a ese objeto realizando una llamada al mtodogetDisplay()que suele invocarse en el constructor del MIDlet. Para indicar cul es el objetoDisplayableque se visualiza en el display se utilizan los mtodossetCurrent(Displayable nextDisplayable)ysetCurrent(Alert alert, Displayable nextDisplayable). Fijaros cmo se utilizan en el HelloWorld.Eventos y su gestinEn MIDP la gestin de eventos sigue el mismo modelo que se usa en AWT en J2SE, este modelo comprende dos componentes: las fuentes de eventos, que los generan y los "listeners" de eventos, que son los que los procesan. En MIDP los "listeners" de eventos van a estar asociadas a objetosDisplayables, que son las fuentes de eventos.El UI de MIDP a alto nivel utiliza dos tipos de eventos:CommandyItemStateChanged, cada uno de estos eventos tiene el correspondiente listener asociado:CommandListeneryItemStateListener, respectivamente. Cualquier objetoDisplayablepuede ser fuente de eventosCommandmientras que sloFormpuede ser fuente deItemStateListener.

A bajo nivel el UI de MIDP permite gestionar un mayor nmero de eventos, incluyendo pulsacin de cualquier tecla, pantalla tctil,...Para poder capturar eventos a bajo nivel se deben de utilizarDisplayablesde bajo nivel, es decir la claseCanvaso subclases de la misma.

Tanto los eventos a alto nivel, como a bajo nivel tienen una cosa en comn: la gestin de eventos debe de realizarse siempre en el mismo thread en el que se produce el evento.

Para finalizar esta prctica veremos la clase Command y CommandListener utilizadas en el ejemplo HelloWorld.

Un objetoCommandtiene tres valores importantes:1. Label: un String que representa el significado delCommand, y es el que la aplicacin muestra a los usuarios2. Type: un entero que especifica lo que va a realizar elCommand. Los tipos definidos son BACK, CANCEL, HELP, EXIT, ITEM, OK, SCREEN, y STOP3. Priority: un entero que indica la importancia del comando. El que tenga un nmero menos ser el ms importanteLas implementaciones de MIDP mapean estos comandos con lo que se denominan "soft-button", tpicamente los botones que no son numricos en el telfono y que sirven para navegar por los mens.

CommandListeneres un interfaz que proporciona el procesamiento de un eventoCommand, a travs del mtodocommandAction(Command c, Displayable d)que deberemos implementar con las acciones oportunas.

Fijaros cmo se utilizan en el ejemploHelloWorld

Ejercicio 1:Realizar un MIDlet en el que se pueda navegar a travs de dos pantallas, que muestren dos mensajes distintos. En la primera apareceran dos comandos, uno para pasar a la siguiente pantalla y otro para salir, y en la segunda aparecera slo un comando para volver a la primera pantalla.

Ejercicio 2:Ver la posibilidades de la claseImage, y repetid el ejercicio anterior poniendo en cada una de las pantallas una imagen distinto.

OBJETIVOS

En la clase anterior hemos visto como utilizar dos de los elementos centrales en el desarrollo de interfaces de usuario en MIDP, las clases Display/Displayable y la gestin de eventos. La clase Displayable tiene dos subclases: la clase Screen (implementa el API de alto nivel) y la clase Canvas (implementa el API a bajo nivel).En la clase vamos a aprender la funcionalidad del API a alto nivel, es decir, la clase Screen y sus subclases: List, TextBox y Alert que definen estructuras predefinidas y la clase Form cuya estructura es genrica y depende de la aplicacin.

List y Choice

Cuando arranca una aplicacin normalmente presenta una lista de opciones, para que el usuario seleccione alguna de ellas. Veremos en este apartado como la clase List y el interfaz Choice nos permiten realizar este tipo de listas.Clase ListLa clase List es una subclase de la clase Screen que implementa el interfaz Choice. Tiene dos constructores:1. List(String title, int listType)2. List(String title, int listType, String[] stringElements, Image[] imageElements)El primer constructor crea una lista vaca, cuyo elementos de seleccin pueden incluirse posteriormente. El segundo constructor crea un objeto List con los elementos de seleccin, enstringElementsse indican los elementos de la lista y enimageElementsse indican las imgenes asociadas a cada elemento (si no existen imgenes asociadas su valor ennull, si existen,imageElementsdebe de tener la misma longitud questringElements, aunque existan elementos sin imgenes).Interface ChoiceComo podeis ver en el API, el interface Choice define un conjunto de mtodos que sirven para gestionar una lista de seleccin, permitindonos aadir/borrar nuevos elementos, modificar elementos, saber qu elemento est seleccionado,etc.

Elementos de seleccin

Un objeto que implementa el interfaz Choice presenta al usuario una serie de elementos que puede seleccionar. Cada uno de los elementos tiene asociado un texto y opcionalmente una imagen.

El mtodosize()nos permite obtener el nmero de elementos de seleccin que existen y que estn ordenados consecutivamente desde0asize() - 1.

Tanto el texto como la imagen asociados a un elemento de seleccin pueden ser obtenidos y modificados a travs de los mtodosvoid set(int elementNum, String stringPart, Image imagePart)yImage getImage(int elementNum)yString getString(int elementNum).

El estado "seleccionado" de un elemento es un propiedad del elemento. El usuario puede seleccionar o deseleccionar un elemento utilizando alguna tecla del dispositivo (tpicamente la central, que permite movernos hacia arriba y hacia abajo). Las aplicaciones pueden seleccionar el estado de los elementos, a travs de dos mtodos:setSelectedFlags(boolean[] selectedArray)osetSelectedIndex(int elementNum, boolean selected).

Una aplicacin puede aadir o eliminar elementos de la lista de seleccin a travs de los mtodos:append(String stringPart, Image imagePart)yinsert(int elementNum, String stringPart, Image imagePart).

Tipos de objetos Choice

Existen tres tipos de objetos Choice:1. Choice exclusivo: slo existe un nico elemento seleccionado al mismo tiempo, y siempre hay alguno seleccionado.2. Choice implcito: es un choice exclusivo especial en el que se selecciona un elemento cuando se inicializa un Command. El usuario no puede modificar mediante botones, el elemento seleccionado. Este tipo de Choice slo es vlido en la clase List.3. Choice mltiple: cualquier conjunto de elementos puede estar seleccionado.

Estos tres tipos de Choice se diferencian visualmente.

Ejercicio 1:En los enlaces siguientes podeis descargaros tres MIDlets que utilizan cada los tres tipo de Choice: choice exclusivo,ListTest2.java, choice implcito,ListTest1.javay choice mltiple,ListTest3.java. Probadlos en J2ME Wireless Toolkit, empaquetando los tres MIDlets en un mismo MIDlet Suite.

Ejercicio 2:Reutilizando el cdigo de los MIDlet anteriores, crear un MIDlet que muestre en sucesivas pantallas los tres tipos de Choice que hemos visto anteriormente, utilizando la clase List. Como elementos de la listas poned, por ejemplo los que son necesario implementar en la prctica final.

TextBox

La clase TextBox es una subclase de Screen que permite al usuario introducir y editar un texto. Un objeto TextBox puede crearse a travs del constructor:TextBox(String title, String text, int maxSize, int constraints).

Tamao mximo

El contenido de un TextBox se almacena en un char array, y por lo tanto, su tamao est limitado a un determinado nmero de caracteres. El mximo tamao de un objeto TextBox puede limitarse cuando se construye (parmetromaxSizedel constructor), o bien utilizando el mtodosetMaxSize().

Debido a las limitaciones de los telfonos mviles, se limita a un valor por defecto el tamao de los TextBox. A travs del mtodogetMaxSize()se puede obtener el tamao mximo que tiene asignado un determinado objeto TextBox. Si se excede el tamao mximo se produce una excepcinIllegalArgumentException.

Restricciones de entrada

Se pueden indicar las siguientes restricciones (compartidas con la clase TextField):NombreRestriccin

ANYEl usuario puede introducir cualquier texto.

EMAILADDREl usuario puede introducir una direccin de e-mail.

NUMERICEl usuario puede introducir un valor entero (puede ser negativo).

PHONENUMBEREl usuario puede introducir un nmero de telfono con algunos caracteres no-numricos. El conjunto de caracteres que se aceptan dependen de la implementacin.

URLEl usuario puede introducir una URL.

Las restricciones asociadas a un objeto TextBox pueden establecerse cuando se contruye, o bien utilizando el mtodo setConstraints(). Si el string insertado en el TextBox no cumple la restriccin impuesta, se resetea su valor.

Una aplicacin puede obtener las restricciones asociadas a un TextBox con una llamada al mtodo getConstraints().

Editar y obtener texto de un TextBox

Los siguientes mtodos de la clase TextBox pueden utilizarse para editar el texto en el TextBox:1. void delete(int offset, int length)2. void insert(char[] data, int offset, int length, int position)3. void insert(String src, int position)4. void setChars(char[] data, int offset, int length)5. void setString(String text)Las aplicaciones pueden obtener el contenido de un TextBox en un array de bytes mediante el mtodogetChars(char[] data)o en un String mediante el mtodogetString(). El nmero de caracteres en un TextBox se obtiene con una llamada al mtodosize().

Cuando se visualiza un TextBox el usuario puede introducir, en cualquier momento, nuevos contenidos mediante el teclado del telfono. El significado de cada tecla depender de la implementacin, y en general, se mantiene la misma que se utiliza para editar SMS.

Ejercicio 1:El primer MIDlet que implementamos, el HelloWorld utilizaba un TextBox para visualizarnos su saludo. Modificad el cdigo de este MIDlet, para que solicite previamente el nombre del usuario y lo incluya en el posterior saludo.

Alert

La clase Alert es una subclase de Screen, que permite visualizar datos (texto o imgenes) al usuario y espera un cierto periodo de tiempo (timeout) antes de visualizar otra pantalla. Tiene dos constructores:1. Alert(String title)2. Alert(String title, String alertText, Image alertImage, AlertType alertType)Timeout

El timeout est medido en milisegundos, este tiempo se indica bien el constructor o mediante un llamada al mtodosetTimeout(). Se puede indicar un valor de timeout infinito mediante la constanteAlert.FOREVER. Si un objeto de la clase Alert tiene un timeout infinito, la aplicacin debe permitir el cambio de pantalla a travs de algn comando.

Para indicar cul es el siguiente objeto de la claseDisplayableque se visualiza, cuando un objeto de la clase Alert finaliza su timeout, se realiza la llamada al mtodo:Display.setCurrent(Alert alert, Displayable nextDisplayable).

AlertTypes

Los objetos Alert, se utilizan para informar a los usuarios de errores o de otras condiciones excepcionales. Por ello, un objeto Alert puede tener un AlertType, que indica el tipo de problema ocurrido. Se predefinen cinco tipos de Alert:ALARM,CONFIRMATION,ERROR,INFO, yWARNING. Mediante una llamada al mtodosetType()se puede establecer el tipo de un objeto Alert, y mediante una llamada al mtodogetType()se puede obtener el tipo asociado a un objeto Alert.

Ejercicio 1:Pensad qu posibles Alert debereis incluir en la prctica final, por ejemplo, cuando un jugador gane una partida, cuando un jugador consiga el mejor record, cuando el usuario introduce coordenadas errneas, etc.

Form y Items

Form

La claseFormes una subclase deScreen, que contiene un nmero arbitrario deItems, como imgenes, texto y listas de seleccin. La claseFormtiene dos constructores:1. Form(String title), que no contiene Items.2. Form(String title, Items[] items), que contiene un conjunto de Items inciales.

El nmero deItemsque puede contener unForm, se obtiene mediante la llamada al mtodosize(). LosItemsse indexan de forma consecutiva en el rango del0alsize() - 1.

Las aplicaciones pueden utilizar los siguientes mtodos para editarItemsen unForm:1. int append(Image img)2. int append(Item item)3. int append(String str)4. void delete(int itemNum)5. void insert(int itemNum, Item item)6. void set(int itemNum, Item item)

LosItemsen un Form puede recuperarse a travs del mtodoget(int itemNum). Un Item slo puede colocarse en un Form, si un Item ya pertenece a un Form e intenta colocarse en uno nuevo, se produce unaIllegalStateException.

Items

La claseItemes la superclase para un conjunto de elementos, que podremos aadir en unForm. CadaItemtiene asociada una etiquetaLabel, que es un String que suele visualizarse al lado delItemen la pantalla.

Existen seis clases que heredan directamente de Item:1. ChoiceGroup: Es un Item que implementa el interfazChoice. Un objetoChoiceGroupes similar a un objetoList, excepto que no permite Choice implcito.2. StringItem: Es un Item que permite visualizar un texto, los usuarios no pueden interaccionar con un objetoStringItemy cambiar sus contenidos, esto slo se puede hacer desde las aplicaciones.3. ImageItem: Es un Item que contiene un objetoImage. CadaImageItemtiene un parmetro de "layout" que especifica donde se situa la imagen respecto a la pantalla.Layout DirectiveDescripcin

LAYOUT_DEFAULTUsa el formato por defecto que posea el contenedor de la imagen.

LAYOUT_LEFTLa imagen se sita a la izquierda (punto de vista del usuario) del rea dibujada.

LAYOUT_RIGHTLa imagen se sita a la derecha (punto de vista del usuario) del rea dibujada.

LAYOUT_CENTERLa imagen debe centrarse horizontalmente.

LAYOUT_NEWLINE_BEFORESe inserta una lnea antes de dibujar la imagen.

LAYOUT_NEWLINE_AFTERSe inserta una lnea despus de dibujar la imagen.

4. Los diferentesLAYOUTpueden combinarse mediante la operacin OR para obtener el efecto deseado.5. TextField:Es un Item que contiene un texto que los usuarios pueden editar de forma interactiva. UnTextFieldy unTextBoxson muy similares, y tienen algunos mtodos en comn. La diferencia existente es que para visualizar unTextFielddebe incluirse en unForm, unTextBoxpuede visualizarse directamente.6. DataField:Es un Item editable que permite visualizar fechas y tiempos.7. Gauge:Es un Item que visualiza un diagrama de barras de un valor entre un rango de cero amaxValue

Consultad el API para ver todas las posibilidades que proporcionan cada uno de los Items.

Ejercicio 1:Realizad un MIDlet que os permita visualizar la fecha y la hora, en todos los modos que permite la claseDataField.

Desarrollando UI con el API de bajo nivel

OBJETIVOS

En la clase de hoy vamos a ver cmo se utiliza el API a bajo nivel que nos proporciona MIDP para realizar interfaces de usuario. Este API es el favorito de los desarrolladores de juegos porque permite tener control total sobre lo que dibujas en la pantalla, a nivel de pixel, y adems puedes definir tus propios eventos de entrada. Lo que se gana en flexibilidad, se pierde en portabilidad ya que el resultado final depender del telfono concreto en el que se implemente.En una misma aplicacin podrs utilizar los API de alto nivel y de bajo nivel (vistos en la clase pasada), pero no ambos simultaneamente.El objetivo de la clase de hoy es que os familiariceis con este API, para realizar el tablero de juego de la prctica final.

Canvas

La claseCanvases una subclase de Displayable.

Cuando trabajamos a bajo nivel es importante saber las dimensiones del display, ya que stas varan de dispositivo a dispositivo y por lo tanto, nuestras apliaciones no deben de asumir un determinado tamao por defecto. La clase Canvas proporciona los mtodosgetHeight()ygetWidth()para obtener el tamao del display.

La clase Canvas proporciona un mtodopaint(Graphics g)y varios mtodos para la gestin de eventos a bajo nivel que las aplicaciones pueden sobreescribir. La clase Canvas es abstracta y por lo tanto una aplicacin debe obligatoriamente extender la clase Canvas para poder utilizarla. La clase que extiende la clase Canvas debe de proporcionar obligatoriamente una implementacin del mtodo paint()

A continuacin se muestra el cdigo de un MIDlet que extiende la clase Canvas (EjemploCanvas.java):import javax.microedition.lcdui.*;import javax.microedition.midlet.*;

public class EjemploCanvas extends MIDlet {

private Display display; private MyCanvas canvas; public EjemploCanvas(){ display = Display.getDisplay( this ); canvas = new MyCanvas(); } protected void startApp(){ display.setCurrent(canvas); } protected void pauseApp(){ } protected void destroyApp( boolean unconditional ){ } public void exit(){ destroyApp( true ); notifyDestroyed(); }

// extiende la clase Canvas public class MyCanvas extends Canvas { public MyCanvas(){ } protected void paint(Graphics g){ g.setColor( 255, 255, 255 ); g.fillRect( 0, 0, getWidth(), getHeight() ); g.setColor( 0, 0, 0 ); g.drawString( "Hola!", getWidth()/2, 0, g.TOP | g.HCENTER ); } }}

El MIDlet anterior funciona, pero si os fijais para finalizar su ejecucin no espera ninguna interaccin del usuario. Para ello, vamos a ver ahora como se gestionan los eventos con el API de bajo nivel.

La clase Canvas proporciona algunos mtodos para gestionar eventos, que las aplicaciones pueden sobreescribir, estos mtodos son: Entradas del teclado: mtodoskeyPressed,keyRepeated, ykeyReleased.

Utilizando un puntero (pantalla tctil): mtodospointerPressed,pointerDraggedypointerReleased

Visualizacin del Canvas (en el Display): mtodosshowNotify,hideNotify.

Por ejemplo, si sobreescribimos el mtodo keyPressed, en MyCanvas:protected void keyPressed( int keyCode ){ exit();}

El resultado ser que cuando se presione cualquier tecla, finalizar la aplicacin.

Del mismo modo que en el API a alto nivel, se puede definir Commands, que se pueden asociar a un objeto de un clase que extiende la clase Canvas, utilizando el mtodo addCommand.

Graphics

La claseGraphicses similar a la clasejava.awt.Graphicsde J2SE, y proporciona mtodos para geometra en dos dimensiones. Se definen mtodos para dibujar texto, imgenes y lneas, y para dibujar y rellenar rectngulos y arcos, enumero a continuacin alguno de ellos: drawArc(int x, int y, int width, int height, int startAngle, int arcAngle)

drawLine(int x1, int y1, int x2, int y2)

drawRect(int x, int y, int width, int height)

drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight)

fillArc(int x, int y, int width, int height, int startAngle, int arcAngle)

fillRect(int x, int y, int width, int height)

fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight)

Si os fijais en los ejemplos anteriores, el mtodo paint de la clase Canvas, acepta como nico parmetro un objeto de la clase Graphics.

La clase Graphics tambin nos da soporte para colores a travs de varios mtodos: getColor()

getBlueComponent()

getGreenComponent()

getRedComponent()

getGrayScale()

setColor(int RGB)

setColor(int red, int green, int blue)

setGrayScale(int value)

A continuacin, se incluye un MIDlet que dibuja dos lneas (LineTest.java)

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

public class LineTest extends MIDlet { private Display display;

public LineTest() { display=Display.getDisplay(this); }

public void startApp() throws MIDletStateChangeException { display.setCurrent(new LineTestCanvas()); }

public void pauseApp() { }

public void destroyApp(boolean unconditional) { }

class LineTestCanvas extends Canvas { public void paint(Graphics g) { // Tamao del rea de dibujo int width=this.getWidth(); int height=this.getHeight();

// Fondo de la pantalla blanco g.setColor(0xFFFFFF); g.fillRect(0,0,width,height);

// Lneas en negro g.setColor(0x000000); // Dibujamos dos lneas (ejes) g.drawLine(0,height,0,0); g.drawLine(0,height-1,width,height-1); } }}

Como ejercicio y tomando como base el cdigo de los ejemplos anteriores, realizad el tablero del juego de los barcos.

RETO:Os atreveis a que el tablero sea mejor, por ejemplo, que los barcos, las bombas y el agua sean imgenes?

RMS: Almacenamiento en MIDP

OBJETIVOS

MIDP define una sencilla base de datos orientada a registros que permite almacenar a las aplicaciones datos de forma persistente. Esta base se denominaRecord Management System(RMS).La prctica de hoy tiene como objetivo aprender los conceptos bsicos para el manejo de esta base datos, a travs del API que nos ofrece MIDP. Todas las clases relacionadas con RMS estn contenidas en el paquetejavax.microedition.rms.Esta prctica os debe servir para enfrentaros con dos partes de la prctica final: almacenar el estado de una partida, para que sea posible parar y reanudar un partida (opciones del men Stop y Restart) y para mantener el registro de mejores puntuaciones (opcin Records).

RecordStore

El mecanismo bsico de almacenamiento de RMS es denominado record store. Un record store es un conjunto de registros, y un registro es un byte array de datos de tamao variable. Un record store est representado por un objeto de la clase RecordStore.Existen reglas importantes sobre los record store:1. El nombre de un record store consiste en una combinacin de hasta 32 caracteres (sensible a las maysculas).

2. Los record stores creados por MIDlets de un mismo MIDlet suite estn almacenados en el mismo espacio de nombres, y por lo tanto, pueden compartir y ver sus contenidos.

3. Los record stores creados por MIDlets en un MIDlet suite, no son accesibles para los MIDltes de otros MIDlets suite.

4. El nombre de un record store debe ser nico en un MIDlet suite.

Operaciones con un Record StoreLa claseRecordStoreproporciona los siguientes mtodos para crear, abrir, cerrar y borrar un record store: Para crear/abrir un objeto RecordStore se utiliza el mtodopublic static RecordStore openRecordStore(String recordName, boolean createIfNecessary: Para crearlo se puede utilizar:RecordStore.openRecordStore(recordStoreName, true), de tal forma que si el record store con nombrerecordStoreNameno existe, se crea. Si existe, se "abre" el existente para trabajar sobre l.

Para abrirlo tambin se puede utilizar:RecordStore.openRecordStore(recordStoreName, false), de tal forma que si el record store no existe, se produce una excepcinRecordStoreNotFoundException

Para cerrar un objeto RecordStore se utiliza el mtodopublic void closeRecordStore. Despus de utilizar un record store siempre debe cerrarse.

Para borrar un objeto RecordStore se utiliza el mtodopublic static void deleteRecordStore(String recordStoreName). Antes de borrar un record store es necesario cerrarlo.

Cada record store mantiene al menos un campo de cabecera. Si no existe espacio suficente para almacenar la cabecera, el record store no se crear y se producir unaRecordStoreFullException. Si ocurre otro tipo de problema, como que el nombre del record store es demasiado largo, o el record store est corrupto, se produce unaRecordStoreException.

A continuacin, se puede ver un sencillo ejemplo de creacin de un RecordStore (RecordStoreTest1.java).import javax.microedition.midlet.*;import javax.microedition.rms.*;

public class RecordStoreTest1 extends MIDlet { public RecordStoreTest1() { } public void startApp() throws MIDletStateChangeException { RecordStore rs=null; try { rs = RecordStore.openRecordStore("file1",true); System.out.println("record store file1 is opened."); }catch(Exception e){ System.out.println("Error: "+e.getMessage()); } finally{ //close the record store try { rs.closeRecordStore(); System.out.println("record store file1 is closed"); }catch (Exception e){ System.out.println("Error: "+e.getMessage()); } } destroyApp(true); notifyDestroyed(); }

/** * Pause the MIDlet */ public void pauseApp() { }

/** * Called by the framework before the application is unloaded */ public void destroyApp(boolean unconditional) { }}Records

Los elementos de un record store se denominan records. Los records se representan por arrays de bytes y se identifican univocamente medianterecordIDs(valores enteros que comienzan en1). Los records pueden se aadidos, borrados, leidos y modificados a travs de los siguientes mtodos, proporcionados por el API: public int addRecord(byte[] data, int offset, int numBytes)

public void deleteRecord(int RecordId)

public int getRecord(int recordId, byte[] buffer, int offset)ypublic byte[] getRecord(int recordId)

public void setRecord(int recordId, byte[] newData, int offset, int numBytes)

A continuacin podeis ver un ejemplo sencillo, que partiendo del primer ejemplo, aade dos records nuevos y borra uno de ellos (RecordStoreTest3.java).import javax.microedition.midlet.*;import javax.microedition.rms.*;

public class RecordStoreTest3 extends MIDlet { public RecordStoreTest3() { } public void startApp() throws MIDletStateChangeException { RecordStore rs=null; try { rs = RecordStore.openRecordStore("file1",true); byte data[]= new byte[4]; for(int j=0; j> 24) & 0xff); data[1] = (byte)((i >> 16) & 0xff); data[2] = (byte)((i >> 8) & 0xff); data[3] = (byte)(i & 0xff); System.out.println("record "+ rs.addRecord(data,0,4)+" is added."); }try { rs.deleteRecord(2); System.out.println("record 2 is deleted.");}catch(InvalidRecordIDException e) {System.out.println("record 2 does not exist");} }catch(Exception e){} finally{ //close the record store try { rs.closeRecordStore(); }catch (Exception e){} } destroyApp(true); notifyDestroyed(); }

/** * Pause the MIDlet */ public void pauseApp() { }

/** * Called by the framework before the application is unloaded */ public void destroyApp(boolean unconditional) { }}La cabecera de un Record StoreLos record stores al igual que los ficheros mantienen una cabecera con informacin propia: El nmero de records en el record store. El valor inicial es cero. Cuando se aade un nuevo record, su valor se incrementa en uno. Cuando se elimina un record su valor se decrementa en uno. Para obtener su valor se utiliza el mtodopublic int getNumRecords()

Nmero de versin. El nmero de versin inicial depende de la implementacin, y normalmente es cero, cada vez que un record es aadido, borrado o modificado, el nmero de versin se incrementa, normalmente en uno. Para obtener su valor se utiliza el mtodopublic int getVersion(). La versin le sirve a los MIDlets para saber si otro proceso o thread ha modificado un determinado record store

El ltimo momento en el que se modific. Para obtener su valor se utiliza el mtodopublic long getLastModified()

El siguiente recordID. El identificador del siguiente record que ser aadido. Para obtener su valor se utiliza el mtodopublic int getNextRecordID()

El API nos proporciona adems la siguiente informacin adicional sobre los records store, aunque no est almacenada en la cabecera: public int getSizeAvailable(), que nos permite saber cual es la memoria disponible en bytes, para seguir almacenando en el record store.

public int getSize(), que nos permite saber cuanto espacio ocupa, en bytes, el record store.

public static String[] listRecordStores(), que nos permite obtener en un array de Strings los nombres de los records stores en un MIDlet suite. Si no se ha creado ninguno devuelvenull.

El interfaz RecordListenerA travs del interfazRecordListenerse pueden monitorizar cambios en record stores. Se pueden gestionar tres tipos de eventos, a travs de los mtodos: void recordAdded(RecordStore recordStore, int recordId)

void recordChanged(RecordStore recordStore, int recordId)

void recordDeleted(RecordStore recordStore, int recordId)

La clase RecordStore proporciona los siguientes mtodos para aadir o borrar un RecordListener: public void addRecordListener(RecordListener listener)

public removeRecordListener(RecordListener listener)

NOTA:Un objeto RecordStore puede tener varios RecordListeners registrados.

RecordEnumeration

Despus de que los records se borren, los recordIds de los records que estn almacenados en un record store no son consecutivos. Por lo tanto, realizar un recorrido secuencial para obtener todos los records almacenados no es la manera ms eficiente de hacerlo.

Para ello se proporciona la claseRecordEnumeration, que aunque en el API de MIDP se presenta como un interfaz, toda implementacin de MIDP debe proporcionar una implementacin de ella.

Un RecordEnumeration es parecido a un lista doblemente enlazada, en la que cada nodo representa un recordId. Un RecordEnumeration mantiene una secuencia lgica de recordIds de los records almacenados en un record store.

Ejercicio:Analizad el interfaz y realizad un pequeo programa en el que obteneis secuencialmente el contenido de los records en un record store. Cread despus un nuevo programa que utilice la implementacion de RecordEnumeration y comprobad la diferencia.

RecordFilter y RecordComparator

El interfazRecordFilterdefine un nico mtodopublic boolean matches(byte candidate[])que nos permite definir un criterio para seleccionar un record en un record store que cumpla una determinada condicin, de tal forma que si la cumple, se devuelvetruey si nofalse.

El interfazRecordComparatornos proporciona una forma sencilla de clasificar records. Define una nica funcinint compare(byte[] rec1, byte[] rec2), que puede devolver nicamente los siguientes constantes: PRECEDES FOLLOWS EQUIVALENT

Por ejemplo, una manera de clasificarlos sera por fecha de creacin. As al implentar esta funcin se devolveraPRECEDESsirec1se ha creado antes derec2,FOLLOWSsi se ha creado despus yEQUIVALENTsi se han creado simultaneamente.

Programacin en red en MIDP

OBJETIVOS

En la clase de hoy vamos a ver el soporte que da MIDP a la programacin en red. Como hemos visto en la clase terica, en el CLDC de J2ME se redisearon las clases para entrada/salida y para el soporte a conexiones de red de J2SE, definiendo lo que se denominaCLDC Generic Connection Framework.

CLDC Generic Connection Frameworkdefine una serie de interfaces para dar soporte a la variedad de tipos de conexiones que nos podemos encontrar en dispositivos mviles, pero no implementa ninguna de ellas, es en los perfiles donde se debe realizar esta implementacin. En el perfil con el que estamos trabajando, MIDP, se debe dar soporte obligatoriamente a conexiones HTTP, a travs de la implementacin del interfazHttpConnection.

Para la prctica final no necesitais hacer uso de conexiones de red, por lo que es muy recomendable realizar esta prctica para que completeis vuestros conocimientos sobre MIDP.

CLDC Generic Connection Framework

En elCLDC Generic Connection Framework, todas las conexiones se crean utilizando el mtodo estticoopende la claseConnector. Si no se produce ningn error, este mtodo devuelve un objeto que implementa una de las interfaces definidas en elCLDC Generic Connection Framework.Estas interfaces estn contenidas en el paquetejavax.microedition.ioy son: El interfazConnectiones el tipo bsico de conexin. Esta conexin slo puede abrirse y cerrarse.

El interfazInputConnectionrepresenta un dispositivo desde el que se pueden leer datos. Proporciona el mtodoopenInputStreamque devuelve un stream de entrada para la conexin.

El interfazOuputConnectionrepresenta un dispositivo en el que se pueden escribir datos. Proporciona el mtodoopenOutputStreamque devuelve un stream de salida para la conexin.

El interfazStreamConnectionque combina la conexiones de entrada y de salida anteriores.

El interfazContectConnectionque es una subinterfaz deStreamConnection. Proporciona acceso a informacin de algunos meta datos proporcionados en un conexin HTTP.

El interfazStreamConnectionNotifiedque espera a que se establezca una conexin. Devuelve unStreamConnectiona travs del cual puede establecerse un enlace de comunicacin bidireccional.

El interfazDatagramConnectionque representa el destino de un datagrama.

El mtodoopende la claseConnectortiene la siguiente sintaxis,Connector.open(String);

donde el parmteroStringtiene el formato"protocol:address;parameters". Por ejemplo: Conexin HTTP: Connector.open("http://www.it.uc3m.es/pervasive"); Conexin Datagrama: Connector.open("datagram://address:port#"); Conmunicacin con puerto serie: Connector.open("comm:0;baudrate=9600"); Acceso a ficheros: Connector.open("file:/miFichero.txt");

El objetivo de tener esta sintaxis, es abstraer al programador de las diferencias que existen entre los diferentes protocolos, de manera que la mayora del cdigo de una aplicacin no se modifica cuando se cambia el protocolo que se est usando.

IMPORTANTE:Los ejemplos de conexiones anteriores son slo ilustrativos. CLDC en s mismo no proporciona ninguna implementacin de ningn protocolo, stas deben de proporcionarse a nivel de perfil. Adems un determinado perfil no tiene porque implementar todos los protocolos, as MIDP proporciona una implementacin del protocolo HTTP, pero en general no implementa ni sockets, ni datagramas (aunque algunos fabricantes pueden incorporarlas).

En el siguiente apartado veremos el interfazHttpConnectionpropocionada en MIDP.

HttpConnection

HTTP puede implementarse utilizando protocolos IP (como TCP/IP) o protocolos no-IP (como WAP o i-mode), por este motivo se seleccion como protocolo para comunicaciones de red en MIDP. Todas las implementaciones de MIDP deben soportarlo, garantizando de esta manera la portabilidad de las aplicaciones, que utilizan este protocolo, entre diferentes dispositivos.

En MIDP se define un nuevo interfaz dentro de la jerarqua delCLDC Generic Connection Framework, el interfazHttpConnectionpara el soporte a conexiones HTTP. Este interfaz extiende del interfazContentConnection.

El protocolo HTTP es un protocolo a nivel de aplicacin del tipo peticin/respuesta, en el que los parmetros de una peticin deben establecerse antes de que se enve la peticin. La conexin puede estar en uno de los siguientes tres posibles estados: "Setup": No se ha establecido todava la conexin.

"Connected": Se ha establecido la conexin, la peticin se ha enviado y se est esperando por una respuesta.

"Closed": La conexin se ha cerrado.

En el interfazHttpConnectionse proporcionan una serie de mtodos que pueden invocarse en cada uno de los estados anteriores:

En el estado "setup" se pueden invocar los siguientes mtodos: setRequestMethod(String method)que establece el mtodo de la peticin, que puede serPOST,GEToHEAD. El mtodo por defecto esGETy si el mtodo no es HTTP o la implementacin de HTTP est recortada y no lo soporta, se produce unaIOException.

setRequestProperty(String key, String value)que permite indicar el valor de algunas propiedades HTTP antes de enviar la peticin, la propiedad que se quiere establecer se indica en el parmetrokeyy su valor se establece en el parmetrovalue.

Por ejemplo, en el cdigo siguiente se crea una conexin HTTP a la URLhttp://www.it.uc3m.es/pervasivey se indica que el mtodo de la peticin esPOST, y que la propiedad HTTPUser-Agenttiene el valorProfile/MIDP-1.0 Configuration/CLDC-1.0:HttpConnection c = (HttpConnection)Connector.open("http://www.it.uc3m.es/pervasive");c.setRequestMethod(HttpConnection.POST);c.setRequestProperty("User-Agent, "Profile/MIDP-1.0 Configuration/CLDC-1.0");

La transicin entre el estado "setup" y el estado "connected" se produce cuando se invoca algn mtodo que precisa enviar o recibir datos al servidor con el que se establece la conexin. Algunos de los mtodos que proporciona la implementacin del interfazHttpConnectiony que provocan esta transicin, son: openInputStream ()

openOutputStream()

openDataInputStream()

openDataOutputStream()

getLength()

getType()

getDate()

getExpiration()

Cuando la conexin est abierta (se ha pasado al estado de "connected"), se pueden invocar los siguientes mtodos: getURL()

getProtocol()

getHost()

getPort()

close()

A continuacin se muestra un ejemplo de cdigo en el que se utiliza la implementacin deHttpConnectionpara leer el contenido de la pginahttp://www.it.uc3m.es/celeste/docencia/cr/hola.txty mostrarselo al usuario (MIDletHTTPExample.java):import java.io.*;import javax.microedition.midlet.*;import javax.microedition.io.*;import javax.microedition.lcdui.*;

/** * Un ejemplo de MIDlet para visualizar el contenido de una URL * utilizando la implementacin del interfaz HttpConnection. */

public class MIDletHTTPExample extends MIDlet {

private Display display; private String url = "http://www.it.uc3m.es/celeste/docencia/cr/hola.txt";

public MIDletHTTPExample() { display = Display.getDisplay(this); }

/** * Mtodo startApp() */ public void startApp() { // Llama al mtodo download para descargar el contenido de la URL try { download(url); } catch(IOException e) { System.out.println("IOException: " + e); } }

private void download (String url) throws IOException { StringBuffer b = new StringBuffer(); InputStream is = null; HttpConnection c = null; TextBox t = null; try { long len = 0 ; int ch = 0;

// Abre una conexin del tipo HttpConnection c = (HttpConnection)Connector.open(url); // Obtiene un stream de entrada, para leer el contenido de la url // con la que establece la conexin is = c.openInputStream(); // Lee hasta que se cierra la conexin while ((ch = is.read()) != -1) { b.append((char)ch); } // Se contruye un TextBox con el contenido de la URL t = new TextBox("Hola...", b.toString(), 1024, 0);

} finally { // Se cierra tanto el stream de entrada if (is != null) is.close(); // Se cierra la conexin if (c != null) c.close(); } // Se visualiza el TextBox en el Display display.setCurrent(t); } /** * pauseApp */ public void pauseApp() { }

/** * destroyApp */ public void destroyApp(boolean unconditional) { }}

Ejercicio 1:Partiendo del cdigo del ejemplo anterior realizad un MIDlet que solicite al usuario una URL y una etiqueta HTML, y le muestre como resultado el texto modificado por esa etiqueta.

Ejercicio 2:Repetid el ejercicio anterior, pero adems de visualizar el texto modificado por la etiqueta HTML, almacenad su contenido en un Record Store, de forma que el usuario de forma "off-line" pueda visualizar el resultado de sus consultas (por lo tanto, se debe de almacenar: URL solicitada, etiqueta HTML indicada y texto modificado por la etiqueta HTML en la URL indicada).