Download - progav-tema6
![Page 1: progav-tema6](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/1.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/2.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/3.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/4.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/5.jpg)
●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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/6.jpg)
●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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/7.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/8.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/9.jpg)
●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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/10.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/11.jpg)
●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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/12.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/13.jpg)
●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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/14.jpg)
Paquetes opcionales en J2ME●Permiten extender la funcionalidad básica de los perfiles para aprovechar todas las posibilidades del dispositivo●Wireless Messaging API (WMA) JSR120, JSR205. Envío de mensajes SMS.●Mobile Media API (MMAPI) JSR135. Soporte de audio y video, tanto reproducción como captura ●Location API JSR179. Localización geográfica del dispositivo, mediante GPS u otros mecanismos
Paquetes opcionales en J2ME
Sistemas operativos móviles
![Page 15: progav-tema6](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/15.jpg)
●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) JSR172. 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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/16.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/17.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/18.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/19.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/20.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/21.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/22.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/23.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/24.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/25.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/26.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/27.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/28.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/29.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/30.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/31.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/32.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/33.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/34.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/35.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/36.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/37.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/38.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/39.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/40.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/41.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/42.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/43.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/44.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/45.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/46.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/47.jpg)
●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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/48.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/49.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/50.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/51.jpg)
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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/52.jpg)
●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](https://reader031.vdocumento.com/reader031/viewer/2022020206/544b3891b1af9f884f8b4f77/html5/thumbnails/53.jpg)
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