progav-tema6

53
Tema 6: Programación de dispositivos móviles Programación de dispositivos móviles 1.Programación de dispositivos móviles 2.Limitaciones de los dispositivos móviles 3.Sistemas operativos móviles 4.Desarrollo de aplicaciones móviles 5.Java 2 Mobile Edition 6.Configuración CDC 7.Configuración CLDC 8.Paquetes opcionales en J2ME 9.MIDP: MIDlets 10.MIDP: Interfaces Gráficas de Usuario 11.MIDP: Persistencia 12.MIDP: Conexión por red 13.Persistencia II: Ficheros 14.Para terminar

Upload: yonic

Post on 24-Oct-2014

20 views

Category:

Documents


2 download

TRANSCRIPT

Page 1: progav-tema6

Tema 6: Programación de dispositivos móviles

Programación de dispositivos móviles

1.Programación de dispositivos móviles2.Limitaciones de los dispositivos móviles3.Sistemas operativos móviles4.Desarrollo de aplicaciones móviles5.Java 2 Mobile Edition6.Configuración CDC7.Configuración CLDC8.Paquetes opcionales en J2ME9.MIDP: MIDlets10.MIDP: Interfaces Gráficas de Usuario11.MIDP: Persistencia12.MIDP: Conexión por red13.Persistencia II: Ficheros14.Para terminar

Page 2: progav-tema6

Programación de dispositivos móviles●La generalización en los últimos años de teléfonos móviles, smartphones, PDAs, etc. ha generado un importante necesidad de aplicaciones para este tipo de dispositivos●Las prestaciones de los dispositivos móviles se incrementan día a día, posibilitando la implementación de aplicaciones muy interesantes

● Acceso a Internet y conectividad mediante Bluetooth● Envío de mensajes cortos● Aceleración 2D y 3D● Reproducción de video y sonido● Cámara integrada● Información de localización GPS● Sensores de orientación● etc.

Programación de dispositivos móviles

Programación de dispositivos móviles

Page 3: progav-tema6

Limitaciones de los dispositivos móviles●La necesidad de ahorrar energía obliga a utilizar procesadores con una capacidad de cómputo limitada y baja frecuencia de reloj●El uso intensivo de cálculos, gráficos, sonido, conexiones inalámbricas etc. limita la vida de la bateria●La memoria disponible es muy limitada en comparación con la de un ordenador ordinario●El almacenamiento de datos persistente también es muy limitado: memoria interna + tarjetas SD o similar

Limitaciones de los dispositivos móviles

Programación de dispositivos móviles

Page 4: progav-tema6

Sistemas operativos móviles●Son sistemas operativos específicos para este tipo de dispositivos, que tienen en cuenta las limitaciones que hemos visto antes●Symbian es el S.O. instalado en mayor número de dispositivos móviles en la actualidad, sobre todo teléfonos móviles●Dos plataformas: S60 y UIQ

S60 UIQ

Sistemas operativos móviles

Programación de dispositivos móviles

Page 5: progav-tema6

●Windows Mobile, con mayor difusión en el mercado de PDAs

●Palm OS, utilizado por el fabricante de PDAs Palm Inc.

Programación de dispositivos móviles

Sistemas operativos móviles

Page 6: progav-tema6

●Android, es un S.O. para móviles presentado recientemente por Google. Utiliza un kernel Linux

●Otros S.O. móviles: RIM Blackberry y otros S.O. basados en kernel linux

Programación de dispositivos móviles

Sistemas operativos móviles

Page 7: progav-tema6

Desarrollo de aplicaciones móviles●Gran disparidad de plataformas de desarrollo●Symbian (S60 y UIQ): C++ con librerías nativas●Windows Mobile: .NET Compact Framework, una versión limitada de .NET●PalmOS: C/C++, con librerías nativas●Android: Java con librerías nativas (no J2ME)●Java Mobile Edition (J2ME) para múltiples plataformas, especialmente Symbian●Otras: Python

Programación de dispositivos móviles

Sistemas operativos móviles

Page 8: progav-tema6

Java 2 Mobile Edition●La única opción real que permite un desarrollo multiplataforma para dispositivos móviles●Tiene una estructura altamente modular para adaptarse a las características de cada dispositivo

Java 2 Mobile  Edition

Sistemas operativos móviles

Page 9: progav-tema6

