progav-tema6

Post on 24-Oct-2014

26 Views

Category:

Documents

2 Downloads

Preview:

Click to see full reader

TRANSCRIPT

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

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

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

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

●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

●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

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

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

●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

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

●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

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

●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

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

●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

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

}}

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

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

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

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

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

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

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);

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

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);

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

} } }

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); }

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(); } } }

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()); }

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); } } }

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

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()

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)

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

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(); } }

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; }

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(); } }

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; }}

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()

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(); } } }

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.

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();

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; }

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"; }}

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

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

●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

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

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

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

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

●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

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

top related