Вы находитесь на странице: 1из 56

Master Universitario en Informtica Aplicada a las Telecomunicaciones Mviles

J2ME: Java para dispositivos mviles

Programacin Java

Febrero 2006 David Bueno Vallejo

Plan

Introduccin Introducci Instalacin Instalaci Primer Programa Interfaz de Usuario en J2ME
Commands Screen (Alertas, formularios, imgenes, choicegroup, ticker) im choicegroup, ticker) GameCanvas (lectura de teclado, dibujar en pantalla, sprites, sprites, tiledLayer, tiledManager, scroll, colisiones) tiledLayer, tiledManager, scroll,

RMS HTTP Vibracin e Iluminacin Vibraci Iluminaci Otros: bluetooth/obex, servicios Web, Grficos 3D, bluetooth/ obex, Gr sonido y msica m Referencias 2

Introduccin
Se
llama J2ME (Java Micro Edition) a las Edition) implementaciones de Java par dispositivos mviles m Hay varias implementaciones dependiendo del tipo de dispositivo CLDC y MIDP Personal Java (jdk 1.22) API propia

Telfonos, PALM, Blackberry PDAs Pocket PC Blackberry

En este tema se ve la implementacin relacionada con implementaci


Telfonos Mviles, PALM y Blackberry (API MIDP) Tel M

Introduccin

El universo de J2ME.

Imagen de [Knudsen2003]

Introduccin

Componentes software de MIDP.

Imagen de [Knudsen2003]

Instalacin
Java Development Kit (JDK)
Descripcin: Entorno de desarrollo de java para PC. Versin 1.4.2 o Descripci Versi superior (ltima 1.5 y 1.6 Beta) ( Descarga: http://java.sun.com/j2se/downloads.html j2sdk-1_4_2-windows-i586.exe y j2sdk-1_4_2-doc.zip (docs) j2sdk- 1_4_2- windows- i586.exe j2sdk- 1_4_2docs) Instalacin: Instalaci

Ejecutar el instalador y seleccionar la carpeta por defecto. P.ej: P.ej: Descomprimir la documentacin en esa carpeta documentaci Actualizar la variable de entorno PATH=c:\jsdk1.4.2\bin\ PATH=c:\ jsdk1.4.2\bin\
c:\jsdk1.4.2 c:\ jsdk1.4.2

Instalacin
J2ME Sun Java Wireless Toolkit
Descripcin: Entorno para compilar y generar .jar y .jad incluye Descripci .jar .jad emuladores Descarga: http://java.sun.com/products/sjwtoolkit/download-2_3.html http://java.sun.com/products/sjwtoolkit/downloadsun_java_wireless_toolkit-2_3-beta-windows.exe sun_java_wireless_toolkit- 2_3- beta(Admite bluetooth, multimedia, API 3D, posicionamiento,) bluetooth, posicionamiento, Instalacin: Instalaci

Ejecutar el instalador y seleccionar destino: c:\WTK23 c:\

Primer Programa: Hola Mundo


HolaMundo Primero se compilar y ejecutar en el PC en un compilar ejecutar emulador Despus se enviar al mvil y se ejecutar en l. Despu enviar m ejecutar Los pasos son los siguientes: 1. Con un editor de texto escribir el programa de la transparencia siguiente. Guardarlo como HolaMundo.java

A continuacin se va a realizar el primer programa: continuaci

Primer Programa: Cdigo y explicacin


import javax.microedition.midlet.*; import javax.microedition.lcdui.*; public class DBVHolaMundo extends MIDlet implements CommandListener { private Display pantalla ; private TextBox texto1 ; private Command salir; public DBVHolaMundo() { pantalla = Display.getDisplay(this); // Devuelve un manejador de la pantalla salir = new Command("Salir", Command.SCREEN, 1); // Crea un nuevo comando para Salir texto1 = new TextBox("Hola Mundo", "Mi primer MIDlet", 40, 0); // Crea un cuadro de texto texto1 .addCommand(salir); // Aade el comando al cuadro de texto texto1 .setCommandListener(this); // Indica que la gestin de evento se hace en esta clase } public void startApp() { // Se ejecuta al comenzar la aplicacin pantalla .setCurrent(texto1); // Muestra en la pantalla el texto y el comando } public void pauseApp() { } // Se ejecuta si se interrumpe la aplicacin public void destroyApp(boolean unconditional) { } // Se ejecuta al terminar public void commandAction(Command c, Displayable displayable) { // Gestiona los eventos if (c == salir) { // Si el evento es pulsar el botn salir, termina destroyApp(false); notifyDestroyed(); } } }

Primer Programa: Proyecto


2. Abrir el programa Ktoolbar (c:\j2me\WTK21\bin) (c:\ j2me\ WTK21\ bin)
1. Seleccionar New Project

Esto crea la siguiente estructura en c:\j2me\WTK23\apps\HolaMundo c:\ j2me\ WTK23\ apps\ Hay que guardar en src el cdigo (.java) (HolaMundo.java anterior) c (HolaMundo.java En classes se guardarn los (.class) guardar (.class) En bin se guardarn los ficheros que hay que enviar al mvil (.jad y .jar) guardar m (.jad .jar)
10

Primer Programa: Generacin


2. Ktoolbar
2. Compilar/Enlazar el cdigo con el botn Build c bot

11

Primer Programa: Ejecucin en emulador


2. Ktoolbar
3. Seleccionar el emulador en el desplegable Device 4. Ejecutar mediante el botn Run bot

Siguiendo estos pasos se pueden probar todos los programas que se realicen en el emulador. El siguiente paso ser pasar el programa al telfono ser tel
12

Primer Programa: Preparacin para el mvil


2. Ktoolbar
5. Editar datos del proyecto: (Project Settings Required) (Project Required)
Nombre del perfil. Por defecto es MIDP-2.0. Si el telfono slo es compatible con MIDP-1.0 es IMPRESCINDIBLE cambiarlo. (Por ejemplo, para el Nokia 3650)

Nombre del proveedor

6. Generar los fichero .jad y .jar: Project Package Create Package .jad .jar: 7. Los 2 ficheros a enviar al telfono son: HolaMundo.jad tel HolaMundo.jar, guardados en c:\j2me\WTK21\apps\HolaMundo\bin HolaMundo.jar, c:\ j2me\ WTK21\ apps\ HolaMundo\

y
13

Primer Programa: Envo al telfono bluetooth


3. Enviar los 2 ficheros al telfono por bluetooth tel
1. Instalar dispositivo bluetooth en PC (Como ejemplo se explicarn los pasos para el dispositivo Bluetooth 3Com) explicar 2. Arrancar en el PC el Bluetooth Connection Manager (o programa similar que traiga el Bluetooth) Bluetooth) 3. Encender en el telfono el bluetooth (Normalmente: tel Conexiones Bluetooth Activar) Activar) 4. Si todo va bien el PC ver el ver telfono. Con el botn derecho tel bot sobre el icono seleccionar enviar archivo 5. Seleccionar los 2 ficheros HolaMundo.jad y HolaMundo.jar y enviarlos al telfono tel

14

Primer Programa: Envo al telfono bluetooth


3. Enviar los 2 ficheros al telfono por bluetooth tel
6. En el telfono se recibirn 2 mensajes. Uno por cada fichero. tel recibir Aceptarlos. 7. En el men mensajes Buzon de entrada del telfono Abrir el men tel fichero HolaMundo.jad. Aparecer un mensaje como: HolaMundo.jad. Aparecer
Instalar HolaMundo 1.0 suministrado por David Bueno?

8. Donde el nombre de la aplicacin, la versin y el suministrador aplicaci versi son los que se hayan seleccionado al editar los datos del proyecto 9. Si la instalacin es correcta, se podr ejecutar la aplicacin en instalaci podr aplicaci el men del telfono Aplicaciones Hola Mundo men tel

15

Primer Programa: Envo al telfono infrarrojos


NOKIA:
Si se pasan los ficheros directamente no pueden ejecutarse Es necesario descargar el instalar la aplicacin: NOKIA PC Suite aplicaci Se puede descargar de http://www.nokia.es (seleccionando el http://www.nokia.es tefono y las aplicaciones para ste) te

16

Primer Programa: Envo al telfono serie/usb


SIEMENS:
Conectar el telfono al cable serie o usb tel Es necesario descargar el instalar la aplicacin: Siemens Data aplicaci Suite Se puede descargar de http://www.siemens-mobile.com http://www.siemens(seleccionando el tefono y las aplicaciones para ste) te Despus aparecer el telfono como una carpeta y habr que Despu aparecer tel habr copiar los ficheros .jad y .jar en la carpeta /java/jam/HolaMundo .jad .jar /java/jam/

17

Primer Programa: Envo al telfono por Web


Se necesita un servidor Web accesible desde el exterior En el servidor web habr que configurar 2 tipos MIME: habr
text/vnd.sun.j2me.app-descriptor application/java-archive jad jar

Dentro de la UMA es necesario tener abierto el puerto 80 en los servicios centrales de Informtica Inform

En algunos mviles ser suficiente con descargar el .jar m ser .jar En lo que no sea suficiente, habr que descargar el .jad habr .jad
pero modificando la linea URL de la siguiente forma:
Antes
MIDlet-Jar-URL: DBVMijar.jar

Despus
MIDlet-Jar-URL: http://miweb.com/DBVMijar.jar 18

Interfaz de Usuario en J2ME


Hay 3 formas como un usuario puede interactuar con las
aplicaciones
Command.- Son acciones que se asocian a los botones que el Command. usuario pulsa en el dispositivo para realizar alguna tarea Screen.- Interfaz de alto nivel con alertas, formularios, cuadros Screen. de texto, radiobuttons, checkbox, listas similares a las utilizadas radiobuttons, checkbox, en HTML Canvas.- Interfaz de bajo nivel en la que el usuario trabaja a Canvas. nivel de pixel, utilizadas para aplicaciones como juegos pixel,

19

IU: Display Class


La pantalla del dispositivo se asocia a un objeto Display Un MIDlet est asociado a un nico objeto Display est En este objeto se pueden mostrar objetos de tipo
Displayable (Screen y Canvas) Canvas)
Screen Displayable Alert List Form TextBox

Canvas Javax.microedition.lcdui

GameCanvas Javax.microedition.lcdui.game
20

10

IU: Display Class


La referencia al objeto Display se obtiene normalmente
en el constructor o en startApp() aunque se declare startApp() como atributo de la clase
public class NombreClase { Private Display pantalla; Public void startApp() { pantalla= Display.getDisplay(this); } }

Se pueden tener varios objetos de tipo Displayable pero

slo uno (aunque puede ser compuesto como un form) form) que se muestre en el Display. Para asociarlo a la pantalla Display. se utiliza setCurrent y se puede cambiar cuando se quiera TextBox cuadrotexto;
cuadrotexto=new TextBox(titulo,contenido,30,TextField.ANY); pantalla.setCurrent(cuadrotexto); 21

