28/4/14

[Tutorial] Guardar información cifrada (libGDX)

Buenas gente!

Como bien sabéis, la mayoría de las aplicaciones necesitan guardar cierta información, como puede ser puntuaciones, niveles, opciones de música o sonido, etc. Alguna información no es necesario ocultarla, como puede ser la configuración del perfil que se puede cambiar en el menú de opciones (el volumen al que queremos la música, etc.) pero otra información importante no queremos que esté a simple vista y que cualquiera pueda cambiarla fácilmente (por ejemplo la puntuación máxima que hemos obtenido en el juego, etc.). Esta última información irá cifrada.

En esta entrada veremos como guardar la información tanto cifrada como no.

Adaptando nuestras clases para guardar en fichero


Para guardar nuestra información en un fichero crearemos una clase que contenga esa información e implemente la interfaz Serializable.

Veremos un ejemplo con una clase Profile donde guardaremos algunos datos del perfil del jugador de nuestra aplicación:


Como podemos ver necesitamos dos funciones, una para guardar nuestros datos en fichero y otra para leerlos.

En la función write guardaremos valor a valor con la función:


El nombre que pongamos aquí será el que tengamos que usar para leer esa variable del fichero.

Como nota especial, para guardar un vector o una lista indicaremos el comienzo y el final de la lectura del vector con:


En la función read leeremos todos los valores usando los nombres que les pusimos en la función anterior e indicando la clase de cada variable (Integer.class para tipo int, String.class para las cadenas de caracteres, etc.).


Con esto ya tenemos lista nuestra clase para que sea guardada y leída en un fichero de tipo JSON.

Creando la clase de lectura y escritura de datos


Una vez que tenemos las clases que queremos guardar serializadas vamos a crear una clase que se encargue de organizarlo todo, de modo que con una llamada a una función de esta clase se guarden todos los datos, se creen los que no estén creados, etc. La clase debe ser parecida a esta:


En una variable de la clase guardaremos la dirección del fichero donde queremos guardar todos los datos, y tendremos una variable de cada clase que queramos leer/escribir en fichero.

Esta clase además tiene dos funciones: Read y Write, veamos que hace cada una de ellas.

  • Función read()

Si ya existe un perfil creado devuelve ese perfil.

Crea un nuevo objeto de tipo Json para tratar con él y crea un enlace con el fichero que le hemos indicado. Si no existiese el fichero el mismo se encargaría de crearlo.

Si existe ese archivo mira a ver si tiene información correcta. Para ello guarda toda la información en un String y lo decodifica (Si no necesitáis la información codificada podéis borrar la línea 14 y usar en la línea 16 profileAsCode en vez de profileAsText). Una vez tiene la información se la pasa a nuestra clase Profile para que tome los datos de ella (Si se tienen varias clases se les pasa a todas las clases).

Si no existe el fichero crea un nuevo perfil (si tienes más clases las creas aquí también) y lo guarda en el nuevo fichero creado.

  • Función write(Clases_a_leer)

Esta función crea un nuevo Json para tratar con él, y el enlace al fichero en el que escribiremos los datos.

Crea un String con los datos obtenidos de la clase Profile (Si tenéis más de una es solo concatenar las cadenas resultantes de leer todas las clases).

Despues codifica la información (de nuevo si no queréis información codificada podéis eliminar esta línea y sustituir en la línea 36 el profileAsCode por la variable profileAsText).

Una vez está la información lista para ser escrita la pasa al fichero.

Y con esto ya podremos guardar nuestros datos en un fichero de forma segura.

Ahora solo tendremos que llamar a nuestro ProfileSerializer.read() o ProfileSerializer.write(...) cada vez que queramos obtener los datos de perfil (por ejemplo al inicio de la aplicación, cuando seleccionamos una partida concreta, etc.) y guardar esos datos (por ejemplo al terminar una partida, al llegar a ciertos puntos, al cerrar la aplicación...).

Notas:


  •   El fichero se ha guardado en local, de modo que si se ejecuta nuestra aplicación en un ordenador se creará el fichero a partir de la ruta por defecto del usuario, es decir, en su carpeta personal.
  • Es recomendable poner un “.” delante del nombre de la carpeta donde vamos a guardar nuestros datos ya que en algunos sistemas como Linux esto indica que es una carpeta oculta y no nos molestará a la vista una vez creada.
  • El archivo puede tener la extensión que queramos, los más comunes son .json, .dat o .txt.

4 comentarios:

  1. muy buenos tutos!!
    Una consulta.. como hago para guardar una matriz.. ej: Array< Array>

    ResponderEliminar
    Respuestas
    1. No se si existirá una forma más fácil, pero siempre puedes hacer un bucle for recorriendo el Array e ir guardando cada uno de los Arrays que tiene dentro como cualquier otro Array.
      Espero que te sirva ^^

      Eliminar
    2. eso intente y arrojo error :P ahora pruebo de nuevo! gracias por dar una respuesta tan rapida!

      Eliminar
  2. Estube leyendo un poco y llege a esto que parece ser bastante efectivo...
    public static void save(Object p, FileHandle file) {
    Json json = new Json();
    json.setOutputType(OutputType.json);
    file.writeString(Base64Coder.encodeString(json.toJson(p)), false);
    }

    public static Object load(FileHandle file, Class type) {
    Object o = null;
    Json json = new Json();
    o = json.fromJson(type, Base64Coder.decodeString(file.readString()));
    return o;
    }

    ResponderEliminar