Taller de Programación de Dispositivos Móvileszeus.inf.ucv.cl/~jrubio/docs/2010-2/ICI...

40
Taller de Programación de Dispositivos Móviles José Miguel Rubio L. Oficina 3-20 http://www.inf.ucv.cl/~jrubio [email protected]

Transcript of Taller de Programación de Dispositivos Móvileszeus.inf.ucv.cl/~jrubio/docs/2010-2/ICI...

Taller de Programación de Dispositivos Móviles

José Miguel Rubio L.Oficina 3-20

http://www.inf.ucv.cl/[email protected]

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

MIDP: Midlets

MIDP: MIDlets

●Una aplicación MIDP requiere la implementación de un MIDlet, cuya estructura recuerda los Appletsy 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

} }

Sistemas operativosmóviles

MIDP: Midlets

●De manera similar a un Applet, un MIDlet requierela 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 astartApp() o la terminación definitiva mediante lallamada a destroyApp().

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

Sistemas operativosmóviles

MIDP: Midlets

●Un conjunto de MIDlets se distribuye en un fichero.jar

●El MANIFEST del fichero jar es más complicado quelos que conocemos

●Primero se indica el nombre global del conjunto deMIDlets del fichero jar, su versión, autor y las versio-nes de CLDC y MIDP necesarias ●Después cada MIDlet se describe mediante un nom-bre, el icono correspondiente y el nombre de la clase que lo implementa

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

Sistemas operativosmóviles

MIDP: Interfaces Gráficasde Usuario

MIDP: Interfaces Gráficas de Usuario

●MIDP proporciona una forma sencilla de construirinterfaces de usuario adaptada a las limitaciones depantalla, potencia de cálculo y batería de los dispo-sitivos móviles. ●En comparación con toolkits como Swing, la varie-dad y número de componentes existentes es muypequeño. ●La interfaz se construye a base de distintas panta-llas, en lugar de ventanas o diálogos. ●Las acciones del usuario definen la transición de una pantalla a otra .

Sistemas operativosmóviles

MIDP: Interfaces Gráficasde Usuario

●Es importante tener en cuenta el pequeño tamañola pantalla del dispositivo a la hora de diseñar lainterfaz. ●La mayoría de los dispositivos dispone de un parde botones de acción cuyo efecto se puede progra-mar para cada pantalla.

Sistemas operativosmóviles

MIDP: Interfaces Gráficasde Usuario

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

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

d.setCurrent(Displayable pantalla) ●Una vez obtenido el display, el MIDlet sigue elsiguiente esquema de funcionamiento: 1.Crear una pantalla 2.Mostrarla mediante setCurrent() 3.Esperar las acciones del usuario 4.Elegir otra pantalla en función de estas acciones (volver a 1)

Sistemas operativosmóviles

MIDP: Interfaces Gráficasde Usuario

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

TextBox List Alert Form

Sistemas operativosmóviles Canvas

●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 indicarel siguiente displayable a mostrar tras el Alert

Alert a = new Alert( Error , Error al salvar la in formación , null, AlertType.ERROR);

a.setTimeout(5000);

d.setCurrent(a, siguienteDisp);

móviles

MIDP: Interfaces Gráficasde Usuario

●El displayable Form permite definir una pantallacon 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

móviles

MIDP: Interfaces Gráficasde Usuario

●Los Form permiten crear interfaces mucho más ricas: Form f = new Form("Ficha deportiva"); f.append(new TextField("Apellidos", null, 40, TextF ield.ANY)); f.append(new TextField("Nombre", null, 40, TextFiel d.ANY)); f.append(new DateField("Fecha de nacimiento", DateFi eld.DATE)); f.append(new TextField("E-mail", null, 20, TextField.EMAILADDR)); String[] tipos = {"Profesor", "Alumno"}; f.append(cg = new ChoiceGroup("Tipo", ChoiceGroup.EX CLUSIVE, tipos, null));

d.setCurrent(f);

Sistemas operativosmóviles

●Para asociar acciones a los botones del dispositivose utiliza la clase Command

●Las activación de un comando es capturada porun CommandListener, cuya única operación es

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

// Procesar el comando }

} }

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

Tarea:Siguiendo el ejemplo que hemos desarrollado en la asignatura, crear unvisor 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, cMovimiento s;