IU: Command Class


Son acciones que se asocian a botones del dispositivo.
Los posibles tipos son:
Command.BACK Command.CANCEL Command.EXIT Command.HELP Command.ITEM Command.OK Command.SCREEN Command.STOP Ir a la pantalla anterior Cancelar la operacin actual Terminar la aplicacin Mostrar ayuda Asocia una accin a un elemento de la pantalla Aceptar Accin genrica para comandos especficos de la aplicacin Para parar la operacin actual

Aunque existan todos esos tipos en realidad no influye el

hecho de elegir uno u otro salvo en la posicin en la que posici aparecer en pantalla aparecer Para crear una nuevo objeto Command 3 parmetros par (texto, tipo, prioridad [0 es la mxima]): m
Command miok; Miok=new Command(Aceptar, Command.OK,0) 22

11

IU: Command Class


Para aadir el Command al display a
Pantalla.addCommand(miok);

Para asociar una accin a un Command hay que implementar la acci


interfaz CommandListener
public class MiClase extends MIDlet implements CommandListener { public void commandAction(Command c, Displayable displayable) { if (c == quitar) { destroyApp(false); notifyDestroyed(); } else if (c==miok) { } }

Como ejemplo un programa con 2 cuadros de texto, uno de los

cuales es una ayuda, en total hay 3 command asociados a las operaciones de salir de la aplicacin, ayuda y volver (salir de la aplicaci ayuda)
23

Programa: DBVCommands

24

12

Programa: DBVCommands
import javax.microedition.midlet.*; import javax.microedition.lcdui.*; public class DBVCommands extends MIDlet implements CommandListener { private Display pantalla ; private TextBox tintro,tayuda ; private Command salir, ayuda, volver; public DBVCommands () { pantalla = Display.getDisplay(this); // Preparando la pantalla principal tintro = new TextBox("Mis Comandos", "Puedes salir o elegir ayuda", 40, 0); salir = new Command("Salir", Command.EXIT, 0); ayuda = new Command("Ayuda",Command.HELP,1); tintro .addCommand(salir); tintro.addCommand(ayuda); tintro.setCommandListener(this); // Preparando pantalla de ayuda tayuda = new TextBox("Ayuda", "Para salir debe regresar :-)", 40, 0); volver=new Command("Volver",Command.BACK,1); tayuda.addCommand(volver); tayuda.setCommandListener(this); } public void startApp() { pantalla .setCurrent(tintro); } public void pauseApp() { }

25

Programa: DBVCommands
public void destroyApp(boolean unconditional) { } public void commandAction(Command c, Displayable displayable) { if (c == salir) { destroyApp(false); notifyDestroyed(); } else if (c==ayuda) { pantalla.setCurrent(tayuda); } else if (c==volver) { pantalla.setCurrent(tintro); } } }

26

13

IU: Screen:Alertas
Las alertas son cuadros de dialogo que avisan al usuario
de algn problema, confirman alguna accin del usuario, alg acci o muestran un recordatorio en la pantalla Hay varios tipos predefinidos

AlertType.ALARM, AlertType.CONFIRMATION, AlertType.ERROR, AlertType.INFO, AlertType.WARNING

El constructor de la alerta tiene 4 parmetros: ttulo, par t


texto, imagen, tipo
Alert mialerta; mialerta=new Alert(Titulo,Texto de la alerta, null, AlertType.CONFIRMATION);

Las alertas pueden ser:


Modales. Permanecen hasta que el usuario realce alguna accin acci
mialerta.setTimeout(Alert.FOREVER);

Temporales. Se cierran pasado algunos segundos


mialerta.setTimeout(5000); // Espera 5 segundos 27

IU: Screen:Alertas
Por defecto aparecen acciones Command asociadas a Command
las alertas, aunque pueden definirse nuevas con addCommand para personalizar los resultados Para mostrar la alerta se cambia el display como siempre
pantalla.setCurrent(mialerta);

Cuando la alerta se cierra se vuelve a la pantalla anterior Si se quiere que al cerrar la alerta se pase a otra
pantalla se utiliza un segundo parmetro de setCurrent par
pantalla.setCurrent(mialerta,siguientepantalla);

28

14

IU: Screen:Formularios
Los formularios permiten recoger datos del usuario En un formulario se pueden incluir derivados de la clase
Item
ChoiceGroup, CustomItem, DateField, Gauge, ImageItem, ChoiceGroup, CustomItem, DateField, ImageItem, Spacer, StringItem, TextField StringItem,
Form miform; miform=new Form(Ttulo");

Se aaden elementos al formulario con Append a


TextField usuario; usuario=new TextField("usuario","",10,TextField.ANY); miform.append(usuario);

A continuacin un ejemplo de un formulario que pide un continuaci


nombre de usuario y una contrasea. Utiliza una alerta contrase para mostrar el nombre ledo le
29

Programa: DBVAcceso

30

15

Programa: DBVAcceso
import javax.microedition.midlet.*; import javax.microedition.lcdui.*; public class DBVAcceso extends MIDlet implements CommandListener { private Display pantalla ; private Form flogin ; private Alert confirmacion; private TextField usuario; private TextField passwd; private Command salir,aceptar; private String cad; public DBVAcceso () { pantalla = Display.getDisplay(this); // Preparando la pantalla principal flogin=new Form("Control Acceso"); usuario=new TextField("usuario","",10,TextField.ANY); passwd=new TextField("contrasea","",10,TextField.ANY|TextField.PASSWORD); aceptar = new Command("Enviar", Command.OK, 0); salir = new Command("Salir", Command.EXIT, 0); flogin.append(usuario); flogin.append(passwd); flogin.addCommand(aceptar); flogin.addCommand(salir); flogin.setCommandListener(this); // Alerta de confirmacion de datos confirmacion= new Alert ("Confirmacin","", null, AlertType.CONFIRMATION); confirmacion.setTimeout(Alert.FOREVER); }

31

Programa: DBVAcceso
public void startApp() { pantalla .setCurrent(flogin); } public void pauseApp() { } public void destroyApp(boolean unconditional) { } public void commandAction(Command c, Displayable displayable) { if (c == salir) { destroyApp(false); notifyDestroyed(); } else if (c==aceptar) { cad="Bienvenido al sistema " + this.usuario.getString(); confirmacion.setString(cad); pantalla.setCurrent(confirmacion); } }

32

16

IU: Screen: Formularios: Imgenes


Para trabajar con imgenes hay que hacerlo en formato im
.png El programa Paint de Windows guarda cualquier imagen en este formato Hay que guardar las imgenes en la carpeta res que im genera J2ME Wireless Toolkit (WT) al crear un proyecto La referencia a la imagen se hace con esta carpeta como raiz /.
Es decir, una imagen dentro de esta carpeta se referencia /imagen.png imagen.png Una imagen en res/imagenes se referencia res/imagenes /imgenes/imagen.png /im genes/imagen.png

Las imgenes se aadirn al fichero .jar (lo hace WT) im a adir .jar

33

IU: Screen: Formularios: Imgenes


Una objeto imagen se declara y crea:
Image mimagen; mimagen=Image.createImage("/nombre.png");

Es importante crear la imagen en un try..catch por si no try..catch


se encuentra
try { // Ejemplo de imagen en formulario mimagen=Image.createImage("/nombre.png"); } catch (java.io.IOException error) { Alert alerta=new Alert("Error","No se pueda cargar la imagen",null,AlertType.ERROR); alerta.setTimeout(5000); pantalla.setCurrent(alerta); }

34

17

IU: Screen: Formularios: Imgenes


Para usarla en una alerta se pondr como 3er parmetro pondr par
en el constructor de la alerta
intro=new Alert(Titulo", Texto...",mimagen,AlertType.INFO);

Para usarla en un formulario hay que crear un


ImageItem
imagenit=new ImageItem(null,mimagen,ImageItem.LAYOUT_CENTER,"Davilin"); principal.append(imagenit);

En el siguiente ejemplo se carga una imagen en una


alerta que dura 3 segundos y despus se muestra un despu formulario con otra imagen

35

Programa: DBVImagenes

3 segs.

36

18

Programa: DBVImagenes (1/3)


import javax.microedition.midlet.*; import javax.microedition.lcdui.*; public class DBVImagenes extends MIDlet implements CommandListener { private Alert intro; private Display pantalla ; private Form principal ; private Command salir; private Image imagen2,imagen1; private ImageItem imagenit; private String cad; public DBVImagenes() { pantalla = Display.getDisplay(this); // Preparando la pantalla principal principal=new Form("Imagenes"); salir = new Command("Salir", Command.EXIT, 0); principal.addCommand(salir); principal.setCommandListener(this); ...

37

Programa: DBVImagenes (2/3)


// Creacin de la imagen try { // Ejemplo de imagen en formulario imagen2=Image.createImage("/david2.png"); imagenit=new ImageItem(null,imagen2,ImageItem.LAYOUT_CENTER,"Davilin"); principal.append(imagenit); } catch (java.io.IOException error) { Alert alerta=new Alert("Error","No se pueda cargar la imagen",null,AlertType.ERROR); alerta.setTimeout(5000); pantalla.setCurrent(alerta); } // Preparacion de la pantalla de bienvenida try { // Ejemplo de imagen en alerta imagen1=Image.createImage("/david1.png"); intro=new Alert("Bienvenido", "Bienvenido a mi programa\nCargando...",imagen1,AlertType.INFO); intro.setTimeout(3000); } catch (java.io.IOException error) { Alert alerta=new Alert("Error","No se pueda cargar la imagen",null,AlertType.ERROR); alerta.setTimeout(5000); pantalla.setCurrent(alerta); } }

38

19

Programa: DBVImagenes (3/3)


public void startApp() { pantalla.setCurrent(intro,principal); } public void pauseApp() { } public void destroyApp(boolean unconditional) { } public void commandAction(Command c, Displayable displayable) { if (c == salir) { destroyApp(false); notifyDestroyed(); } } }

39

IU: Screen:Formularios:ChoiceGroup
Permite crear botones de tipo radio y checkbox. checkbox. Hay 3 tipos
Choice.EXCLUSIVE Choice.MULTIPLE Choice.IMPLICIT Botones Radio Botones Checkbox Men

Para crear las selecciones: Para procesar elemento seleccionado en radio: Para procesar elementos seleccionados en check:
for (i=0;i<micheck.size();i++) { if (micheck.isSelected(i)){ mensaje=new StringItem("",micheck.getString(i)+"\n"); principal.append(mensaje); } } i=miradio.getSelectedIndex(); mensaje=new StringItem("",miradio.getString(i)+"\n"); miradio=new ChoiceGroup("Mi Radio",Choice.EXCLUSIVE); miradio.append("opcion1",null); // 2 parmetro es una imagen miradio.append("opcion2",null); principal.append(miradio);

40

20

Programa: DBVChoice

41

Programa: DBVChoice (1/3)


import javax.microedition.midlet.*; import javax.microedition.lcdui.*; public class DBVChoice extends MIDlet implements CommandListener { private ChoiceGroup miradio, micheck, milista; private Command procesaradio, procesacheck, salir; private Display pantalla ; private Form principal ; private String cad; public DBVChoice() { pantalla = Display.getDisplay(this); // Preparando la pantalla principal principal=new Form("Imagenes"); salir = new Command("Salir", Command.EXIT, 0); procesaradio = new Command("Ver Radio", Command.SCREEN, 0); procesacheck = new Command("Ver Check", Command.SCREEN, 0); principal.addCommand(salir); principal.addCommand(procesaradio); principal.addCommand(procesacheck); principal.setCommandListener(this); // Radio miradio=new ChoiceGroup("Mi Radio",Choice.EXCLUSIVE); miradio.append("opcion1",null); miradio.append("opcion2",null); principal.append(miradio); 42

21

Programa: DBVChoice (2/3)


// Checkbox micheck=new ChoiceGroup("Mi Check",Choice.MULTIPLE); micheck.append("check1",null); micheck.append("check2",null); principal.append(micheck);

} public void startApp() { pantalla.setCurrent(principal); } public void pauseApp() { } public void destroyApp(boolean unconditional) { } public void commandAction(Command c, Displayable displayable) { int i; StringItem mensaje; if (c == salir) { destroyApp(false); notifyDestroyed();

43

Programa: DBVChoice (3/3)


} else if (c==procesaradio) { i=miradio.getSelectedIndex(); mensaje=new StringItem("",miradio.getString(i)+"\n"); principal.append(mensaje); } else if (c==procesacheck){ for (i=0;i<micheck.size();i++) { if (micheck.isSelected(i)){ mensaje=new StringItem("",micheck.getString(i)+"\n"); principal.append(mensaje); } } }

44

22

IU: Screen:Ticker

Permite mostrar un scroll horizontal. Se puede asociar a cualquier clase derivada de Screen Para crearlo y asociarlo, por ejemplo a un formulario
cad=new String("Soy un texto que se desplaza por la pantalla"); miticker=new Ticker(cad); principal.setTicker(miticker);

Para modificar su valor


miticker.setString(Texto nuevo del ticker");

A continuacin un ejemplo que tiene ticker y un radio y continuaci

muestra en el ticker informacin adicional sobre el informaci significado del radio

45

Programa: DBVTicker

46

23

Programa: DBVTicker (1/2)


import javax.microedition.midlet.*; import javax.microedition.lcdui.*; public class DBVTicker extends MIDlet implements CommandListener, ItemStateListener { private ChoiceGroup miradio; private Command salir; private Display pantalla ; private Form principal ; private String cad; private Ticker miticker; public DBVTicker() { pantalla = Display.getDisplay(this); // Preparando el ticker cad=new String("Soy un texto que se desplaza por la pantalla"); miticker=new Ticker(cad); // Preparando la pantalla principal principal=new Form("Formulario"); principal.setTicker(miticker); // Se asocia el ticker al formulario salir = new Command("Salir", Command.EXIT, 0); principal.addCommand(salir); principal.setCommandListener(this); // Radio miradio=new ChoiceGroup("Mi Radio",Choice.EXCLUSIVE); miradio.append("opcion1",null); miradio.append("opcion2",null); principal.append(miradio); principal.setItemStateListener(this); // Listener que se llama si cambia el radio }

47

Programa: DBVTicker (2/2)


public void startApp() { pantalla.setCurrent(principal); } public void pauseApp() { } public void destroyApp(boolean unconditional) { } public void commandAction(Command c, Displayable displayable) { if (c == salir) { destroyApp(false); notifyDestroyed(); } } public void itemStateChanged(Item item) { // Listener de RadioButton int i; if (item==miradio) { i=miradio.getSelectedIndex(); if (i==0) { // Dependiendo del radio elegido se cambia en texto del ticker miticker.setString("La Opcion primera es muy buena"); } else { miticker.setString("Elegir la 2 te dara buena suerte"); } } else { miticker.setString("no se ha elegido miradio"); } } } 48

24

IU: Canvas y GameCanvas


Canvas es la clase bsica para trabajar con la pantalla a bajo nivel: b
Dibujar pixels, lineas, figuras, etc. pixels, lineas, GameCanvas mejora Canvas incluyendo carga de Imgenes, Sprites, Im Sprites, TiledLayers y un mejor control de los botones del telfono tel Estas clases son la utilizada para hacer los juegos Java que han hecho tan populares los mviles m La programacin de juegos se convierte en algo mucho ms sencillo programaci m que en cualquier otra plataforma El programador no tiene que preocuparse de problemas clsicos cl como:
Refresco de pantalla, doble buffering, colisiones, gestin de capas o buffering, gesti mapas

Las clases anteriores se encargan de todo el trabajo sucio sucio

49

IU: GameCanvas
Las aplicaciones no suelen utilizar directamente
GameCanvas, sino que heredan de esta clase GameCanvas, Como mnimo hay dos clases: Una para el midlet clases: principal y otra para la clase que hereda de GameCanvas El juego suele ejecutarse en una hebra independiente con el siguiente bucle principal
// Dentro de la clase que hereda de GameCanvas public void run() { Graphics g = getGraphics(); while (jugando == true) { colision(); // Controla colisiones leeTeclado(); // Lee acciones del usuario dibujaPantalla(g); // Dibuja la escena actual try { Thread.sleep(retraso); } // Retraso entre iteraciones catch (InterruptedException ie) {} } }

50

25

IU: GameCanvas: Lectura de teclado


Para leer de teclado es necesario leer el estado de las
teclas con:
int keyStates = getKeyStates();

Hay varias constantes en GameCanvas para cada tecla: tecla:


DOWN_PRESSED, LEFT_PRESSED, RIGHT_PRESSED, UP_PRESSED, FIRE_PRESSED, GAME_A_PRESSED, GAME_B_PRESSED, GAME_C_PRESSED, GAME_D_PRESSED

// Metodo para gestionar el teclado private void leeTeclado() { int keyStates = getKeyStates(); // Izquierda if ((keyStates & LEFT_PRESSED) != 0) { // Acciones cuando pulse izquierda } // Derecha if ((keyStates & RIGHT_PRESSED) !=0 ) { // Acciones cuando pulse izquierda } } 51

IU: GameCanvas: Dibujar en la pantalla


Suele haber un mtodo en el que se realiza todo el m
refresco de pantalla: imgenes, lineas, sprites, fondos im lineas, sprites, fondos Para hacer cualquier dibujo se utiliza un objeto Graphics que puede obtenerse dentro de GameCanvas con
Graphics g=getGraphics();

Algunos de las acciones posibles:


g.setColor(0xbbecf3); // Selecciona el color de lo siguiente que se dibuje g.fillRect(0, 0, ancho, alto); // Dibuja un rectangulo relleno con ese color g.setColor(0x0000ff); g.drawLine(0,100,200,0); // Dibuja una lnea // Para escribir un texto, se indican las coordenadas de la pantalla y la // alineacin del texto en la pantalla g.drawString(Hola", anchop, altop, Graphics.RIGHT | Graphics.BOTTOM);

52

26

IU: GameCanvas: Sprites



La clase Sprite maneja los personajes del juego Carga del Sprite en un fichero con 5 posiciones Se indica el tamao de un elemento tama
Sprite babosin; Image imagen; imagen = Image.createImage("/babosin.png"); babosin = new Sprite (image,16,24);

24

16 2 3 4

0 24

80

Fichero: babosin.png

53

IU: GameCanvas: Sprites


Para mostrar el sprite hay que seleccionar la posicin de posici
pantalla Tambin cual de los frames se va a mostrar Tambi Y cmo quiere mostrarse: Su posicin original, invertida c posici o girada en x grados

Sprite.TRANS_NONE, Sprite.TRANS_MIRROR, Sprite.TRANS_ROT90, Sprite.TRANS_ROT180, Sprite.TRANS_ROT270, Sprite.TRANS_MIRROR_ROT90, Sprite.TRANS_MIRROR_ROT180, Sprite.TRANS_MIRROR_ROT270

Para dibujar se necesita un Graphics g que puede


obtenerse con: Graphics g = getGraphics(); getGraphics();
babosin.setFrame(3); // Selecciona el frame (4 imagen de las 5) babosin.setTransform(Sprite.TRANS_NONE); // Muestra la imagen en su posicin original babosin.setPosition(100,100); // Colocar en la pantalla el sprite en la posicin (100,100) babosin.paint(g); // Dibuja el Sprite.

54

27

Programa: DBVGameCanvas
Se va a mostrar en un programa los elementos
relacionados con GameCanvas vistos hasta este punto Se dibujaran algunas lneas y rectngulos y se mover l rect mover un Sprite por la pantalla Se va a utilizar una clase para el midlet (DBVGameCanvas), que ser muy similar en todos los DBVGameCanvas), ser programas que usen GameCanvas Por otro lado, se va a utilizar una clase que hereda de GameCanvas (BabosinCanvas) sobre la que recae la BabosinCanvas) mayor parte de la accin acci Esta ltima tiene una hebra que es iniciada por la clase principal

55

Programa: DBVGameCanvas

Cursores

56

28

Programa: DBVGameCanvas (1/2)


import javax.microedition.midlet.*; import javax.microedition.lcdui.*; public class DBVGameCanvas extends MIDlet implements CommandListener { private Display display; private BabosinCanvas babosinCanvas; private Command salir; public void startApp() { try { display = Display.getDisplay(this); babosinCanvas= new BabosinCanvas(); babosinCanvas.start(); // Inicia la hebra del canvas salir = new Command("Salir", Command.EXIT, 0); // Boton para salir babosinCanvas.addCommand(salir); babosinCanvas.setCommandListener(this); display.setCurrent(babosinCanvas); } catch (Exception ex) { System.out.println(ex); } } public void pauseApp() { }

57

Programa: DBVGameCanvas (2/2)


public void destroyApp(boolean unconditional) { if (babosinCanvas != null) { babosinCanvas.stop(); // Para la hebra del canvas } } public void commandAction(Command c, Displayable s) { if (c.getCommandType() == Command.EXIT) { System.gc(); // Llama al recolector de basura destroyApp(true); notifyDestroyed(); } }

58

29

Programa: DBVGameCanvas-BabosinCanvas (1/4)


import javax.microedition.lcdui.*; import javax.microedition.lcdui.game.*; public class BabosinCanvas extends GameCanvas implements Runnable { private boolean jugando; // Indica que la partida esta en curso private long retraso; // Retraso entre cada ciclo private int babosinX, babosinY; // Coordenadas del personaje private int ancho; // Ancho de la pantalla private int alto; // Alto de la pantalla private int posbabosin; // babosin actual del personaje (0-4) private Sprite babosin; // Sprites del personaje // Constructor public BabosinCanvas() throws Exception { super(true); ancho = getWidth(); alto = getHeight(); babosinX = ancho / 2; babosinY = alto / 2; retraso = 20; // Carga el personaje principal Image image = Image.createImage("/babosin.png"); babosin = new Sprite (image,16,24); }

59

Programa: DBVGameCanvas-BabosinCanvas (2/4)


// Crea y arranca la hebra del juego public void start() { jugando = true; Thread t = new Thread(this); t.start(); } public void stop() { jugando = false; } // Bucle principal del juego public void run() { Graphics g = getGraphics(); while (jugando == true) { leeTeclado(); // Lee acciones del usuario dibujaPantalla(g); // Dibuja la escena actual try { Thread.sleep(retraso); } catch (InterruptedException ie) {} } }

60

30

Programa: DBVGameCanvas-BabosinCanvas (3/4)


// Metodo para gestionar el teclado private void leeTeclado() { int keyStates = getKeyStates(); if ((keyStates & LEFT_PRESSED) != 0) {// Izquierda babosinX = Math.max(0, babosinX - 1); posbabosin=(posbabosin+1)%5; babosin.setFrame(posbabosin); babosin.setTransform(Sprite.TRANS_NONE); } if ((keyStates & RIGHT_PRESSED) !=0 ) {// Derecha babosinX = Math.min(ancho-16, babosinX + 1); posbabosin=(posbabosin+1)%5; babosin.setFrame(posbabosin); babosin.setTransform(Sprite.TRANS_MIRROR); } if ((keyStates & UP_PRESSED) != 0) {// Arriba babosinY = Math.max(0, babosinY - 1); babosin.setFrame(0); } if ((keyStates & DOWN_PRESSED) !=0) {// Abajo babosinY = Math.min(alto-24,babosinY + 1); babosin.setFrame(4); } } 61

Programa: DBVGameCanvas-BabosinCanvas (4/4)


// Dibuja la pantalla private void dibujaPantalla(Graphics g) { // lineas montaas g.setColor(0xbbecf3); g.fillRect(0, 0, getWidth(), getHeight()); g.setColor(0x0000ff); g.drawLine(0,getHeight()/2,getWidth()/2,0); g.drawLine(getWidth()/2,0,getWidth(),getHeight()/2); g.setColor(0xf5d58d); g.drawLine(0,(getHeight()/4)*3,getWidth(),(getHeight()/4)*3); // dibuja el personaje babosin.setPosition(babosinX,babosinY); babosin.paint(g); } } flushGraphics(); // actualiza la pantalla

62

31

IU: GameCanvas: TiledLayer

Deco.png

Image tileImages = Image.createImage("/deco.png"); // Carga la imagen con los elementos de la pantalla TiledLayer decorado = new TiledLayer(40,24,tileImages,8,8); // reserva espacio para la capa del decorado // Selecciona los 40x24 elementos del decorado segn su posicin en deco.png // 0 indica que no hay nada en esa posicin int[] map= {42,41,42,41,1,2,42,41,1,2,42,41,1,2,42,41,1,2,42,41,1,2,42,41,1,2,42,41,1,2,42,41,1,2,42,41,42,41,1,2, 264,264,264,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,264, 264,264,264,0,0,248,249,250,251,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,264, } // Guarda los elementos del mapa en la posicin de pantalla que corresponda for (int i=0; i < mapa.length; i++) { int columna = i % 40; // Se divide por el nmero de elementos de una fila=numero de columnas int fila = i/40; decorado.setCell(columna,fila,mapa[i]); // Actualiza 1 a 1 todas las celdas }

63

IU: GameCanvas: TiledLayer


Para mover un TiledLayer se utiliza setPosition
decorado.setPosition(decox,decoy);

Para dibujarlo se puede utilizar el mtodo paint de m


private LayerManager controlcapas; // Declaracin del LayerManager controlcapas=new LayerManager(); // Crea el control de capas controlcapas.append(decorado); // Aade cada capa que se quiera controlar Controlcapas.paint(g,0,0); // Dibuja todas las capas controladas a partir de (x,y) en la pantalla

TiledLayer o un LayerManager que gestiona todas las capas

64

32

IU: GameCanvas: TiledLayer+Sprite+Image

+ +

=
// Dibuja la imagen de fondo g.drawImage(fondo,decox/4,decoy/4,0); decorado.setPosition(decox,decoy); // Actualiza el decorado controlcapas.paint(g,0,0); // Pinta el decorado // Actualiza el personaje babosin.setPosition(babosinX,babosinY); babosin.paint(g); // pinta el personaje 65

IU: GameCanvas: Scroll Fondos


TRUCO En muchos juegos de plataformas los escenarios pueden estar a diferentes distancias Los escenarios ms lejanos deben moverse a menor m velocidad que los cercanos para producir un movimiento real Es fcil conseguir ese efecto dndole al primer plano f d unas coordenadas (x,y) y a cada plano ms lejano se le (x,y) m asignar un (x/distancia,y/distancia) asignar (x/distancia,y/distancia) En el ejemplo anterior el fondo se desplaza 4 veces ms m lentamente que el decorado principal
// Dibuja la imagen de fondo g.drawImage(fondo,decox/4,decoy/4,0);

66

33

IU: GameCanvas: Colisiones


Se puede mirar en cada momento si un Sprite choca con
otro Sprite, Imagen o TiledLayer Las colisiones se pueden hacer a nivel de pixel (pixelLevel=true) o aproximando la imagen a un pixelLevel=true) rectangulo (pixelLevel=false) pixelLevel=false)
// Mira si el sprite babosin choca con la imagen situada en x,y choca=babosin.collidesWith(imagen,x,y,pixelLevel); // Mira si el sprite babosin choca con la otro Sprite choca=babosin.collidesWith(enemigo,pixelLevel); // Mira si el sprite babosin choca con un tiledLayer choca=babosin.collidesWith(escenario,pixelLevel);

67

Programa: DBVBabosin
En el siguiente programa se combina todo lo relacionado
con GameCanvas: Sprites, Imgenes, TiledLayer, GameCanvas: Sprites, Im TiledLayer, LayerManager, Control de Teclado LayerManager, Teclado Con esto se podra hacer prcticamente cualquier juego podr pr en 2D Se va a utilizar para el midlet la misma clase que en (DBVGameCanvas) DBVGameCanvas) Por otro lado, se va a utilizar una clase que hereda de GameCanvas (BabosinCanvas) en la que se desarrolla el BabosinCanvas) juego El programa carga una imagen de fondo, un tiledLayer y un sprite y cuando se mueven los cursores, el sprite se desplaza por el fondo que tambin se desplaza, tambi detectando posibles colisiones
68

34

Programa: DBVBabosin

Con los cursores se desplaza el personaje, el escenario y el fondo

69

Programa: DBVBabosin (1/6)


import javax.microedition.lcdui.*; import javax.microedition.lcdui.game.*; public class BabosinCanvas extends GameCanvas implements Runnable { private boolean jugando; // Indica que la partida esta en curso private long retraso; // Retraso entre cada ciclo private int babosinX, babosinY; // Coordenadas del personaje private int antx,anty; // Coord. anterior del personaje (para colisiones) private int decox,decoy; // Coordenadas del decorado private int antdecox,antdecoy; private int ancho; // Ancho de la pantalla private int alto; // Alto de la pantalla private int posbabosin; // sprite actual del personaje (0-4) private LayerManager controlcapas; private int ultmov; // Ultimo movimiento: 0 nada 1 izq 2 dch 3 arr 4 aba private TiledLayer decorado; // Escenario private boolean cayendo=true; private Image fondo; private Sprite babosin; // Sprite del personaje principal

70

35

Programa: DBVBabosin (2/6)


// Constructor public BabosinCanvas() throws Exception { // Llama al constructor de GameCanvas, al ser true, desabilita // el manejo estandar del teclado super(true); // Lee las coordedanas del dispositivo ancho = getWidth(); alto = getHeight(); // Coloca el mueco en una posicin que no choque babosinX = 100; babosinY = 30; // Inicializa las coordenadas del decorado a la esquina sup,izq de la pantalla decox=0; decoy=0; // inicializa coordenadas anteriores (para deshacer movimientos si choca) antdecox=decox; antdecoy=decoy; antx=babosinX; anty=babosinY; ultmov=0; retraso = 5; decorado=iniDecorado(); // Carga e inicializa el decorado fondo= Image.createImage("/fondo2.png"); // Carga imagen de fondo controlcapas=new LayerManager(); // Crea el control de capas controlcapas.append(decorado); Image image = Image.createImage("/babosin.png"); // Carga el personaje principal babosin = new Sprite (image,16,24); } // Fin del constructor 71

Programa: DBVBabosin (3/6)


// Controla las colisiones private void colision() { if (!babosin.collidesWith(decorado, false)) { // Si babosin colisiona con el decorado se vuelve a su estado anterior decox=antdecox;decoy=antdecoy; babosinX=antx; babosinY=anty; } } // Dibuja todo private void dibujaPantalla(Graphics g) { g.setColor(0xffffff); // Dibuja un fondo blanco g.fillRect(0, 0, getWidth(), getHeight()); g.drawImage(fondo,decox/4,decoy/4,0); // Dibuja la imagen de fondo decorado.setPosition(decox,decoy); // Actualiza el decorado controlcapas.paint(g,0,0); // Pinta el decorado babosin.setPosition(babosinX,babosinY); // Actualiza el personaje babosin.paint(g); // pinta el personaje g.setColor(0x000000); // Pone el color a negro if (babosin.collidesWith(decorado, true)) {// Texto que indica si choca o no g.drawString("CHOCA", ancho, alto, Graphics.RIGHT | Graphics.BOTTOM); } else { g.drawString("nochoca", ancho, alto, Graphics.RIGHT | Graphics.BOTTOM); } // refresca los graficos flushGraphics(); }

72

36

Programa: DBVBabosin (4/6)


// Inicializa el decorado que es un TiledLayer private TiledLayer iniDecorado() throws Exception { // Carga la imagen con los elementos de la pantalla Image tileImages = Image.createImage("/deco.png"); // reserva espacio para la capa del decorado TiledLayer tiledLayer = new TiledLayer(40,24,tileImages,8,8); // Selecciona los 40x24 elementos del decorado segun su posicion den deco.png // 0 indica que no hay nada en esa posicion int[] mapa= { 42,41,42,41,1,2,42,41,1,2,42,41,1,2,42,41,1,2,42,41,1,2,42,41,1,2,42,41,1,2,42,41,1,2,42,41,42,41,1,2, 264,264,264,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,264, 264,264,264,0,0,248,249,250,251,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,264, }; // Guarda los elementos del mapa en la posicion de pantalla que corresponda for (int i=0; i < mapa.length; i++) { int columna = i % 40; int fila = i/40; tiledLayer.setCell(columna,fila,mapa[i]); // Actualiza 1 a 1 todas las celdas } return tiledLayer;

73

Programa: DBVBabosin (5/6)


// Maneja la entrada de teclado private void leeTeclado() { int estadoTeclado; // se guardan los valores para restaurar si choca antdecox=decox; antdecoy=decoy; antx=babosinX; anty=babosinY; estadoTeclado = getKeyStates(); // Lee el estado del teclado babosin.setFrame(0); // selecciona el 1er sprite de babosin // Mira si se ha movido a la Izquierda if ( (estadoTeclado & LEFT_PRESSED) != 0) { //mueve a la izquierda el decorado y babosin decox+=1; babosinX = Math.max(0, babosinX - 1); // Cambia el sprite de babosin tambien posible con babosin.nextFrame() posbabosin=(posbabosin+1)%5; babosin.setFrame(posbabosin); babosin.setTransform(Sprite.TRANS_NONE); ultmov=1; } // Derecha if ( (estadoTeclado & RIGHT_PRESSED) !=0 ) { // Igual que izquierda salvo // babosin.setTransform(Sprite.TRANS_MIRROR); } } 74

37

Programa: DBVBabosin (6/6)


// Bucle principal del juego public void run() { Graphics g = getGraphics(); while (jugando == true) { colision(); // Controla colisiones leeTeclado(); // Lee acciones del usuario dibujaPantalla(g); // Dibuja la escena actual try { Thread.sleep(retraso); } catch (InterruptedException ie) {} } } // Crea y arranca la hebra del juego public void start() { Thread t; jugando = true; t= new Thread(this); t.start(); } // para la ejecucion public void stop() { jugando = false; }

75

RMS (Record Management System)



El almacenamiento en J2ME se realiza a travs de RMS trav No existen ficheros RMS permite guardar registros numerados El contenido de un registro es un array de bytes La gestin de todo lo que haya en el registro debe hacerla el gesti usuario.
Por ejemplo, si se guarda una cadena y un nmero ser el usuario el n ser encargado de escribirlo y leerlo correctamente convirtiendo los datos a arrays de bytes

La clase RecordStore es la encargada de la manipulacin de los manipulaci


registros
Id registro 1 2 contenido valor1

76

38

RMS: RecordStore
RecordStore permite realizar operaciones con los
registros del tipo: Crear, Insertar, Borrar, ... Todas las operaciones que se realizan con RecordStore necesitan estar en un try..catch try..catch Para crear o abrir:

RecordStore recordstore; // Declaracin try { // Abre un registro llamado contador y lo crea si es necesario (2 parametro a true) recordstore = RecordStore.openRecordStore("contador", true ); } catch (Exception error) { alert = new Alert("Error Creando", error.toString(), null, AlertType.WARNING); alert.setTimeout(Alert.FOREVER); display.setCurrent(alert); }

En adelante se pondrn las sentencias sin el try aunque pondr


debe estar
77

RMS: RecordStore: Escritura Simple


El caso ms simple de registros es aquel en el que se m
escribe un nico tipo de datos Para escribir un dato, por ejemplo, un String hay que convertirlo a un array de bytes Despus se aade con addRecord: Despu a addRecord:

String outputData = "1"; // Cadena que se va a escribir byte[] byteOutputData = outputData.getBytes(); // Conversin de la cadena // Se aade la array de bytes al registro desde el inicio (0) y con longitud (length) recordstore.addRecord(byteOutputData, 0, byteOutputData.length);

78

39

RMS: RecordStore: Lectura Simple


Para leer se utiliza getRecord que necesita como mnimo m
el nmero de registro a leer aunque tiene varias n versiones Puede ser necesario saber cuantos registros hay en el RecordStore, puede consultarse con getNumRecords RecordStore, Por ejemplo para leer todas las cadenas almacenadas en el RecordStore: RecordStore:

// Crea un array de bytes para leer los datos byte[] byteInputData = new byte[30]; int length = 0; // Almacenar el nmero de bytes leidos String cadena=new String(""); // Bucle para los todos los registros que haya (getNumRecords) for (int x = 1; x <= recordstore.getNumRecords(); x++) { // Lee el registro de la posicin x en el array de bytes al inicio (0) length = recordstore.getRecord(x, byteInputData, 0); cadena=cadena + " "+ new String(byteInputData); } 79

RMS: RecordStore: Borrado y Cierre


Para cerrar el RecordStore y dejar de usarlo Para borrar todo el RecordStore (mtodo static) (m static)
RecordStore.deleteRecordStore("contador"); recordstore.closeRecordStore();

Para borrar un registro concreto, se indica su posicin posici


recordstore.deleteRecord(3);

80

40

RMS: RecordStore: Emulador


En el Wireless Toolkit puede accederse a los RecordStore que se
almacenan en:
C:\WTK22\appdb\

Para cada telfono emulado hay una carpeta con su nombre, por tel
ejemplo para el DefaultColorPhone
C:\WTK22\appdb\DefaultColorPhone

Cada recordset es precedido por run_by_class_storage_ run_by_class_storage_ Es decir si tenemos un RecordStore llamado contador, que se ha
usado en el telfono por defecto se encontrar en: tel encontrar
C:\WTK22\appdb\DefaultColorPhone\run_by_class_storage_contador.db

Este fichero binario puede visualizarse con un editor hexadecimal o


borrarse si la aplicacin empieza a dar problemillas ;-) aplicaci ;-

81

Programa: DBVRMSSimple
Para probar los elementos bsicos de registros se va a b
mostrar el programa DBVRMSSimple Este programa crea un RecordStore llamado contador en el que la primera vez escribe la cadena 1 Y posteriormente escribe 2, 3, ... Dispone de un men que permite Crear, Insertar, Ver, men Borrar y Salir

82

41

Programa: DBVRMSSimple

Crear Incrementar Incrementar Ver

Salir

83

Programa: DBVRMSimple (1/5)


import javax.microedition.rms.*; import javax.microedition.midlet.*; import javax.microedition.lcdui.*; import java.io.*; import java.lang.Integer; public class DBVRMSSimple extends MIDlet implements CommandListener { private Display display; private Alert alert; private Form form; private Command salir,crear,ver,incrementar,borrar; private RecordStore recordstore = null; public DBVRMSSimple() { display = Display.getDisplay(this); salir = new Command("Salir", Command.SCREEN,4); // Definicin del men incrementar = new Command("Incrementar", Command.SCREEN, 2); crear=new Command("Crear", Command.SCREEN, 1); ver=new Command("Ver",Command.SCREEN,3); borrar=new Command("Borrar",Command.SCREEN,3); form = new Form("Record"); form.addCommand(salir); form.addCommand(crear); form.addCommand(incrementar); form.addCommand(ver); form.addCommand(borrar); form.setCommandListener(this); }

84

42

Programa: DBVRMSimple (2/5)


public void startApp() { display.setCurrent(form); } public void pauseApp() { } public void destroyApp( boolean unconditional ) { } public void commandAction(Command command, Displayable displayable) { // Para cada opcin del men se realiza una accin sobre el RecordSet if (command == salir) {// Para cerrar el RecordStore try { recordstore.closeRecordStore(); } catch (Exception error) { alert = new Alert("Error Cerrando", error.toString(), null, AlertType.WARNING); alert.setTimeout(Alert.FOREVER); display.setCurrent(alert); } destroyApp(true); notifyDestroyed(); } else if (command==crear) {// Para crear el RecordStore e insertar el valor 1 try { recordstore = RecordStore.openRecordStore("contador", true ); } catch (Exception error) { alert = new Alert("Error Creando", error.toString(), null, AlertType.WARNING); alert.setTimeout(Alert.FOREVER); display.setCurrent(alert); }

85

Programa: DBVRMSimple (3/5)


try { String outputData = "1"; byte[] byteOutputData = outputData.getBytes(); recordstore.addRecord(byteOutputData, 0, byteOutputData.length); } catch ( Exception error) { alert = new Alert("Error Escribiendo 1", error.toString(), null, AlertType.WARNING); alert.setTimeout(Alert.FOREVER); display.setCurrent(alert); } } else if (command == incrementar) {// Para aadir nuevos valores try { // Se mira cuantos elementos hay y se guarda ese valor+1 en el RecordStore String outputData = (new Integer(recordstore.getNumRecords()+1)).toString(); byte[] byteOutputData = outputData.getBytes(); recordstore.addRecord(byteOutputData, 0, byteOutputData.length); } catch ( Exception error) { alert = new Alert("Error Escribiendo", error.toString(), null, AlertType.WARNING); alert.setTimeout(Alert.FOREVER); display.setCurrent(alert); } } else if (command == ver) { // Muestra todos los registros 86

43

Programa: DBVRMSimple (4/5)


try { byte[] byteInputData = new byte[30]; int length = 0; String titulo=null; String cadena=new String(""); for (int x = 1; x <= recordstore.getNumRecords(); x++) { length = recordstore.getRecord(x, byteInputData, 0); titulo="Leyendo" + (new Integer(x)).toString(); cadena=cadena + " "+ new String(byteInputData); } // Se muestra el resultado en un alert alert = new Alert(titulo, cadena, null, AlertType.WARNING); alert.setTimeout(Alert.FOREVER); display.setCurrent(alert); } catch (Exception error) { alert = new Alert("Error Leyendo", error.toString(), null, AlertType.WARNING); alert.setTimeout(Alert.FOREVER); display.setCurrent(alert); }

87

Programa: DBVRMSimple (5/5)


else if (command == borrar) { // Elimina el registro completo if (RecordStore.listRecordStores() != null) { try { RecordStore.deleteRecordStore("contador"); } catch (Exception error) { alert = new Alert("Error Borrando", error.toString(), null, AlertType.WARNING); alert.setTimeout(Alert.FOREVER); display.setCurrent(alert); } }

88

44

RMS: Datos complejos


Si se quieren guardar en un Registro datos compuestos
la mejor forma es crear para escritura: escritura:

Y el simtrico para lectura sim


ByteArrayInputStream

un ByteArrayOutputStream DataOutputStream DataInputStream

Estas estructuras permiten almacenar datos de distintos

tipos La clase DataOutputStream tiene mtodos para escribir todo tipo de elementos: elementos:
boolean Byte Float Int String writeBoolean writeByte writeFloat writeInt writeUTF
89

RMS: Escritura de datos complejos


Si se quiere por ejemplo escribir un nmero y un String
// Creacin de variables necesarias byte[] outputData; ByteArrayOutputStream outputStream=new ByteArrayOutputStream(); DataOutputStream outputDataStream=new DataOutputStream(outputStream); outputDataStream.writeInt(numero); // Escritura del nmero outputDataStream.writeUTF(nombre); // Escritura del nombre outputDataStream.flush(); // Enviar los datos al flujo outputData=outputStream.toByteArray(); // Convierte los datos a un array de bytes recordstore.addRecord(outputData, 0, outputData.length); // Escribe los datos en el registro outputDataStream.close(); outputStream.close();

90

45

RMS: Lectura de datos complejos


Si se quiere leer un nmero y un String n
// Creacin de variables necesarias byte[] byteInputData = new byte[30]; ByteArrayInputStream inputStream; DataInputStream inputDataStream; inputStream=new ByteArrayInputStream(byteInputData); // Crea el ByteArray inputDataStream=new DataInputStream(inputStream); // Crea el DataInputStream int length = records.getRecord(i, byteInputData, 0); // Lee el registro i-esimo numero= inputDataStream.readInt(); // Lee el nmero cadena= inputDataStream.readUTF()); // Lee la cadena inputStream.reset(); // Limpia el buffer para poder seguir leyendo ms registros

El resto de las operaciones de creacin y borrado son creaci


iguales que para el caso de datos simples A continuacin un ejemplo en el que se aaden pares continuaci a (nombre, puntos) a una lista de records
91

Programa: DBVRMSRecords

Insertar Listado

Salir 92

46

Programa: DBVRMSRecords (1/5)


import javax.microedition.rms.*; import javax.microedition.midlet.*; import javax.microedition.lcdui.*; import java.io.*; public class DBVRMSRecords extends MIDlet implements CommandListener { private Alert alert; private Command salir,listado,nuevorecord, insertar, eliminar; private Display pantalla; private Form principal,frecord; private TextField fnombre,fpuntos; private RecordStore records = null; public DBVRMSRecords() { pantalla = Display.getDisplay(this); // Preparacion de la pantalla para poner records frecord=new Form("Nuevo Record"); fnombre=new TextField("Nombre:","",30,TextField.ANY); fpuntos=new TextField("Puntos:","",30,TextField.NUMERIC); insertar=new Command("Insertar", Command.SCREEN,0); frecord.append(fnombre); frecord.append(fpuntos); frecord.addCommand(insertar); frecord.setCommandListener(this); // Preparando la pantalla principal principal=new Form("Administracion"); salir = new Command("Salir", Command.EXIT, 0); nuevorecord = new Command("Nuevo Record", Command.SCREEN, 0); listado = new Command("Listado", Command.SCREEN, 0); eliminar=new Command("Eliminar Todo", Command.SCREEN,0); 93

Programa: DBVRMSRecords (2/5)


principal.addCommand(salir); principal.addCommand(nuevorecord); principal.addCommand(listado); principal.addCommand(eliminar); principal.setCommandListener(this);

} public void startApp() { cargarRecords(); mostrarRecords(); pantalla.setCurrent(alert,principal); } public void pauseApp() { } public void destroyApp( boolean unconditional ) { } public void commandAction(Command command, Displayable pantallaable) { if (command == salir) { // Accin para terminar if (records!=null) { cerrarRecords(); } destroyApp(true); notifyDestroyed(); } else if (command==nuevorecord) {// Aadir un nuevo record pantalla.setCurrent(frecord); } else if (command==listado) { // Ver todos los records mostrarRecords(); 94

47

Programa: DBVRMSRecords (3/5)


} else if (command==eliminar) { // Borrar todos los registros if (records!=null) { cerrarRecords(); } eliminarRegistros(); } else if (command==insertar) { // Aadir un nuevo registro desde el formulario guardarRecords(Integer.parseInt(fpuntos.getString()),fnombre.getString()); pantalla.setCurrent(principal); } } public void cargarRecords() { // Abre el RecordStore de los records o lo crea si no existe try { records = RecordStore.openRecordStore("records", true ); } catch (Exception error) { alert = new Alert("Error Creando", error.toString(), null, AlertType.WARNING); alert.setTimeout(Alert.FOREVER); pantalla.setCurrent(alert); } } public void cerrarRecords() { // Cierra el RecordStore try { records.closeRecordStore(); } catch (Exception error) { alert = new Alert("Error Cerrando", error.toString(), null, AlertType.WARNING); alert.setTimeout(Alert.FOREVER); pantalla.setCurrent(alert); } } 95

Programa: DBVRMSRecords (4/5)


public void eliminarRegistros() {// Borrar todos los registros try { RecordStore.deleteRecordStore("records"); } catch (Exception error) { alert = new Alert("Error Borrando...", error.toString(), null, AlertType.WARNING); alert.setTimeout(Alert.FOREVER); pantalla.setCurrent(alert); } } public void guardarRecords(int numero,String nombre) {// Aadir un nuevo registro try { byte[] outputData; ByteArrayOutputStream outputStream=new ByteArrayOutputStream(); DataOutputStream outputDataStream=new DataOutputStream(outputStream); if (records==null) { cargarRecords(); } outputDataStream.writeInt(numero); outputDataStream.writeUTF(nombre); outputDataStream.flush(); outputData=outputStream.toByteArray(); records.addRecord(outputData, 0, outputData.length); outputDataStream.close(); outputStream.close(); } catch ( Exception error) { alert = new Alert("Error Escribiendo 1", error.toString(), null, AlertType.WARNING); alert.setTimeout(Alert.FOREVER); pantalla.setCurrent(alert); } }

96

48

Programa: DBVRMSRecords (5/5)


public void mostrarRecords() {// Ver todos los records StringBuffer buffer=new StringBuffer(); byte[] byteInputData = new byte[30]; int puntos; String nombre; ByteArrayInputStream inputStream; DataInputStream inputDataStream; try { if (records==null) { cargarRecords(); } inputStream=new ByteArrayInputStream(byteInputData); inputDataStream=new DataInputStream(inputStream); buffer.append("Registros: " + records.getNumRecords()); for(int i=1;i<=records.getNumRecords();i++) { int length = records.getRecord(i, byteInputData, 0); buffer.append("\n" + inputDataStream.readInt() + " "+ inputDataStream.readUTF()); inputStream.reset(); } alert = new Alert("Records", buffer.toString(), null, AlertType.WARNING); alert.setTimeout(Alert.FOREVER); pantalla.setCurrent(alert); } catch (Exception error) { alert = new Alert("Error Leyendo", error.toString(), null, AlertType.WARNING); alert.setTimeout(3000); pantalla.setCurrent(alert); } } }

97

Problema: Versiones de Prueba


Cuando se quiere entregar una muestra de un programa
antes de venderlo hay varias opciones:
Limitar opciones Fecha lmite de uso l Nmero limitado de ejecuciones

Se pide utilizando RMS hacer una aplicacin que slo aplicaci s


pueda ejecutarse 5 veces
Cada vez que se ejecuta debe decirnos cuantas pruebas nos quedan

Puede ser necesario otro programa que inicialice o


modifique el nmero de evaluaciones posibles n

98

49

Comunicaciones HTTP
J2ME permite hacer conexiones por HTTP Esto permite hacer cualquier tipo de aplicacin en la que aplicaci
el dispositivo mvil ser el cliente m ser Lo nico que hay que hacer es definir un protocolo propio para interpretar los mensajes entre el cliente y el servidor Lo ms sencillo es que el servidor devuelva texto plano m Por ejemplo, el telfono pide por el mtodo get la lista tel m de citas del da, y el servidor las devuelve: d
Cliente (Telfono abre esta direccin)

El servidor devuelve texto plano

http://miservidor.es/citas.jsp?idusuario=bueno&fecha=hoy

Citas para hoy: 9:00-14:00 Curso de J2ME 16:00-20:00 Examen 1Teleco

99

Comunicaciones HTTP: Servidor


El servidor podr estar programado en cualquier podr
lenguaje que permita conexin http: conexi
CGI ASP Java: Servlets o JSP PHP, etc.

Como ejemplo se ver 2 aplicaciones del servidor que ver


devuelven texto plano: Hola Mundo, una con Servlets y plano: Mundo servlet otra en php import javax.servlet.http.*;
php import javax.servlet.*; import java.io.*; public class HitServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String message = "Hola Mundo"; response.setContentType("text/plain"); response.setContentLength(message.length()); PrintWriter out = response.getWriter(); out.println(message); } } 100

<?php // Enviaremos un texto plano header('Content-type: text/plain'); echo ("hola mundo"); jsp ?> <% response.setContentType("text/plain");%> <%=Hola Mundo%>

50

Comunicaciones HTTP: Cliente J2ME


Para no bloquear la ejecucin, las conexiones deben ejecuci
realizarse en una hebra independiente Se utiliza un objeto HttpConnection con la url y los parmetros del programa servidor par

HttpConnection conexion=(HttpConnection) Connector.open("http://localhost/j2mehola.php");

Los datos se leen en un array de bytes que podr podr


procesarse a voluntad, igual que en RMS voluntad,
InputStream entrada=null; int longitud; byte[] texto; String cadena; entrada=conexion.openInputStream(); longitud=(int)conexion.getLength(); if (longitud==-1) { // A veces la longitud se lee incorrectamente longitud=255; } texto=new byte[longitud]; // Reserva array de bytes longitud=entrada.read(texto); entrada.close(); // Cierra el flujo de entrada conexion.close(); // Cierra la conexin cadena=new String(texto,0,longitud); // Convierte el array de bytes a String 101

Programa: DBVHTTPHolaMundo
La luz verde Indica conexin Web

102

51

Programa: DBVHTTPHolaMundo (1/3)


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

public class DBVHTTPHolaMundo extends MIDlet implements CommandListener, Runnable { private Alert alert; private Command salir,conectar; private Display pantalla; private Form principal; private TextField ftexto; public DBVHTTPHolaMundo() { principal=new Form("Conexion HTTP"); // Preparacion de la pantalla principal ftexto=new TextField("Texto Leido:","",30,TextField.ANY); conectar=new Command("Conectar", Command.SCREEN,0); salir = new Command("Salir", Command.EXIT, 0); principal.append(ftexto); principal.addCommand(conectar); principal.addCommand(salir); principal.setCommandListener(this); } public void startApp() { pantalla = Display.getDisplay(this); pantalla.setCurrent(principal); ftexto.setString("Pulse conectar..."); } public void pauseApp() { }

103

Programa: DBVHTTPHolaMundo (2/3)


public void destroyApp( boolean unconditional ) { } public void commandAction(Command command, Displayable pantallaable) { if (command == salir) { destroyApp(true); notifyDestroyed(); } else if (command==conectar) { Thread t=new Thread(this); // Inicia la hebra de conexin t.start(); } } public void conectar() { HttpConnection conexion=null; InputStream entrada=null; int longitud; byte[] texto; String cadena; try { ftexto.setString("Conectando..."); conexion=(HttpConnection) Connector.open("http://localhost/j2mehola.php"); //conexion.setRequestProperty("Connection","close"); ftexto.setString("Abriendo..."); entrada=conexion.openInputStream(); longitud=(int)conexion.getLength(); if (longitud==-1) { longitud=255; } 104

52

Programa: DBVHTTPHolaMundo (3/3)


texto=new byte[longitud]; ftexto.setString("Leyendo..."); longitud=entrada.read(texto); ftexto.setString("Cerrando..."); entrada.close(); conexion.close(); cadena=new String(texto,0,longitud); ftexto.setString(cadena); // Modifica el cuadro de texto con el texto recibido } catch (Exception error) { alert = new Alert("Error Conectando", error.toString(), null, AlertType.WARNING); alert.setTimeout(Alert.FOREVER); pantalla.setCurrent(alert); }

} public void run() { // Inicio de la hebra conectar(); }

105

Curiosidades
Para hacer vibrar el telfono a partir de MIDP 2.0 tel Para probar estas caractersticas se va a mostrar un caracter
Display.vibrate(100) .- Tiempo en Milisegundos Display.vibrate(100) . Display.flashBacklight(tiempo).- Enciende la luz del telfono Display.flashBacklight(tiempo).tel

programa que permitir usar el telfono para dar permitir tel masajes o como una linterna :-) :En el emulador la vibracin se muestra con un zumbido vibraci La luz de fondo se muestra con un marco de color No todos los telfonos permiten controlar la luz y el tel vibrador

106

53

Programa: DBVMasaje

zumbido

107

Programa: DBVMasaje
import javax.microedition.midlet.*; import javax.microedition.lcdui.*; public class DBVMasaje extends MIDlet implements CommandListener { private Display pantalla ; private TextBox tintro,tayuda ; private Command salir, masaje, linterna; public DBVMasaje(){ pantalla = Display.getDisplay(this); // Preparando la pantalla principal tintro = new TextBox("Mi linterna mgica", "Elije un masaje o una linterna", 40, 0); salir = new Command("Salir", Command.EXIT, 0); masaje = new Command("Masaje",Command.HELP,1); linterna= new Command("Linterna",Command.SCREEN,1); tintro .addCommand(salir); tintro.addCommand(masaje);tintro.addCommand(linterna); tintro.setCommandListener(this); } public void startApp() {pantalla .setCurrent(tintro); } public void pauseApp() { } public void destroyApp(boolean unconditional) { } public void commandAction(Command c, Displayable displayable) { if (c == salir) { destroyApp(false); notifyDestroyed(); } else if (c==linterna) { pantalla.flashBacklight(3000); // Enciende la luz 3 segundos } else if (c==masaje) { pantalla.vibrate(3000); // Activa la vibracin 3 segundos } } }

108

54

Sonidos
Tonos en la clase Manager
playTone(int nota, int duracion, int volumen)

Las notas se asocian igual que en un midi, cada tecla del midi,
piano es una nota C(60-440Hz)C#(61)D(62)D#(63)E(64)F(65)F#(66) C(60G(67)G#(68)A(69) Volumen mximo=100 m
Manager.playTone(60,1000,100)

109

Para ampliar
Servicios Web (jsr172) Bluetooth/OBEX (jsr82)

Grficos 3D (jsr184) Gr Sonidos y Msica. MMAPI(Mobile Media API-jsr135) sica. API Uso de push para iniciar aplicaciones desde un servidor
en el movil RecordEnumeration
Permite ordenar y filtrar los registros de un RecordStore

Para probar los ejemplos bluetooth es necesario en ktoolbar: ktoolbar: Edit Preferences Security Security Domain=trusted

Location (jsr179) Localizacin geogrfica (CLDC 1.1) Localizaci geogr Cada especificacin jsrXYZ se puede encontrar en:
http://jcp.org/en/jsr/detail?id=XYZ
110

55

Referencias
Jonathan Knudsen, Wireless Java: Developing with J2ME, 2nd edition. J2ME James Keogh, The Complete Reference: J2ME, Ed. Osborne, 2003. J2ME Jason Lam, J2ME & Gaming, 2004. Gaming
http://www.jasonlam604.com

Libros

Ed. APress, 2003. APress,

Artculos Art Qusay H. Mahmoud, Wireless Application Programming with J2ME and Mahmoud, Bluetooth, 2003 Bluetooth

Jonathan Knudsen, Creating 2D Action Games with the Game API, API
2003. http://developers.sun.com/techtopics/mobility/midp/articles/game/ http://developers.sun.com/techtopics/mobility/midp/articles/game/ Webs de Inters Inter Forum Nokia. http://www.forum.nokia.com/ http://www.forum.nokia.com/ Java en sun. http://java.sun.com/

http://developers.sun.com/techtopics/mobility/midp/articles/bluetooth1/ y /bluetooth2/ http://developers.sun.com/techtopics/mobility/midp/articles/bluetooth1/

111

Curiosidades
Para hacer vibrar el telfono a partir de MIDP 2.0 tel
display.vibrate(100) .- Tiempo en Milisegundos display.vibrate(100) . Display.flashBacklight(tiempo).- Enciende la luz del telfono Display.flashBacklight(tiempo).tel

112

56

Вам также может понравиться