lunes, 9 de febrero de 2015

Programación de juegos para móviles con J2ME Parte X

Almacenamiento. RMS

Hasta ahora hemos usado la memoria principal del móvil (la RAM) para almacenar datos temporales, pero al salir del midlet, estos datos son eliminados. Esto plantea algunos problemas. Por ejemplo, ¿cómo podemos almacenar las puntuaciones máximas de nuestro juego?
Un dispositivo móvil (al menos por ahora) no dispone de disco duro donde almacenar información permanentemente. J2ME resuelve el problema mediante el RMS (Record Management System). RMS es un pequeño sistema de bases de datos muy sencillo, pero que nos permite añadir información en una memoria no volátil del móvil. RMS no tiene nada que ver con JDBC debido a las limitaciones de los dispositivos J2ME, por lo tanto, el acceso y almacenamiento de la información se hace a mucho más bajo nivel. RMS no puede ser consultado con sentencias SQL ni nada parecido. En una base de datos RMS, el elemento básico es el registro (record). Un registro es la unidad de información más pequeña que puede ser almacenada. Los registros son almacenados en un recordStore que puede visualizarse como una colección de registros. Cuando almacenamos un registro en el recordStore, a éste se le asigna un identificador único que identifica unívocamente al registro.
Para poder utilizar RMS hemos de importar el paquete javax.microedition.rms. Este paquete nos provee de la clase RecordStore y de cuatro interfaces, de las cuales solamente profundizaremos en la interfaz RecordEnumeration.

Trabajando con RMS

Cubrir todas las capacidades de RMS se escapa del ámbito de este libro. Sin entrar en profundidades, vamos a ver cómo realizar las operaciones básicas de almacenamiento, lectura y borrado de registros.

Abrir y errar un recordStore

Antes de poder almacenar un registro hemos de abrir un recordStore con el método openRecordStore().
static RecordStore openRecordStore(String nombre, bolean crear)
El parámetro nombre es el nombre de la base de datos. El nombre puede tener un tamaño de 32 caracteres. El parámetro crear, si tiene su valor a true, creará la base de datos si no existe. Cuando creamos un recordStore, sólo puede ser accedido desde la suite de MIDlets que la creó.
Cuando terminamos de utilizar el recordStore, hemos de cerrarlo:
RecordStore.closeRecordStore();

Añadir registros

Una vez abierto nuestro recordStore podemos comenzar a añadir registros con el método addRecord().
public int addRecord(byte[] dato,int offset, int numBytes)
El primer parámetro es el dato que queremos almacenar. Es un array de bytes. El offset es la posición a partir de la cual (dentro del array) se va a almacenar el dato. Finalmente, numBytes es el número de bytes que se van a almacenar. El método retorna el identificador que el RMS ha asignado al registro.
El método addRecord puede lanzar la excepción RecordStoreException, por lo tanto hemos de capturarla.
try {
    int id = recordStore.addRecord (datos, 0, datos.length);
} catch (RecordStoreException e) {}

Leer registros

El método getRecord() permite acceder al registro que deseemos, siempre que conozcamos su identificador.
public byte[] getRecord(int Id)
No es necesario que almacenemos y mantengamos una lista con todos los identificadores de los registros. Un poco más adelante veremos el método recordEnumeration que nos permitirá conocer el identificador de cada registro. Al igual que con el método addRecord(), hemos de capturar la excepción RecordStoreException.
byte[] dato = null;

try {
    dato = recordStore.getRecord(id);
} catch (RecordStoreException e) {}

Borrar registros

El borrado de registros se realiza con el método deleteRecord().
public void deleteRecord(int recordId)
Al igual que con la escritura y lectura de registros hemos de tener en cuenta que puede provocar la excepción RecorStoreException.
try {
    recordStore.deleteRecord(id);
} catch (RecordStoreException e) {}

Recorriendo registros

Vamos a valernos del objeto RecordEnumeration para recorrer todos los registros almacenados en la base de datos. Para crear una enumeración utilizamos el método enumerateRecords().
public RecordEnumeration enumerateRecords(RecordFilter filtro,
    RecordComparator, comparador,boolean Actualizar)
Los dos primeros parámetros sirven para personalizar el recorrido de los registros. No entraremos en detalle, pero, gracias al primero podremos filtrar la búsqueda, y con el segundo podemos recorrer los registros de forma ordenada. El parámetro Actualizar indica si la enumeración debe actualizarse cuando realicemos alguna operación de inserción o borrado de registros. Si vas a hacer un recorrido rápido por los registros es mejor ponerlo a false para evitar la sobrecarga.
RecordEnumeration registro = null;

try {
    registro = recordStore.enumerateRecords(null, null, false);
    while (registro.hasNextElement()) 
        System.out.println (registro.nextRecordId());
} catch (Exception e) {}
Hay dos métodos interesantes del RecordEnumeration: hasNextElement() que devolverá el valor true si hay un siguiente elemento disponible para ser leído. Cada vez que leemos un elemento se adelanta el puntero al siguiente. El método nextRecordId() devuelve el identificador del siguiente registro.
El siguiente código muestra un ejemplo completo de uso de RMS.
import java.io.*;
import javax.microedition.midlet.*;
import javax.microedition.rms.*;

public class RMS extends MIDlet {

// nombre de la BD
static final String BD = "datos";

String dato;
int id, i;
char b;

public RMS() {
RecordStore rs = null;

// Borramos la BD si tenía algo
try {
RecordStore.deleteRecordStore(BD);
} catch( Exception e ){}

try {
// Abrimos el recordStore
rs = RecordStore.openRecordStore(BD, true);

guardaRegistro(rs,"Datos del registro 1");
guardaRegistro(rs,"Datos del registro 2");
guardaRegistro(rs,"Datos del registro 3");

// Leemos los registros
RecordEnumeration registros = rs.enumerateRecords(null, null, false);
// Recorremos todos los elementos
while (registros.hasNextElement()) {

// Obtenemos el ID del siguiente registro
verRegistro(rs, registros.nextRecordId());
}
rs.closeRecordStore();
} catch( RecordStoreException e ){
System.out.println( e );
}
notifyDestroyed();
}

public void verRegistro(RecordStore rs, int id) {
try {
ByteArrayInputStream bais = new ByteArrayInputStream(rs.getRecord(id));
DataInputStream is = new DataInputStream(bais);
// leemos el registro
try {
dato = is.readUTF();
System.out.println("-> "+dato);
} catch (EOFException eofe) {
} catch (IOException ioe) {}
} catch (RecordStoreException e) {}
}

public void guardaRegistro(RecordStore rs, String dato) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream os = new DataOutputStream(baos);
try {
// guadar el dato
os.writeUTF(dato);
} catch (IOException ioe) {}

// extraer el array de butes
byte[] b = baos.toByteArray();

// lo añadimos al recordStore
try {
rs.addRecord(b, 0, b.length);
} catch (RecordStoreException rse) {}
}

public void destroyApp( boolean unconditional ) {}

public void startApp() {}

public void pauseApp() {}
}

No hay comentarios.:

Publicar un comentario