10. Universidad de DeustoUniversidad de Deusto
. . . . . . . . .
Configuraciones/Perfiles
• MIDP (Mobile
Information Device
Profile).
• Dentro de CLDC
• Dirigido a
dispositivos móviles
(combinación
CLDC/MIDP).
10
12. J2ME
Universidad de Deusto
• CLDC: funcionalidades
independientes del
dispositivo (librerías
generales y de
comunicación).
• MIDP: funcionalidades
específicas (GUI,
comunicación ampliada,
almacenamiento
persistente)
12
MIDP (Mobile Information Device
Profile)
13. MIDP (Mobile Information Device
Profile)
Dos versiones: 1.0 y 2.0
La v2.0 introduce
APIs específicas para juegos
Reproducción de sonidos
Criptografía y comunicaciones seguras
(HTTPS, SSL)
Mejoras en los “forms”
13
16. Fragmentacion
1) Problemas con las implementaciones MIDP
• El estándar no es muy preciso por lo que el
comportamiento depende del móvil
2) Diferencias entre dispositivos
• Maximo tamaño de aplicación admitido
• Cantidad de memoria disponible
• Cantidad de almacenamiento (RMS) disponible
• Tamaño de pantalla y profundidad de color
• Modo de navegacion (teclado, QWERTY, stylus)
• APIs disponibles.
16
18. Estandarizacion
JTWI y MSA
18
MSA: Mobile Service Architecture
• Es el JSR 248 que engloba a todos
los JSRs (sucesor del JTWI)
• Los JSRs fuera del MIDP se llaman
paquetes opcionales
37. J2ME
Universidad de Deusto
CLDC
• Dos grupos de clases:
– Heredadas de J2SE. Encuadradas dentro
de las librerías:
• java.util
• java.lang
• java.io
– Específicas de esta configuración
• javax.microedition.io
37
38. J2ME
CLDC: java.lang
• Boolean
• Byte
• Character
• Class
• Integer
• Long
• Math
• Object
• Runnable
• Runtime
• Short
• String
• StringBuffer
• System
• Thread
• Throwable
38
42. Otros paquetes propios de J2ME
• javax.microedition.lcdui
– Clases asociadas con GUI y el soporte de eventos.
• javax.microedition.rms
– Mecanismos para el almacenamiento persistente.
• javax.microedition.io
– APIs para establecer diferentes tipos de comunicación.
– MIDP amplia el Generic Connection Framework de CLDC
– GCF: interfaces y clases que representan los
diferentes tipos de conexiones: http, socket,
datagramas, serie, etc.
42
47. Clase Display
La clase Display es la encargada de administrar la pantalla.
Además de otros métodos relativos a las capacidades gráficas del
dispositivo, sus métodos más importantes son:
void setCurrent(Alert a, Displayable d) Establece la pantalla d despues de la alerta a
void setCurrent(Displayable d) Establece la pantalla d
void setCurrentItem(Item item) Establece el foco en item
47
50. Ticker
Un Ticker es una línea de texto que
se mueve continuamente por la
pantalla
Ejemplo: la banda de resumen de
noticias o cotizaciones de bolsa en TV
Sólo puede haber un Ticker en la
pantalla
50
51. Ticker
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.Ticker;
import javax.microedition.midlet.MIDlet;
public class HolaMundoTicker extends MIDlet
{
protected Display pantalla;
protected Form formulario;
public HolaMundoTicker() { }
public void startApp()
{
if (pantalla != null) return;
this.pantalla = Display.getDisplay(this);
this.formulario = new Form("Hola Mundo");
formulario.setTicker(new Ticker("Este es un Ticker"));
pantalla.setCurrent(formulario);
}
public void pauseApp() { }
public void destroyApp(boolean unconditional) { }
} 51
69. Ejemplo con TextBox
public class EjemploTextBox extends MIDlet implements CommandListener
{
protected Display pantalla;
protected TextBox box;
protected Command mostrar,insertar,limpiar,restric;
protected void startApp()
{
if (pantalla != null) return;
this.pantalla = Display.getDisplay(this);
// String title, String text, int maxSize, int constraints)
this.box = new TextBox("Ejemplo TextBox","Esto es nun texto",100,TextField.ANY);
this.mostrar = new Command("Mostrar",Command.SCREEN,0);
box.addCommand(mostrar);
this.insertar = new Command("Insertar",Command.SCREEN,0);
box.addCommand(insertar);
this.limpiar = new Command("Limpiar",Command.SCREEN,0);
box.addCommand(limpiar);
this.restric = new Command("Ver Restric",Command.SCREEN,0);
box.addCommand(restric);
box.setCommandListener(this);
pantalla.setCurrent(box);
} 69
70. Ejemplo con TextBox
protected void pauseApp() { }
protected void destroyApp(boolean unconditional) { }
public void commandAction(Command c, Displayable d)
{
if (c == mostrar)
{
String texto = box.getString();
Alert alerta = new Alert("Alerta Modal",texto,null,AlertType.INFO);
alerta.setTimeout(Alert.FOREVER);
pantalla.setCurrent(alerta, pantalla.getCurrent());
}
else if (c == insertar)
{
int pos = box.getCaretPosition();
box.insert("Jose María", pos);
}
else if (c == limpiar)
{
box.delete(0,box.size());
// Alternativa: box.setString("");
}
70
71. Ejemplo con TextBox
else if (c == restric)
{
int constraints = box.getConstraints();
boolean esAny = (constraints & TextField.CONSTRAINT_MASK) == TextField.ANY;
String texto = esAny ? "¡SI!" : "¡NO!";
Alert alerta = new Alert("¿Es Modo ANY?",texto,null,AlertType.INFO);
alerta.setTimeout(Alert.FOREVER);
pantalla.setCurrent(alerta, pantalla.getCurrent());
}
}
}
71
72. Ejercicio
Hacer un MIDlet que muestre un
TextBox que sólo admita caracteres
numéricos y los oculte mientras se
escribe
Añadir dos comandos: uno para salir de
la aplicación y otro para mostrar con un
diálogo modal el contenido de la caja de
texto
72
73. Ejercicio: Solución
public class EjercicioTextBox extends MIDlet implements CommandListener
{
protected Display pantalla;
protected TextBox box;
protected Command salir,mostrar;
protected void startApp()
{
if (pantalla != null) return;
this.pantalla = Display.getDisplay(this);
// String title, String text, int maxSize, int constraints)
this.box = new TextBox("Ejercicio TextBox","",100,
TextField.NUMERIC | TextField.PASSWORD);
this.salir = new Command("Salir",Command.EXIT,0);
box.addCommand(salir);
this.mostrar = new Command("Mostrar",Command.SCREEN,1);
box.addCommand(mostrar);
box.setCommandListener(this);
pantalla.setCurrent(box);
} 73
79. Ejemplo Lista Implícita
public class ListaImplicita extends MIDlet implements CommandListener
{
protected Command atras, salir;
protected Display pantalla;
protected List menu;
public void startApp()
{
if (pantalla != null) return;
this.pantalla = Display.getDisplay(this);
this.atras = new Command("Atras", Command.BACK, 1);
this.salir = new Command("Salir", Command.EXIT, 1);
this.menu = new List("Lista Implícita",Choice.IMPLICIT);
menu.append("Opción 1", null);
menu.append("Opción 2", null);
menu.append("Opción 3", null);
menu.addCommand(salir);
menu.setCommandListener(this);
pantalla.setCurrent(menu);
}
79
80. Ejemplo Lista Implícita
public void pauseApp() { }
public void destroyApp(boolean unconditional) { }
public void commandAction(Command c, Displayable d)
{
if (c == List.SELECT_COMMAND)
{ // Selección de item
Form form = null;
switch (menu.getSelectedIndex())
{ //opcion del menu
case 0: form = new Form("Formulario 1"); break;
case 1: form = new Form("Formulario 2"); break;
case 2: form = new Form("Formulario 3"); break;
}
final Displayable anterior = pantalla.getCurrent(); // menu
form.addCommand(atras);
form.setCommandListener(new CommandListener() {
public void commandAction(Command c, Displayable d)
{ //Selecciono comando “Atrás”
pantalla.setCurrent(anterior);
}
}
);
pantalla.setCurrent(form);
} 80
81. Ejemplo Lista Implícita
else if (c == salir)
{ // Selecciono salir de la aplicacion
destroyApp(false);
notifyDestroyed();
}
}
}
81
82. Ejemplo Lista Exclusiva
public class ListaExclusiva extends MIDlet implements CommandListener
{
protected Display pantalla;
protected Command salir, salvar;
protected List lista;
public void startApp()
{
if (pantalla != null) return;
this.pantalla = Display.getDisplay(this);
this.salir = new Command("Salir", Command.EXIT, 1);
this.salvar = new Command("Salvar", Command.ITEM, 1);
String opciones[] = {"Opción 1", "Opción 2", "Opción 3"};
this.lista = new List("Lista exclusiva", Choice.EXCLUSIVE, opciones, null);
lista.addCommand(salvar);
lista.addCommand(salir);
lista.setCommandListener(this);
pantalla.setCurrent(lista);
}
public void pauseApp() { }
public void destroyApp(boolean unconditional) { }
82
83. Ejemplo Lista Exclusiva
public void commandAction(Command c, Displayable d)
{
if (c == salvar)
{
int opcionElegida = lista.getSelectedIndex();
Alert alerta = new Alert("Opción Elegida",
"Ha sido elegida :" + (opcionElegida + 1), null, AlertType.INFO);
alerta.setTimeout(5000);
pantalla.setCurrent(alerta, lista);
}
else
{
destroyApp(false);
notifyDestroyed();
}
}
}
83
84. Ejemplo Lista Múltiple
public class ListaMultiple extends MIDlet implements CommandListener
{
protected Display pantalla;
protected List lista;
protected Command salir, salvar;
public void startApp()
{
if (pantalla != null) return;
this.pantalla = Display.getDisplay(this);
this.salir = new Command("Salir", Command.EXIT, 1);
this.salvar = new Command("Salvar", Command.ITEM, 1);
this.lista = new List("Lista Multiple", Choice.MULTIPLE);
lista.insert(menu.size(),"Opción 1", null);
lista.insert(menu.size(),"Opción 2", null);
lista.insert(menu.size(),"Opción 3", null);
lista.addCommand(salir);
lista.addCommand(salvar);
lista.setCommandListener(this);
pantalla.setCurrent(lista);
}
84
85. Ejemplo Lista Múltiple
public void pauseApp() { }
public void destroyApp(boolean unconditional) { }
public void commandAction(Command c, Displayable d)
{
if (c == salvar)
{
boolean seleccionados[] = new boolean[lista.size()];
lista.getSelectedFlags(seleccionados);
StringBuffer buf = new StringBuffer();
for (int i = 0; i < seleccionados.length; i++)
{
if (!seleccionados[i]) continue;
// Alternativa: lista.isSelected(i)
buf.append("Opción ");
buf.append( i + 1 );
buf.append( "n" );
}
Alert alerta = new Alert("Seleccionados:",buf.toString(), null, AlertType.INFO);
alerta.setTimeout(5000);
pantalla.setCurrent(alerta, lista);
}
85
87. Ejercicio
Hacer una lista múltiple con 5
opciones
Añadir tres comandos
Salir de la aplicación
Seleccionar todos
Eliminar los seleccionados mostrando
en un diálogo la lista de los eliminados
87
88. Ejercicio: Solución
public class EjercicioListaMultiple extends MIDlet implements CommandListener
{
protected Display pantalla;
protected List lista;
protected Command salir,eliminar,selecTodos;
public void startApp()
{
if (pantalla != null) return;
this.pantalla = Display.getDisplay(this);
this.salir = new Command("Salir", Command.EXIT, 1);
this.eliminar = new Command("Eliminar Selec", Command.ITEM, 1);
this.selecTodos = new Command("Seleccionar Todos", Command.ITEM, 1);
this.lista = new List("Lista Multiple", Choice.MULTIPLE);
for(int i = 1; i <= 5; i++)
lista.append("Opción " + i, null);
lista.addCommand(salir);
lista.addCommand(eliminar);
lista.addCommand(selecTodos);
lista.setCommandListener(this);
pantalla.setCurrent(lista);
} 88
89. Ejercicio: Solución
public void pauseApp() { }
public void destroyApp(boolean unconditional) { }
public void commandAction(Command c, Displayable d)
{
if (c == eliminar)
{
boolean seleccionados[] = new boolean[lista.size()];
lista.getSelectedFlags(seleccionados);
StringBuffer buf = new StringBuffer();
for (int i = seleccionados.length - 1; i >= 0; i--)
{
if (!seleccionados[i]) continue;
buf.append("Opción ");
buf.append( i + 1 );
buf.append( "n" );
lista.delete(i);
}
Alert alerta = new Alert("Eliminados:",buf.toString(), null, AlertType.INFO);
alerta.setTimeout(5000);
pantalla.setCurrent(alerta, lista);
}
89
90. Ejercicio: Solución
else if (c == selecTodos)
{
for (int i = 0; i < lista.size(); i++)
lista.setSelectedIndex(i,true);
}
else
{
destroyApp(false);
notifyDestroyed();
}
}
}
90
166. Networking (Generic Connection Framework)
• Las diferentes posibilidades de comunicación
están representadas por 7 interfaces:
– Connection
– ContentConnection
– DatagramConnection
– InputConnection
– OutputConnection
– StreamConnection
– StreamConnectionNotifier
• Todas las conexiones se crean de la misma
manera:
– Connection Connector.open(String s)
Universidad de Deusto
. . . . . . . . .
166
167. Networking
• Formato del String pasado como parámetro:
– {protocol}:[{target}][{params}]
• Valores para protocol:
– file
– comm
– socket
– datagram
– http
• Target hostname,puerto,nombre de un archivo.
• Params opcional (información adicional)
167
169. Networking (sockets)
• No todos los móviles soportan este tipo
de conexión.
• Envío de datos OuputConnection OutputStream
• Recepcion de datos InputConnection InputStream
• StreamConnection recepción y envío de datos
• Hay que cerrar el socket al finalizar la
aplicación.
169
170. SocketConnection
Con setSocketOption se puede parametrizar la conexión:
Definiendo el tamaño de los buffers de entrada (RCVBUF) y salida
(SNDBUF). Con getSocketOption se puede saber las medidas que usa
el sistema. Lo normal (el sistema deberia hacerlo) es ajustarlos al MTU
(Max. Transmission Unit) y el MSS (Max. Segment Size, cuerpo) de la
red.
Parametros:
//SocketConnection properties
private int KEEPALIVE_VALUE=1;
private int LINGER_VALUE=5;
private int RCVBUF_SIZE=256;
private int SNDBUF_SIZE=256;
private int DELAY_VALUE=0;//Nagle algorithm is turned off with 0 value!
170
171. Networking (http)
• Ejemplo: Interacción con un jsp.
public class Conexion {
private String URL="http://localhost:8080/numero/numero.jsp";
public Conexion(){
}
public String enviarNumero(int i)throws IOException{
HttpConnection c=null;
DataInputStream is=null;
OutputStream os=null;
StringBuffer b=new StringBuffer();
try {
c = (HttpConnection)Connector.open(URL);
c.setRequestMethod(HttpConnection.POST);
c.setRequestProperty( "Accept","application/octet-stream" );
171
174. Almacenamiento persistente
• Dos tipos de memoria:
– Ejecución de las aplicaciones.
– Almacenamiento persistente.
• RMS (Record Management System)
• javax.microedition.rms
• RecordStore tabla
• record registro
174
176. Almacenamiento (RecordStore)
• Fichero consistente en un grupo de records.
• Métodos:
– RecordStore openRecordStore(String nombre,boolean
create)
– closeRecordStore()
– deleteRecordStore(String nombre)
• Un RecordStore tiene una cabecera y una serie de
bloques de datos (registros o records).
– int getVersion()
– int getNumRecords()
– int getNextRecordId()
– long getLastModified()
176
177. Creación de un RecordStore
try{
// Abro el RecordStore
tablaDatosPersonales = RecordStore.openRecordStore("DatosPersonales",true);
// Imprimo los valores de la propiedades del Record Store
System.out.println("Nombre: " + tablaDatosPersonales.getName());
System.out.println("Version: " + tablaDatosPersonales.getVersion());
System.out.println("Ultima modificacion: " + tablaDatosPersonales.getLastModified());
System.out.println("Tamaño: " + tablaDatosPersonales.getSize());
System.out.println("Espacio disponible: " + tablaDatosPersonales.getSizeAvailable());
// Cierro el RecordStore
tablaDatosPersonales.closeRecordStore();
} catch (RecordStoreException e) {
System.out.println(e.toString());
}
177
179. Agregar registros
// Creo los streams de soporte
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream (baos);
// Vuelco los parámetros de entrada en DataOutputStream
try{
try{
dos.writeUTF(nombre);
dos.writeUTF(dirIP);
dos.writeInt(puerto);
} catch (IOException ioe){
System.out.println(ioe.toString());
}
// Vuelco ByteArrayOutputStream en el RecordStore
byte[] vectorDatos = baos.toByteArray();
System.out.println("Añadiendo un registro");
tablaConexiones.addRecord(vectorDatos, 0, vectorDatos.length);
} catch (RecordStoreException rse) {
System.out.println(rse.toString());
} 179
180. Recuperar un registro
// Crea los streams de soporte a partir del registro
ByteArrayInputStream bais;
DataInputStream dis;
try{
bais = new ByteArrayInputStream(tablaConexiones.getRecord(recordId));
dis = new DataInputStream (bais);
// Extraigo la información
try{
String nombre = dis.readUTF();
String dirIP = dis.readUTF();
int puerto = dis.readInt();
System.out.println("Conexión " + nombre + ", hacia " + dirIP + ": " + puerto);
} catch (IOException ioe){
System.out.println(ioe.toString());
}
} catch (RecordStoreException rse) {
System.out.println(rse.toString());
}
180
184. public int compare (byte[] registro1, byte[]
registro2){
int
resultado=RecordComparator.EQUIVALENT;
// Crea streams de soporte
ByteArrayInputStream bais1;
DataInputStream dis1;
ByteArrayInputStream bais2;
DataInputStream dis2;
try{
// Para el registro 1
bais1 = new
ByteArrayInputStream(registro1);
dis1 = new DataInputStream (bais1);
// Para el registro 2
bais2 = new
ByteArrayInputStream(registro2);
dis2 = new DataInputStream (bais2);
// Extrae la información del registro 1
String nombre1 = dis1.readUTF();
String dirIP1 = dis1.readUTF();
int puerto1 = dis1.readInt();
// y del registro 2
String nombre2 = dis2.readUTF();
String dirIP2 = dis2.readUTF();
int puerto2 = dis2.readInt();
if (puerto1==puerto2){
resultado=RecordComparator.EQUIVALENT;
} else if (puerto1<puerto2){
resultado=RecordComparator.PRECEDES;
} else if (puerto1>puerto2){
resultado=RecordComparator.FOLLOWS;
}
} catch (IOException ioe){
System.out.println(ioe.toString());
}
return resultado;
} 184
185. MIDlet
Suite A
RecordStore 1
RecordStore 2
TimeStamp: 223234544332
Nombre: RecordStore1
Versión: 1.0
Registros: 3
1
2
3
Juan Perez, 18
Jose Carlos Zerep, 65
Mario Perelló Salamanca, 48
RecordStore 1
MIDlet
Suite B
185
186. Almacenamiento (RecordStore)
• Otros métodos:
– int getSizeAvailable()
– int getSize()
– String[] listRecordStores()
• Un RecordStore se bloquea durante una
operación de lectura o escritura.
186
187. Almacenamiento (Record)
• Cada una de las entradas a un RecordStore:
– Son arrays de bytes.
– Identificados únivocamente por un entero.
• Métodos:
– Int addRecord(byte[] data,int offset,int numBytes)
– deleteRecord(int recordId)
– getRecord(int recordId,byte[] buffer,int offset)
– byte[] getRecord(int recordId)
– setRecord(int recId,byte[] data,int offset,int num)
187
188. Almacenamiento (RecordListener)
• Se pueden monitorizar los cambios en un
RecordStore mediante el interface
RecordListener.
• Cuando se modifica un RecordStore se lanzá
un evento al RecordListener registrado.Hay
tres tipos de eventos:
– recordAdded(RecordStore rs,int recordId)
– recordChanged(RecordStore rs,int recordId)
– recordDeleted(RecordStore rs,int recordId)
188
189. Almacenamiento (RecordListener)
• Métodos:
– addRecordListener(RecordListener rl)
– removeRecordListener(RecordListener rl)
• Un RecordStore puede tener registrados
varios RecordListener.
– Al contrario que un Displayable (sólo un
CommandListener) o un Form (sólo un
ItemStateListener).
189
190. Tablas con múltiples columnas
• Un registro (record) en un RecordStore sólo
tiene un campo representado por un array de
bytes.
• Se puede utilizar clases del paquete java.io
para empaquetar diferentes tipos de datos en
un array de bytes.
– DataInputStream
– DataOuputStream
– ByteArrayOutputStream
– ByteArrayInputStream
Universidad de Deusto
. . . . . . . . .
190
191. Tablas con múltiples columnas
public class Persona{
int id;
String nombre;
String apellido;
int edad;
...
}
public byte[] convertirBytes(){
byte[] datos;
try{
ByteArrayOutputStream bos=new ByteArrayOutputStream();
DataOutputStream dos=new DataOutputStream(baos);
dos.writeUTF(nombre);
dos.writeUTF(apellido);
dos.writeInt(edad);
datos=baos.toByteArray();
baos.close();
dos.close();
}...
191
192. Tablas con múltiples columnas
• Se guarda el array de bytes:
public void guardar(Persona p){
RecorStore rs;
try{
byte[] datos=p.convertirBytes();
int id=p.getId();
if(id==0){
id=rs.addRecord(datos,0,datos.length);
p.setId();
}
else{
rs.setRecord(id,datos,0,datos.length);
}
}...
192
193. Paquetes opcionales
• MMAPI (Mobile Media API)
– Influencia de JMF (++limitado)
– Basado en:
• Player: reproducir datos multimedia.
• Control: controlar ciertas funciones de procesamiento de
información.
• DataSource: sirve de soporte de protocolos.
• Manager: gestiona el proceso de creación de los Player y
los DataSource asociados.
• WMA (Wireless Messaging API)
– Permite al desarrollador el acceso al servicio SMS.
193
194. Paquetes opcionales
• Web Services API:
– Abre nuevas posibilidades a J2ME:
• Permite acceso remoto a web services
mediante SOAP / XML.
• Permite parsing XML.
– Muy importante dado el auge actual de
XML.
194
196. J2ME
GUI (Interfaz gráfica)
• No es un subconjunto de AWT o Swing.
• javax.microedition.lcdui
• Se compone de dos grupos de APIs:
– De alto nivel:
• Trabajan desde un punto de vista más conceptual
mayor grado de portabilidad.
• No hay acceso a las características nativas del
dispositivo.
– De bajo nivel:
• Control total del diseño de la pantalla (juegos).
• Menor portabilidad.
196
197. Representa los objetos que pueden
renderizarse en la pantalla.
- Canvas (bajo nivel)
- Screen (alto nivel)
• Estructuras predefinidas: Alert, TextBox,
List
• Pantalla genérica (Form), con la que
puede presentarse una mezcla de
componentes (imágenes, listas, etc.)
GUI (Displayable)
197
198. GUI (Manejo de eventos)
• Dos componentes:
– Generadores de eventos.
– Listener de eventos (asociado a Displayable).
• Evento de alto nivel más importante
Command.
– CommandListener.
– Cualquier Displayable puede ser el generador de
un tipo de evento Command.
• Displayable.addCommand(Command)
• Displayable.removeCommand(Command)
198
199. GUI (Command)
• Command(String label, int type, int priority)
• Cuando se activa un Command se genera un evento
se le pasa a un CommandListener asociado.
• CommandListener interfaz que provee del método
de procesamiento de eventos.
– void commandAction(Command c, Displayable d)
• Un objeto que implemente CommandListener puede
escuchar a múltiples Displayable.
• Cada Displayable sólo puede tener asociado un
CommandListener
– Displayable.setCommandListener(CommandListener)
199
200. GUI (Image)
• Permite incluir imágenes (PNG)
• Puede crearse un objeto Image a partir:
– Un archivo incluido en el MIDlet.
• Image.createImage(String name)
– Un array de bytes.
• Almacenado de forma persistente.
• Descargada de un servidor.
• Incluido en el propio programa.
• Image.createImage(byte[] b,int offset,int length)
– Otra imagen.
• Image.createImage(Image source)
200
201. GUI (TextBox)
• Permite al usuario introducir
información.
• TextBox(String title,String text,int max,
int constraints).
• Input constraints: permite limitar el tipo
de información que el usuario puede
introducir (ANY,NUMERIC,URL,
PHONENUMBER,PASSWORD,etc.)
201
202. • Implementa el interface Choice.
• Constructores:
– List(String title,int type)
– List(String title,int type,String[] opc,Image[] opc)
• Tres tipos de objetos Choice:
– Exclusive: sólo un elemento seleccionado.
– Implicit: tipo especial de Exclusive.
– Multiple: es seleccionable cualquier combinación
de elementos.
GUI (List)
202
203. GUI (List)
• append(String s,Image i) añadir un elemento a la lista
• delete (int i) borrar un elemento de la lista
• int getSelectedFlags(boolean[]) devuelve el número de
elementos seleccionados y guarda en el array de booleanos el
estado de los elementos (true si está seleccionado)
• int getSelected index() devuelve el elemento seleccionado
• String getString(int i)
• insert (int num, String s, Image i)
• set (int num, String s, Image i)
• int size()
203
204. J2ME
GUI (Alert)
• Tipo de pantalla predefinida que sirve para mostrar
distintos tipos de mensajes al usuario
(error,advertencia, alarma,etc.)
• Constructores:
– Alert(String title)
– Alert(String title,String text,Image image, AlertType type)
• TimeOut
– Tiempo de expiración de la pantalla Alert.
– Se mide en ms, aunque existe la posibilidad de configurarla
como modal.
– Alert.setTimeout(ms), Alert.setTimeout(Alert.Forever)
204
205. GUI (Alert)
• Display.setCurrent(Alert a,Displayable d) Se
indica el siguiente Displayable que debe mostrarse
cuando el tiempo expire.
-No se pueden añadir Commands a una
pantalla de tipo Alert.
-Tipos: Alarm, Confirmation, Error, Info,
Warning (se diferencian en el sonido emitido
al aparecer la pantalla)
205
206. GUI (Form & Item)
• Tipo de pantalla (hereda de Screen) que
puede contener diferentes tipos de
componentes (imágenes,cuadros de
texto,listas, etc.)
• Constructores:
– Form(String title)
– Form(String title, Item[] items)
• La clase Item es la superclase de los
componentes que se pueden añadir a un
Form.
206
207. GUI (Form & Item)
• Un Item no puede situarse en dos Form.
• Métodos más importantes de Form:
– int size()
– append (Image i)
– append (Item item)
– append (String s)
– delete (int itemNum)
– insert (int itemNum,Item item)
– set (int itemNum,Item item)
• Un Item no puede situarse en dos Form.
• Métodos más importantes de Form:
– int size()
– append (Image i)
– append (Item item)
– append (String s)
– delete (int itemNum)
– insert (int itemNum,Item item)
– set (int itemNum,Item item)
207
209. GUI (StringItem)
• StringItem(String label, String text)
• La aplicación puede modificar el
contenido, pero no el usuario.
• Métodos:
– setText(String s)
– String getText()
209
210. GUI (TextField)
• Similar a un TextBox. La única
diferencia es la clase de la que heredan.
• Item que contiene un texto interactivo.
• TextField(String label,String text,int
maxSize,int constraints)
210
211. GUI (ImageItem)
• ImageItem(String label,Image i,int
layout,String altText)
• Layout:
– Parámetro que indica cómo se alinea el objeto
Image en la pantalla.
– Los diferentes valores pueden combinarse con
operador OR ( | ).
– Valores: DEFAULT, LEFT, RIGHT, CENTER, etc.
– setLayout(int layout)
211
212. GUI (ChoiceGroup)
• Implementa el interface Choice.
• Similar a List. Única diferencia:
– No hay tipo implicito (Implicit)
• ChoiceGroup(String label,int type)
• ChoiceGroup(String label,int type, String[] elements,
Image[] images)
• Los métodos son los mismos que hemos visto
para List.
212
213. GUI (Gauge)
• Item que implementa una barra que normalmente
sirve de indicador.
• Gauge (String label,boolean interactive,int
maxValue,int initialValue)
• Si es interactive el usuario puede cambiar su valor.
• Métodos:
– setMaxValue(int i)
– setValue(int i)
– boolean isInteractive()
213
214. GUI (DateField)
• Item editable para presentar información sobre la
fecha y la hora.
• Constructores:
– DateField(String label,int mode)
– DateField(String label,int mode, TimeZone t)
• Modos:
– DATE: el usuario sólo puede configurar la fecha.
– TIME: el usuario sólo puede configurar la hora.
– DATE_TIME: el usuario puede configurar hora y fecha.
214
215. GUI (ItemStateListener)
• Cuando el usuario interactúa con alguno de
los Item:
– Introducir texto en un TextField.
– Seleccionar/deseleccionar una opción de un Choice.
• Se genera un EVENTO ItemStateChanged
• ItemStateListener Funciona de la misma manera que lo
que hemos visto para Command y CommandListener, es decir,
entre otras cosas puede escuchar a múltiples Forms.
• Método que procesa los eventos:
– void itemStateChanged(Item item)
215
216. GUI (Canvas)
• Subclase de Displayable que implementa la API de bajo nivel.
• Es una clase abstracta. Sus subclases deben implementar el
método paint(Graphics g).
• Métodos para soportar eventos de bajo nivel:
– Pulsación de las teclas.
• keyPressed(int keyCode)
• keyReleased(int keyCode)
• keyRepeated(int keyCode)
– Pulsación con puntero.
• pointerDragged(int x, int y)
• pointerPressed(int x,int y)
• pointerReleased(int x,int y)
• Un Canvas también puede originar eventos de alto nivel
(Command)
216
217. GUI (Canvas)
• Métodos para conocer el tamaño de la pantalla:
– int getHeight()
– int getWidth()
• La clase Graphics posibilita renderizar sobre el
Canvas figuras geómetricas 2D.
• Es muy parecida a la clase Graphics de java.awt de
J2SE.
• Existen métodos para dibujar líneas, imágenes, texto,
rellenar rectángulos o dibujar arcos.
217
219. GUI (Canvas)
• El sistema de coordenadas no representa a
los pixels, sino el espacio entre los pixels:
– Así el pixel de la parte superior izquierda se
encuentra en el cuadrado determinado por las
siguientes coordenadas:
• (0,0),(1,0)
• (0,1),(1,1)
• Es importante diferenciar la forma en la que
se ejecutan las operaciones de dibujado y
relleno de un área.
219
220. GUI (Canvas)
• Color:
– Modelo de color de 24 bits (8r,8v,8a)
– Si el dispositivo no lo soporta (Display.isColor()), la
implementación midp los mapeará a los existentes.
– setColor(int RGB)
– setColor(int red,int green,int blue)
– setGrayScale(int value)
• Antes de dibujar sobre un Canvas, se fija el color de
fondo.
– setColor(int RGB)
– fillRect()
220
221. GUI (Canvas)
• Dos tipos de trazos: solido, de puntos
– setStrokeStyle(int style)
• Dibujado de líneas:
– drawLine(int x1,int y1,int x2,int y2)
• Dibujado y relleno de formas
rectangulares
– drawRect(int x,int y,int ancho,int alto)
– fillRect(int x,int y,int ancho,int alto)
221
222. GUI (Canvas)
• Dibujado de texto:
– drawChar(char c,int x,int y,int anchor)
– drawChars(char[] c,int offset,int length,int x,int y,int anchor)
– drawString(String c,int x,int y,int anchor)
– drawSubstring(String c, int offset,int length, int x,int y,int anchor)
• Anchor Points (Puntos de anclaje):
– El dibujado de texto se basa en estos puntos.
– Hay tres constantes horizontales (LEFT,HCENTER,RIGHT) y
cuatro verticales (TOP,BOTTOM,BASELINE,VCENTER)
– Para la definición de un anchor point se hace uso de una
constante htal y una vcal.
222
224. GUI (Canvas)
• Font:
– Representa las diferentes fuentes de texto.
– En una aplicación no pueden crearse instancias de
Font:
• Font getFont(int face,int style,int size)
• Style:STYLE_BOLD,STYLE_PLAIN,STYLE_ITALIC,STYLE_UNDERLINED
• Size: SIZE_LARGE,SIZE_MEDIUM,SIZE_SMALL
• Face: FACE_MONOSPACE,FACE_PROPORTIONAL,FACE_SYSTEM
224
225. GUI (Canvas)
• Dibujado de imágenes:
– drawImage(Image i,int x,int y,int anchor)
• Traslación de coordenadas:
– translate(int x,int y)
• Clips:
– Se usa cuando se quiere trabajar sobre un área
concreta del Canvas
• setClip(int x,int y,int ancho,int alto)
• Los pixels que no se encuentren dentro del área
determinada por el método no se verán afectadas por las
operaciones gráficas.
225
226. GUI (Canvas)
• En muchas aplicaciones se requiere que el
usuario maneje eventos relacionados con
juegos.
– MIDP define las siguientes eventos:
UP,DOWN,LEFT,RIGHT,FIRE,etc
– Las teclas correspondientes a estos eventos
dependen del dispositivo.
– getGameAction(int keyCode) se usa para
traducir el código de la tecla a una acción de un
juego.
• En muchas aplicaciones se requiere que el
usuario maneje eventos relacionados con
juegos.
– MIDP define las siguientes eventos:
UP,DOWN,LEFT,RIGHT,FIRE,etc
– Las teclas correspondientes a estos eventos
dependen del dispositivo.
– getGameAction(int keyCode) se usa para
traducir el código de la tecla a una acción de un
juego.
226
227. GUI (Canvas)
• Refresco de pantalla:
– Objeto de tipo Screen cambios se
reflejan de forma automática en pantalla.
– Canvas la aplicación debe encargarse de
refrescar la pantalla.
• repaint(int x,int y,int ancho,int alto)
• repaint()
• Si el Canvas no está visible en pantalla el
refresco no tiene ningún efecto.
227
228. GUI (Canvas)
• El dibujado del Canvas se realiza de manera
asíncrona el método repaint() devuelve el
control sin esperar a que finalice el proceso
paint() al que invoca.
• Para conseguir sincronizar con la rutina de
paint()
– Display.callSerially(Runnable r) se invoca el
método run() del objeto Runnable justo después
de haber finalizado el proceso de “repintado”.Es
muy útil para animaciones.
228