private Form fPeticionCodigo, fInfoCuenta; private List lMovCuenta;

public MidletCuenta() { d = null;

}

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

MIDP: Interfaces Gráficasde 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ódig o de cuenta ", null, 10, TextField.NUMERIC)); fPeticionCodigo.addCommand(cEntrar); fPeticionCodigo.addCommand(cSalir);

fPeticionCodigo.setCommandListener(new listenerPetic ionCodigo()); tCodigo.setLayout(Item.LAYOUT_2 | Item.LAYOUT_CENT ER); }

class listenerPeticionCodigo implements CommandListene r { public void commandAction(Command cm, Displayable s) { if(cm == cEntrar) {

// Cargar la cuenta aquí

crearFormInformacionCuenta(); d.setCurrent(fInfoCuenta); } elseif (cm == cSalir) { destroyApp(true);

notifyDestroyed(); }

} }

Sistemas operativosmóviles

MIDP: Interfaces Gráficasde Usuario

void crearFormInformacionCuenta() { // Crear formulario de información dae la cuenta fIn foCuenta = newForm("Información de cuenta"); fInfoCuenta.append(n ewStringItem("Código:", Long.toString(c.leerNumero()) ));

fInfoCuenta.append(new StringItem("Titular:", c.leer Titular()));

fInfoCuenta.append(new StringItem("Interés:", Float.toString(c.leerInteres()))); fInfoCuenta.appe nd(newStringItem("Saldo:", Float.toString(c.leerSaldo())) );

fInfoCuenta.addCommand(cMovimientos); fInfoCuenta.addCommand(cVolver); fInfoCuenta.setCommandListener(new listenerInformaci onCuenta());

// 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.t ipo + '

' + m.importe + ' ' + m.saldo, null); }

lMovCuenta.addCommand(cVolver); lMovCuenta.setCommandListener(new listenerInformacio nMovimientos());

}

Sistemas operativosmóviles

MIDP: Interfaces Gráficasde Usuario

class listenerInformacionCuenta implements CommandList ener{ public void commandAction(Command cm, Displayable s) { if(cm == cVolver) {

d.setCurrent(fPeticionCodigo); } else if (cm == cMovimientos) { d.setCurrent(lMovCuenta); }

} }

class listenerInformacionMovimientos implements Comman dListener { public void commandAction(Command cm, Displayable s) {

if (cm == cVolver) { d.setCurrent(fInfoCuenta);

} }

}

Sistemas operativosmóviles

MIDP: Persistencia

MIDP: Persistencia

●La capacidad de almacenamiento persistente de undispositivo móvil puede ser muy limitada.

●El soporte de tarjetas de memoria, cada vez máscomún, ha aumentado mucho las prestaciones (8Gben iPhone o Nokia N95) posibilitando una estructurade ficheros similar a la de un computador convencional. ●Sin embargo el perfil MIDP es conservador y pro-porciona un soporte sencillo de persistencia a través de registros de bloques de bytes.

Sistemas operativosmóviles

MIDP: Persistencia

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

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

closeRecordStore()

Sistemas operativosmóviles

MIDP: Persistencia

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

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

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)

Sistemas operativosmóviles

MIDP: Persistencia

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

RecordStore rs = RecordStore.openRecordStores( ejem plo, true);

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

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

}

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

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

Sistemas operativosmóviles

MIDP: Persistencia

Tarea:Crear un gestor de persistencia para las cuentas corrientes medianteun 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 RecordStore Exception, IOException{ RecordStore rs = null; try { rs = RecordStore.openRecordStore("cuentas", true); return (buscarRegistroCuenta(rs, numero) != -1); } finally {

if (rs != null) rs.closeRecordStore(); }

}

Sistemas operativosmóviles

MIDP: Persistencia

public Cuenta cargar(long numero) throws RecordStoreE xception, 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(newByteArrayInputStream(rs.getRecord(idReg))); c = ne wCuenta(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; }

Sistemas operativosmóviles

MIDP: Persistencia