●Las configuraciones (CDC y CDLC) definen el entorno mínimo necesario para la ejecución de aplicaciones java en un grupo amplio de dispositivos móviles (JVM/KVM+paquetes básicos)●Los perfiles definen paquetes adicionales para soportar funcionalidades básicas imprescindibles de cada familia de dispositivos●Los paquetes opcionales sirven para cubrir funcionalidades específicas: Bluetooth, soporte 3D, etc.

Java 2 Mobile  Edition

Sistemas operativos móviles

Page 10: progav-tema6

Configuración CDC●CDC (Connected Device Configuration). Para PDAs de última generación o smartphones avanzados●Requiere una máquina virtual java compatible con J2SE 1.4.2 y los siguientes paquetes:

Configuración CDC 

Sistemas operativos móviles

●java.lang●java.lang.ref●java.lang.reflect●java.math●java.text●java.io●javax.microedition.io

●java.util●java.util.zip●java.util.jar●java.net●java.security●java.security.cer

Page 11: progav-tema6

●Los dispositivos que utilizan el CDC admiten tres perfiles: Foundation Profile, Personal Basis Profile y Personal Profile●El Foundation Profile  proporciona soporte básico de red y E/S●El Personal Basis Profile contiene todas las clases del Foundation Profile más soporte limitado de Javabeans y AWT●El Personal Profile incluye los dos perfiles anteriores más soporte completo de AWT y Javabeans●Una aplicación J2SE implementada cuidadosamente puede ser ejecutable en la configuración CDC

Configuración CDC 

Sistemas operativos móviles

Page 12: progav-tema6

Configuración CLDC●CLDC (Connected Limited Device Configuration). Para dispositivos con potencia de cálculo, memoria, batería y acceso a red limitados●Incluye una máquina virtual java reducida (KVM) y los siguientes paquetes:

● java.lang (reducida)● java.lang.ref (reducida)● java.util (reducida)● java.io (reducida)● java.microedition.io

●Sólo incluye las clases básicas●EEDDs: Vector, Hashtable y Stack

Configuración CLDC

Sistemas operativos móviles

Page 13: progav-tema6

●Mobile Information Device Profile (MIDP) es el perfil más común con CLDC●MIDP permite la implementación de aplicaciones con la siguiente funcionalidad:

● Interfaz de usuario sencilla, adaptada a móviles● API especializado para juegos● Persistencia básica● Conexión por red● Sonido

●La mayoría de los móviles actuales soportan CLDC+MIDP. Mucho éxito por la implementación de juegos●La programación MIDP para configuración CLDC requiere la instalación del Sun Java Wireless Toolkit●Netbeans proporciona soporte mediante el Mobility Pack

Sistemas operativos móviles

Configuración CDLC

Page 14: progav-tema6

Paquetes opcionales en J2ME●Permiten extender la funcionalidad básica de los perfiles para aprovechar todas las posibilidades del dispositivo●Wireless Messaging API (WMA) JSR­120, JSR­205. Envío de mensajes SMS.●Mobile Media API (MMAPI) JSR­135. Soporte de audio y video, tanto reproducción como captura ●Location API JSR­179. Localización geográfica del dispositivo, mediante GPS u otros mecanismos

Paquetes opcionales en J2ME

Sistemas operativos móviles

Page 15: progav-tema6

●Personal Information Management and File Connection API JSR 75. Acceso a la lista de contactos del teléfono móvil y al sistema de ficheros●Security and Trust Services API JSR 177. Tratamiento de información privada, ejecución segura,  identificación y autentificación etc.●Mobile 3D Graphics JSR 184. Soporte de gráficos 3D●J2ME Web Services API (WSA) JSR­172. Soporte de servicios web en dispositivos móviles●Bluetooth API JSR 82●J2ME RMI JSR 66. Llamada a operaciones de objetos remotos

Paquetes opcionales en J2ME

Sistemas operativos móviles

Page 16: progav-tema6

MIDP: Midlets

Sistemas operativos móviles

MIDP: MIDlets●Una aplicación MIDP requiere la implementación de un MIDlet, cuya estructura recuerda los Applets y Servlets de J2SE

import javax.microedition.midlet.MIDlet;

