Almacenamiento interno

Para que una aplicación Android pueda gestionar datos en guardados en ficheros dentro del almacenamiento interno del dispositivo, dispones de los métodos getFilesDir()getCacheDir() de la clase Context, que los puedes usar directamente en una Activity, ya que es una subclase de la anterior. Ambos métodos retornan un objeto File que hace referencia a la carpeta donde podrás almacenar ficheros de forma privada (las otras aplicaciones no podrán acceder a estos ficheros)

Debes tener en cuenta que si el usuario desinstala la aplicación, los ficheros almacenados en esas carpetas también son eliminados.

La diferencia que hay entre los métodos getFilesDir y getCacheDir radica en que los ficheros almacenados en la carpeta indicada por el segundo método pueden ser eliminados en cualquier momento por el sistema si necesita espacio de almacenamiento. Se trata de una carpeta que se puede usar como caché, por lo que en ella sólo se deberían almacenar ficheros temporales.

Los ficheros se almacenarán en la carpeta /data/data/com.paquete.aplicacion, dentro de las subcarpetas files o cache en cada caso, como puedes ver desde la ventana File Explorer que puedes abrir en Eclipse (Windows > Show View > Other > File Explorer).

fich01

Almacenamiento externo (SD Card)

El almacenamiento interno de los dispositivos Android suele tener una capacidad bastante limitada. Por lo que si se necesita tener un almacenamiento mayor, es recomendable almacenar la información en el almacenamiento externo, que suele ser una tarjeta de memoria SD extraíble, y a la que se puede acceder desde el PC. Ten en cuenta también que los datos almacenados en el soporte externo podrían ser leídos por cualquier otra aplicación y manipulados por el usuario.

Comprobar disponibilidad

El almacenamiento externo puede dejar de estar disponible si el usuario lo monta en un ordenador o extrae el soporte. Por tanto, no hay seguridad de que los ficheros manejados por la aplicación puedan ser almacenados, y antes de realizar cualquier operación hay que comprobar la disponibilidad del almacenamiento. Puedes comprobarlo usando el método getExternalStorageState() de la clase Environment:

static String getExternalStorageState ()

Retorna un String que puede ser comparado con las constantes declaradas en la misma clase EnvironmentMEDIA_MOUNTED y MEDIA_MOUNTED_READ_ONLY.

Por ejemplo, puedes usar un código similar al siguiente:

{code}String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
    // Se puede leer y escribir en el almacenamiento
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
    // Sólo se puede leer
} else {
    // No se puede leer ni escribir
}{/code}

Asignación de permisos a la aplicación

Si la aplicación va a escribir datos en el almacenamiento externo, hay que asignarle el permiso WRITE_EXTERNAL_STORAGE en el archivo de manifiesto.

fich02

Acceso a los ficheros en el almacenamiento externo

La ruta correspondiente al almacenamiento que corresponde a la aplicación se puede obtener llamando al método getExternalFilesDir(), de la clase Context, para la API a partir de nivel 8, obteniendo un objeto File con dicha ruta.

abstract File getExternalFilesDir (String type)

Se le pasa por parámetro el tipo de contenido que van tener los ficheros que se van a almacenar, de manera que se guardarán en una subcarpeta u otra en función del tipo de contenido. Si no se desea almacenar los ficheros en una de esas subcarpetas, se debe indicar null como parámetro. En otro caso, estos son los tipos que se pueden indicar, como constantes estáticas de la clase Environment, que guardarán los datos en la carpeta que se especifica también a continuación:

Esta estructura de subcarpetas facilita la búsqueda de recursos multimedia a otras aplicaciones. Recuerda que los datos almacenados en estas carpetas serán eliminados si el usuario desinstala la aplicación.

En cualquier caso, los ficheros se almacenarán a partir de la carpeta /mnt/sdcard/Android/data/com.paquete.aplicacion/files, como se puede ver en la siguiente imagen:

fich03

Si estás usando una API de nivel 7 (Android 2.1) o anterior, se debe usar el método getExternalStorageDirectory() que retorna un objeto File que hace refencia a la carpeta del almacenamiento externo (/mnt/sdcard). La propia aplicación debe encargarse de almacenar los datos en la carpeta correspondiente a la aplicación, siguiendo la ruta especificada anteriormente (/Android/data/com.paquete.aplicacion/files).

 

Ficheros compartidos con otras aplicaciones

Si se deseas almacenar ficheros que no sean específicos de tu aplicación, y que no se deban eliminar cuando la aplicación se desinstale, se deben localizar en las carpetas públicas del almacenamiento externo. Estas carpetas cuelgan de la carpeta raíz del almacenamiento externo (/mnt/sdcard) con los nombres correspondientes al tipo de contenido como se ha visto antes.

A partir de la API 8, se usa el método getExternalStoragePublicDirectory(), indicando como parámetro el tipo de recurso como ya se ha visto.

static File getExternalStoragePublicDirectory (String type)

Ficheros caché

Si los ficheros utilizados van a ser temporales, se deberían almacenar como caché en el almacenamiento externo. Puedes hacerlo usando el método getExternalCacheDir() a partir de la API 8, que almacena este tipo de archivos en la subcarpeta cache. La aplicación debe ser la encargada de eliminar los ficheros que se desee dejar de utilizar, y todos serán eliminados si el usuario desinstala la aplicación

Clases para la manipulación de ficheros

A partir del objeto File que has podido obtener anteriormente con cualquiera de los métodos vistos (getFilesDir, getCacheDir, getExternalFilesDir, getExternalStorageDirectory, getExternalStoragePublicDirectory, getExternalCacheDir), puedes usar las mismas clases que hay en Java para la gestión de ficheros además de los métodos que ofrece dicha clase File (FileInputStream, FileOutputStream, FileReader, FileWriter, BufferedReader, BufferedWriter, RandomAccessFile, etc).

A continuación puedes ver un ejemplo, en el que se guarda una cadena de caracteres en un fichero llamado datos_cache.dat, en la carpeta de caché, usando la clase RandomAccessFile.

{code class="highlight:[1]"}File directorioCache = getCacheDir();
File fichPrueba = new File(directorioCache, "datos_cache.dat");
try {
    RandomAccessFile raf = new RandomAccessFile(fichPrueba, "rw");
    raf.writeBytes("Contenido a guardar\n");
raf.close();
} catch (FileNotFoundException e) {
    Toast mensaje = Toast.makeText(this, "Error al abrir el fichero", Toast.LENGTH_LONG);
    mensaje.show();
    e.printStackTrace();
} catch (IOException e) {
    Toast mensaje = Toast.makeText(this, "Error al escribir en el fichero", Toast.LENGTH_LONG);
    mensaje.show();
    e.printStackTrace();
}{/code}