public void salvar(Cuenta c) throws RecordStoreExceptio n, IOException{ RecordStore rs = null; ByteArrayOutputStream bos = null; DataOutputStream dos = null; try {

rs = RecordStore.openRecordStore("cuentas", true); d os = newDataOutputStream(bos = new ByteArrayOutputStream());

dos.writeLong(c.leerNumero()); dos.writeUTF(c.leerT itular()); dos.writeFloat(c.leerInteres()); dos.writeFloat(c.l eerSaldo());

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

} Sistemas operativos

móviles

MIDP: Persistencia

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(newByteArrayInputStream(rs.getRecord(id))); recNum = di s.readLong(); if (recNum == numero)

{ return id; } dis.close(); dis = null;

} } finally { if (dis != null) dis.close(); if (re != null) re.destroy();

}

return -1; }

}

Sistemas operativosmóviles

MIDP: Persistencia

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

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

Sistemas operativosmóviles

MIDP: Persistencia

class listenerPeticionCodigo implements CommandListene r { 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); } elseif (cm == cSalir) { destroyApp(true);

notifyDestroyed(); }

} }

Sistemas operativosmóviles

MIDP: Conexión por red

MIDP: Conexión por red

●MIDP es especialmente potente en lo que se refie-re a la conexión por red mediante sockets, http yotros protocolos ●La clase Connection representa una conexión ge-nérica y es extendida a tres conexiones que admi-ten E/S mediante streams: InputConnection, Output-Connection y StreamConnection●La clase StreamConnection es extendida a variasclases que representan distintos tipos de conexiones:

CommConnection, HttpConnection, httpsConnection,SocketConnection, etc.

Sistemas operativosmóviles

MIDP: Conexión por red

●La clase Connector es una factoría que a partir de un url devuelve la clase de conexión correspon-diente: 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 streamde lectura o escritura HttpConnection con1; con1 = (HttpConnection) Connector.open(http://www .google.es/search?hl=es&q=j2me);

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

Sistemas operativosmóviles

MIDP: Conexión por red

Ejemplo:El siguiente gestor de persistencia obtiene los datos de la cuentadesde 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;

} Sistemas operativos

móviles

MIDP: Conexión por red

public Cuenta cargar(long numero) throws IOException{ InputConnection ic = null; DataInputStream dis = null; Cuenta c = null;

try { ic = (InputConnection) Connector.open(urlCuenta(num ero)); dis = ic.openDataInputStream(); c = new Cuenta(dis.readLong(), dis.readUTF(), dis.r eadFloat()); 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 returnnull;

} finally { if (ic != null) ic.close();

}

return c; }

private String urlCuenta(long codigo) { return "http://robin.ujaen.es/asignaturas/progav/cu entas/"

+ Long.toString(codigo) + ".cnt"; }

}

Sistemas operativosmóviles

Persistencia II: Ficheros

Persistencia II: Ficheros

●El File Connection and PIM API (JSR 75) defineun nuevo tipo de conexión denominado FileConnec-tion que permite trabajar con ficheros de manerasimilar a un computador convencional. ●Este API no está disponible en todos los disposi-tivos. ●El acceso al sistema de ficheros requiere permisosespeciales si la aplicación no está certificada, paraevitar daños en el mismo.

Sistemas operativosmóviles

Persistencia II: Ficheros

El siguiente ejemplo lee una imagen guardada en el dispositivo

FileConnection fc; InputStream is;

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

is.close();

●La clase FileConnection permite abrir un stream deE/S al fichero pero también contiene operacionespara la creación, renombrado y borrado de ficherosy directorios.

Sistemas operativosmó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 operativosmó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 Fil eConnectionAPIInexistente{ 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 operativosmó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(nume ro), Connector.READ); if (!fc.exists()) {

return null; }

dis = fc.openDataInputStream(); c = new Cuenta(dis.readLong(), dis.readUTF(), dis.readFloat()); c.saldo = dis.readFloat();

Sistemas operativosmó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 operativosmó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() { Enumerat ionraicesSF = FileSystemRegistry.listRoots(); if(raicesSF.hasMoreElements()) {

raizSF = (String) raicesSF.nextElement(); }

} } Sistemas operativos

móviles

Persistencia II: Ficheros

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

Sistemas operativosmóviles

Para terminar

Para terminar

●Hemos estudiado MIDP a nivel básico ●En función de las necesidades de la aplicaciónmóvil a implementar será necesario estudiar conmayor 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