public class EjemploMidlet extends MIDlet {public void startApp() {

// Arrancar aplicación}

public void pauseApp() {// Parar aplicación

}

public void destroyApp(boolean unconditional) {// Eliminar recursos

}}

Page 17: progav-tema6

MIDP: Midlets

Sistemas operativos móviles

●De manera similar a un Applet, un MIDlet requiere la implementación de tres operaciones de la clase MIDlet:

● startApp(). Es llamada automáticamente cuando la aplicación debe comenzar su ejecución

● pauseApp(). El dispositivo puede solicitar la parada temporal de la aplicación en cualquier momento. La reanudación implicará una nueva llamada a startApp() o la terminación definitiva mediante la llamada a destroyApp()

● destroyApp(). Es invocada para solicitar la liberación de los recursos del MIDlet y cualquier tarea necesaria antes de su eliminación de memoria

Page 18: progav-tema6

MIDP: Midlets

Sistemas operativos móviles

●Un conjunto de MIDlets se distribuye en un fichero jar●El MANIFEST del fichero jar es más complicado que los que conocemos●Primero se indica el nombre global del conjunto de MIDlets del fichero jar, su versión, author y las versiones de CLDC y MIDP necesarias●Después cada MIDlet se describe mediante un nombre, el icono correspondiente y el nombre de la clase que lo implementa

MIDlet-Name: EjemplosMIDPMIDlet-Version: 1.0MIDlet-Vendor: ajruedaMicroEdition-Configuration: CLDC-1.1MicroEdition-Profile: MIDP-2.0MIDlet-1: Ejemplo,ejemplo.png,EjemploMidlet

Page 19: progav-tema6

MIDP: Interfaces Gráficas de Usuario

Sistemas operativos móviles

MIDP: Interfaces Gráficas de Usuario●MIDP proporciona una forma sencilla de construir interfaces de usuario adaptada a las limitaciones de pantalla, potencia de cálculo y batería de los dispositivos móviles●En comparación con toolkits como Swing, la variedad y número de componentes existentes es muy pequeño●La interfaz se construye a base de distintas pantallas, en lugar de ventanas o diálogos●Las acciones del usuario definen la transición de una pantalla a otra

Page 20: progav-tema6

Sistemas operativos móviles

●Es importante tener en cuenta el pequeño tamaño de la pantalla del dispositivo a la hora de diseñar la interfaz●La mayoría de los dispositivos dispone de un par de botones de acción cuyo efecto se puede programar para cada pantalla

MIDP: Interfaces Gráficas de Usuario

Page 21: progav-tema6

Sistemas operativos móviles

●Para empezar hay que obtener el objeto Display que permite manejar la pantalla del dispositivo●La operación estática getDisplay() de esta clase devuelve el objeto

Display d = Display.getDisplay()●A continuación podemos establecer la pantalla actual mediante:

d.setCurrent(Displayable pantalla)●Una vez obtenido el display, el MIDlet sigue el siguiente esquema de funcionamiento:

1.Crear una pantalla2.Mostrarla mediante setCurrent()3.Esperar las acciones del usuario4.Elegir otra pantalla en función de estas acciones (volver a 1)

MIDP: Interfaces Gráficas de Usuario

Page 22: progav-tema6

Sistemas operativos móviles

●Las clases que implementan la interfaz Displayable son las siguientes:

MIDP: Interfaces Gráficas de Usuario

TextBox List Alert Form

Canvas

Page 23: progav-tema6

Sistemas operativos móviles

MIDP: Interfaces Gráficas de Usuario

●Crear y activar una pantalla TextBox es muy sencillo:

TextBox t = new TextBox(� Escribe un poema� , � � , 500, TextField.ANY);

d.setCurrent(t);

●Un Alert es similar a un messageBox de Swing, admitiendo distintos tipos.●El tiempo de visualización del Alert es configurable mediante setTimeout()●Al llamar a setCurrent() es necesario indicar el siguiente displayable a mostrar tras el Alert

Alert a = new Alert(� Error� , � Error al salvar la información� , null, AlertType.ERROR);a.setTimeout(5000);

d.setCurrent(a, siguienteDisp);

Page 24: progav-tema6

Sistemas operativos móviles

●El displayable Form permite definir una pantalla con múltiples Item (o componentes):

● StringItem. Similar a un label de Swing● Spacer. Un espacio con un ancho y alto determinado. Útil para distribuir los 

componentes● TextField. Un editor de texto con una etiqueta asociada● ImageItem. Una imagen con una etiqueta● DateField. Un editor que permite introducir una fecha/hora● Gauge. Sirve para representar de manera gráfica un valor entero● ChoiceGroup. Sirve para seleccionar valores de una lista predeterminada. Puede 

ser múltiple, exclusiva o popup● Cualquier Item definido por el usuario

MIDP: Interfaces Gráficas de Usuario

Page 25: progav-tema6

Sistemas operativos móviles

MIDP: Interfaces Gráficas de Usuario

●Los Form permiten crear interfaces mucho más ricas:Form f = new Form("Ficha deportiva");f.append(new TextField("Apellidos", null, 40, TextField.ANY));f.append(new TextField("Nombre", null, 40, TextField.ANY));f.append(new DateField("Fecha de nacimiento", DateField.DATE));f.append(new TextField("E-mail", null, 20, TextField.EMAILADDR));

String[] tipos = {"Profesor", "Alumno"};f.append(cg = new ChoiceGroup("Tipo", ChoiceGroup.EXCLUSIVE, tipos, null));

d.setCurrent(f);

Page 26: progav-tema6

Sistemas operativos móviles

MIDP: Interfaces Gráficas de Usuario

●Para asociar acciones a los botones del dispositivo se utiliza la clase Command●Las activación de un comando es capturada por un CommandListener, cuya única operación es commandAction()

TextBox t = new TextBox(� Escribe un poema� , � � , 500, TextField.ANY);

t.addCommand(cFin = new Command(� Fin� , Command.OK, 0));t.setListener(new listenerTextBox());

d.setCurrent(t);

class listenerTextBox implements CommandListener { public commandAction(Command cm, Displayable ds) { if (cm == cFin) { // Procesar el comando

} } }

Page 27: progav-tema6

Sistemas operativos móviles

MIDP: Interfaces Gráficas de Usuario

Siguiendo el ejemplo que hemos desarrollado en la asignatura, vamos a crear un visor móvil de nuestra cuenta

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

public class MidletCuenta extends MIDlet { private Cuenta c; private Display d; private TextField tCodigo; private Command cEntrar, cSalir, cVolver, cMovimientos; private Form fPeticionCodigo, fInfoCuenta; private List lMovCuenta; public MidletCuenta() { d = null; }

void crearComandos() { cEntrar = new Command("Entrar", Command.OK, 0); cSalir = new Command("Salir", Command.EXIT, 1); cVolver = new Command("Volver", Command.BACK, 0); cMovimientos = new Command("ver Mov.", Command.SCREEN, 0); }

Page 28: progav-tema6

Sistemas operativos móviles

MIDP: Interfaces Gráficas de Usuario

public void startApp() { if (d == null) { d = Display.getDisplay(this); } crearComandos(); crearFormPeticionCodigo(); d.setCurrent(fPeticionCodigo); }

void crearFormPeticionCodigo() { fPeticionCodigo = new Form("Información de cuentas"); fPeticionCodigo.append(tCodigo = new TextField("Código de cuenta ", null, 10, TextField.NUMERIC)); fPeticionCodigo.addCommand(cEntrar); fPeticionCodigo.addCommand(cSalir); fPeticionCodigo.setCommandListener(new listenerPeticionCodigo()); tCodigo.setLayout(Item.LAYOUT_2 | Item.LAYOUT_CENTER); }

class listenerPeticionCodigo implements CommandListener { public void commandAction(Command cm, Displayable s) { if (cm == cEntrar) { // Cargar la cuenta aquí crearFormInformacionCuenta(); d.setCurrent(fInfoCuenta); } else if (cm == cSalir) { destroyApp(true); notifyDestroyed(); } } }

Page 29: progav-tema6

Sistemas operativos móviles

MIDP: Interfaces Gráficas de Usuario

void crearFormInformacionCuenta() { // Crear formulario de información dae la cuenta fInfoCuenta = new Form("Información de cuenta"); fInfoCuenta.append(new StringItem("Código:", Long.toString(c.leerNumero()))); fInfoCuenta.append(new StringItem("Titular:", c.leerTitular())); fInfoCuenta.append(new StringItem("Interés:", Float.toString(c.leerInteres()))); fInfoCuenta.append(new StringItem("Saldo:", Float.toString(c.leerSaldo()))); fInfoCuenta.addCommand(cMovimientos); fInfoCuenta.addCommand(cVolver); fInfoCuenta.setCommandListener(new listenerInformacionCuenta()); // Crear lista de movimientos lMovCuenta = new List("Ultimos movimientos", List.IMPLICIT); Movimiento m; int nMov, nm; for (nMov = 10, nm = c.numMovimientosHistorico() - 1; nMov > 0 && nm >= 0; nm--, nMov--) { m = c.leerMovimientoHistorico(nm); lMovCuenta.append(cadenaDate(m.fecha) + ' ' + m.tipo + ' ' + m.importe + ' ' + m.saldo, null); } lMovCuenta.addCommand(cVolver); lMovCuenta.setCommandListener(new listenerInformacionMovimientos()); }

Page 30: progav-tema6

Sistemas operativos móviles

MIDP: Interfaces Gráficas de Usuario

class listenerInformacionCuenta implements CommandListener { public void commandAction(Command cm, Displayable s) { if (cm == cVolver) { d.setCurrent(fPeticionCodigo); } else if (cm == cMovimientos) { d.setCurrent(lMovCuenta); } } }

class listenerInformacionMovimientos implements CommandListener { public void commandAction(Command cm, Displayable s) { if (cm == cVolver) { d.setCurrent(fInfoCuenta); } } }

Page 31: progav-tema6

MIDP: Persistencia

Sistemas operativos móviles

MIDP: Persistencia●La capacidad de almacenamiento persistente de un dispositivo móvil puede ser muy limitada●El soporte de tarjetas de memoria, cada vez más común, ha aumentado mucho las prestaciones (8Gb en iPhone o Nokia N95) posibilitando una estructura de ficheros similar a la de un ordernador convencional●Sin embargo el perfil MIDP es conservador y proporciona un soporte sencillo de persistencia a través de registros de bloques de bytes

Page 32: progav-tema6

MIDP: Persistencia

Sistemas operativos móviles

●Un MIDlet puede abrir un almacén de registros con un  nombre arbitrario mediante:

RecordStore RecordStore.openRecordStore(“nombre”, true);●El segundo parámetro indica que el almacén debe abrirse si no existe●A través de las operaciones del objeto RecordStore podremos manejar los registros●Normalmente un almacén no se comparte con otros MIDlets, aunque puede habilitarse este acceso●El almacén de registros se cierra mediante:

closeRecordStore()

Page 33: progav-tema6

MIDP: Persistencia

Sistemas operativos móviles

●El acceso a los registros se realiza a través de un identificador numérico, que es devuelto al añadir un registro:

int addRecord(byte[] datos, int offset, int numBytes)●Para recuperar un registro debemos indicar su identificador:

int getRecord(int id, byte[] buffer, int offset)●Modificar un registro ya existente:

void setRecord(int id, byte[] nuevosDatos, int offset, int numBytes)●Eliminar un registro:

void deleteRecord(int id)

Page 34: progav-tema6

MIDP: Persistencia

Sistemas operativos móviles

●Es posible recorrer los registros de un almacén creando una enumeración:

RecordStore rs = RecordStore.openRecordStores(� ejemplo� , true);

RecordEnumeration re = re.enumerateRecords(null, null, false);while (re.hasNextElement()) {

byte[] datos = re.nextRecord(); // Operar con los datos

}

re.destroy();rs.closeRecordStore();

●La operación enumerateRecords() admite la especificación de clases de filtrado y ordenación de los registros del almacén

Page 35: progav-tema6

MIDP: Persistencia

Sistemas operativos móviles

Vamos a crear un gestor de persistencia para las cuentas corrientes mediante un almacén de registros

import java.io.*;import java.util.*;import javax.microedition.rms.*;

public class DAOCuentaRS { static DAOCuentaRS instancia = null;

public static DAOCuentaRS obtenerInstancia() throws RecordStoreException { if (instancia == null) { instancia = new DAOCuentaRS(); } return instancia; }

private DAOCuentaRS() {} public boolean existe(long numero) throws RecordStoreException, IOException { RecordStore rs = null; try { rs = RecordStore.openRecordStore("cuentas", true); return (buscarRegistroCuenta(rs, numero) != -1); } finally { if (rs != null) rs.closeRecordStore(); } }

Page 36: progav-tema6

MIDP: Persistencia

Sistemas operativos móviles

public Cuenta cargar(long numero) throws RecordStoreException, IOException { RecordStore rs = null; DataInputStream dis = null; Cuenta c = null; try { rs = RecordStore.openRecordStore("cuentas", true); int idReg = buscarRegistroCuenta(rs, numero); if (idReg == -1) { return null; } dis = new DataInputStream(new ByteArrayInputStream(rs.getRecord(idReg))); c = new Cuenta(dis.readLong(), dis.readUTF(), dis.readFloat()); c.saldo = dis.readFloat(); int nMov = dis.readInt(); for (int nm = 0; nm < nMov; nm++) { c.movimientos.addElement(new Movimiento(new Date(dis.readLong()), dis.readChar(), dis.readFloat(), dis.readFloat())); } } finally { if (dis != null) dis.close(); if (rs != null) rs.closeRecordStore(); } return c; }

Page 37: progav-tema6

MIDP: Persistencia

Sistemas operativos móviles

public void salvar(Cuenta c) throws RecordStoreException, IOException { RecordStore rs = null; ByteArrayOutputStream bos = null; DataOutputStream dos = null; try { rs = RecordStore.openRecordStore("cuentas", true); dos = new DataOutputStream(bos = new ByteArrayOutputStream()); dos.writeLong(c.leerNumero()); dos.writeUTF(c.leerTitular()); dos.writeFloat(c.leerInteres()); dos.writeFloat(c.leerSaldo()); Movimiento m; int nMov = c.numMovimientosHistorico(); dos.writeInt(nMov); for (int nm = 0; nm < nMov; nm++) { m = c.leerMovimientoHistorico(nm); dos.writeLong(m.fecha.getTime()); dos.writeChar(m.tipo); dos.writeFloat(m.importe); dos.writeFloat(m.saldo); } int idReg = buscarRegistroCuenta(rs, c.leerNumero()); if (idReg != -1) { rs.setRecord(idReg, bos.toByteArray(), 0, bos.size()); } else { rs.addRecord(bos.toByteArray(), 0, bos.size()); } } finally { if (dos != null) dos.close(); if (rs != null) rs.closeRecordStore(); } }

Page 38: progav-tema6

MIDP: Persistencia

Sistemas operativos móviles

private int buscarRegistroCuenta(RecordStore rs, long numero) throws RecordStoreException, IOException { RecordEnumeration re = null; DataInputStream dis = null; long recNum; int id; try { re = rs.enumerateRecords(null, null, false); while (re.hasNextElement()) { id = re.nextRecordId(); dis = new DataInputStream(new ByteArrayInputStream(rs.getRecord(id))); recNum = dis.readLong(); if (recNum == numero) { return id; } dis.close(); dis = null; } } finally { if (dis != null) dis.close(); if (re != null) re.destroy(); } return -1; }}

Page 39: progav-tema6

MIDP: Persistencia

Sistemas operativos móviles

public void startApp() { if (d == null) { d = Display.getDisplay(this); }

if (dc == null) { try { dc = DAOCuentaRS.obtenerInstancia(); } catch(Exception e) { d.setCurrent(new Alert("Error", "No es posible abrir el almacén de registros", null, AlertType.ERROR)); destroyApp(true); notifyDestroyed(); return; } }

// Crear las cuentas de ejemplo si no existen crearCuentasEjemplo();

crearComandos(); crearFormPeticionCodigo();

d.setCurrent(fPeticionCodigo); }

En el MIDlet debemos crear un atributo para referenciar el gestor de persistencia, y realizar su inicialización en startApp()

Page 40: progav-tema6

MIDP: Persistencia

Sistemas operativos móviles

class listenerPeticionCodigo implements CommandListener { public void commandAction(Command cm, Displayable s) { if (cm == cEntrar) { try { c = dc.cargar(Long.parseLong(tCodigo.getString())); if (c == null) { d.setCurrent(new Alert("Error", "Cuenta inexistente", null, AlertType.ERROR), fPeticionCodigo); return; } } catch(Exception e) { d.setCurrent(new Alert("Error", "Error de lectura de cuenta", null, AlertType.ERROR), fPeticionCodigo); return; } crearFormInformacionCuenta(); d.setCurrent(fInfoCuenta); } else if (cm == cSalir) { destroyApp(true); notifyDestroyed(); } } }

Page 41: progav-tema6

MIDP: Conexión por red

Sistemas operativos móviles

MIDP: Conexión por red●MIDP es especialmente potente en lo que se refiere a  la conexión por red mediante sockets, http y otros protocolos●La clase Connection representa una conexión genérica y es extendida a tres conexiones que admiten E/S mediante streams: InputConnection, OutputConnection y StreamConnection●La clase StreamConnection es extendida a varias clases que representan distintos tipos de conexiones: CommConnection, HttpConnection, httpsConnection, SocketConnection, etc.

Page 42: progav-tema6

MIDP: Conexión por red

Sistemas operativos móviles

●La clase Connector es una factoría que a partir de un url devuelve la clase de conexión correspondiente:

Connection Connector.open(String url)

HttpConnection con1; con1 = (HttpConnection) Connector.open(� http://www.google.es/search?hl=es&q=j2me� );

SocketConnection con2;con2 = (SocketConnection) Connector.open(� socket://miservidor:79� );

●La conexión debe cerrarse al final con close()●A partir de la conexión podemos obtener un stream de lectura o escritura

HttpConnection con1; con1 = (HttpConnection) Connector.open(� http://www.google.es/search?hl=es&q=j2me� );

InputStream is = con1.openInputStream(); // Utilizar el stream con1.close();

Page 43: progav-tema6

MIDP: Conexión por red

Sistemas operativos móviles

El siguiente gestor de persistencia obtiene los datos de la cuenta desde un servidor web

import java.io.*;import java.util.*;import javax.microedition.io.*;import javax.microedition.io.file.*;

public class DAOCuentaNC { static DAOCuentaNC instancia = null; public static DAOCuentaNC obtenerInstancia() { if (instancia == null) { instancia = new DAOCuentaNC(); } return instancia; }

private DAOCuentaNC() { } public boolean existe(long numero) { try { cargar(numero); } catch(Exception e) { return false; } return true; }

Page 44: progav-tema6

MIDP: Conexión por red

Sistemas operativos móviles

public Cuenta cargar(long numero) throws IOException { InputConnection ic = null; DataInputStream dis = null; Cuenta c = null; try { ic = (InputConnection) Connector.open(urlCuenta(numero)); dis = ic.openDataInputStream(); c = new Cuenta(dis.readLong(), dis.readUTF(), dis.readFloat()); c.saldo = dis.readFloat(); int nMov = dis.readInt(); for (int nm = 0; nm < nMov; nm++) { c.movimientos.addElement(new Movimiento(new Date(dis.readLong()), dis.readChar(), dis.readFloat(), dis.readFloat())); } } catch(Exception e) { // No se encuentra la cuenta return null; } finally { if (ic != null) ic.close(); } return c; } private String urlCuenta(long codigo) { return "http://robin.ujaen.es/asignaturas/progav/cuentas/" + Long.toString(codigo) + ".cnt"; }}

Page 45: progav-tema6

Persistencia II: Ficheros

Persistencia II: Ficheros●El File Connection and PIM API (JSR 75) define un nuevo tipo de conexión denominado FileConnection que permite trabajar con ficheros de manera similar a un ordenador convencional●Este API no está disponible en todos los dispositivos●El acceso al sistema de ficheros requiere permisos especiales si la aplicación no está certificada, para evitar daños en el mismo

Sistemas operativos móviles

Page 46: progav-tema6

El siguiente ejemplo lee una imagen guardada en el dispositivo

FileConnection fc;InputStream is;

fc = (FileConnection) Connector.open(� /Imagenes/flower.jpg� , Connector.READ);is = fc.openInputStream();Image mi = Image.createImage(is);// Utilizar la imagen

is.close();

●La clase FileConnection permite abrir un stream de E/S al fichero pero también contiene operaciones para la creación, renombrado y borrado de ficheros y directorios

Sistemas operativos móviles

Persistencia II: Ficheros

Page 47: progav-tema6

●No obstante existe un problema importante: la estructura del sistema de ficheros de cada dispositivo no es estándar●Cada dispositivo contiene una raíz para cada uno de los medios de almacenamiento: memoria interna (/root, /internal, /InternalMemory) y tarjetas de memoria (/SDCard1, /MemoryCard)●Es posible enumerar las distintas raices existentes mediante el registro del sistema de ficheros:Enumeration raicesSF = FileSystemRegistry.listRoots();while (raicesSF.hasMoreElements()) {

raizSF = (String) raicesSF.nextElement(); // Hacer algo con la raiz encontrada}

Sistemas operativos móviles

Persistencia II: Ficheros

Page 48: progav-tema6

Este gestor de persistencia utiliza el API JSR 75

import java.io.*;import java.util.*;import javax.microedition.io.*;import javax.microedition.io.file.*;

class FileConnectionAPIInexistente extends Exception {}

public class DAOCuentaFC { static DAOCuentaFC instancia = null; String raizSF; public static DAOCuentaFC obtenerInstancia() throws FileConnectionAPIInexistente { if (instancia == null) { String versionFCAPI = System.getProperty( "microedition.io.file.FileConnection.version"); if (versionFCAPI == null) { throw new FileConnectionAPIInexistente(); } instancia = new DAOCuentaFC(); } return instancia; }

private DAOCuentaFC() { obtenerRaizSistemaFicheros(); }

Sistemas operativos móviles

Persistencia II: Ficheros

Page 49: progav-tema6

public boolean existe(long numero) { try { cargar(numero); } catch(Exception e) { return false; } return true; }

public Cuenta cargar(long numero) throws IOException { FileConnection fc = null; DataInputStream dis = null; Cuenta c = null; try { fc = (FileConnection) Connector.open(urlCuenta(numero), Connector.READ); if (!fc.exists()) { return null; } dis = fc.openDataInputStream(); c = new Cuenta(dis.readLong(), dis.readUTF(), dis.readFloat()); c.saldo = dis.readFloat();

Sistemas operativos móviles

Persistencia II: Ficheros

Page 50: progav-tema6

int nMov = dis.readInt(); for (int nm = 0; nm < nMov; nm++) { c.movimientos.addElement(new Movimiento(new Date(dis.readLong()), dis.readChar(), dis.readFloat(), dis.readFloat())); } } finally { if (fc != null) fc.close(); } return c; } public void salvar(Cuenta c) throws IOException { FileConnection fc = null; DataOutputStream dos = null; try { fc = (FileConnection) Connector.open("file:///" + raizSF + "cuentas", Connector.READ_WRITE); if (!fc.exists()) { fc.mkdir(); } fc.close(); fc = (FileConnection) Connector.open(urlCuenta(c.leerNumero()), Connector.READ_WRITE); if (!fc.exists()) { fc.create(); }

Sistemas operativos móviles

Persistencia II: Ficheros

Page 51: progav-tema6

dos = fc.openDataOutputStream();

dos.writeLong(c.leerNumero()); dos.writeUTF(c.leerTitular()); dos.writeFloat(c.leerInteres()); dos.writeFloat(c.leerSaldo());

Movimiento m; int nMov = c.numMovimientosHistorico(); dos.writeInt(nMov); for (int nm = 0; nm < nMov; nm++) { m = c.leerMovimientoHistorico(nm);

dos.writeLong(m.fecha.getTime()); dos.writeChar(m.tipo); dos.writeFloat(m.importe); dos.writeFloat(m.saldo); } } finally { if (fc != null) fc.close(); } }

private String urlCuenta(long codigo) { return "file:///" + raizSF + "cuentas/" + Long.toString(codigo) + ".cnt"; } private void obtenerRaizSistemaFicheros() { Enumeration raicesSF = FileSystemRegistry.listRoots(); if (raicesSF.hasMoreElements()) { raizSF = (String) raicesSF.nextElement(); } } } Sistemas operativos 

móviles

Persistencia II: Ficheros

Page 52: progav-tema6

●Otro problema adicional son las restricciones de seguridad existentes en algunos dispositivos, que sólo permiten el acceso a determinados directorios públicos (/Imagenes, /Sonidos, etc.)

Sistemas operativos móviles

Persistencia II: Ficheros

Page 53: progav-tema6

Para terminar

Para terminar●Hemos estudiado MIDP a nivel básico●En función de las necesidades de la aplicación móvil a implementar será necesario estudiar con mayor profundidad algunos de los APIs que hemos visto y otros nuevos

● PIM API JSR 75● API MIDP para juegos● Mobile Media API JSR JSR 184● Wireless Messaging API JSR 135● Bluetooth API JSR 82

Sistemas operativos móviles