Programación de juegos para móviles con J2ME

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

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP
SIGUIENTE ARTÍCULO