VERSIONES
- 25/01/2013 (Primera publicación)
- 19/10/2013: Aplicación de ejemplo para Jelly Bean 4.3
- Validar que hay disponible un directorio considerado de almacenamiento externo (que por ejemplo en el caso de Nexus 7 es en realidad interno) y que podemos leer/escribir en el mismo comprobando el valor según constante devuelto por getExternalStorageState.
Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
- Obtener la ruta completa a ese directorio usando la API de Android (getExternalStorageDirectory()) y a partir de ahí usar la API I/O estándar de java (File, Stream…) .
String path = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "file.txt";
- Recordar siempre que es necesario el permiso WRITE_EXTERNAL_STORAGE para poder escribir en la tarjeta/directorio.
<uses-permission android:name="android.permissions.WRITE_EXTERNAL_STORAGE" />
Y aunque no es necesario, Google recomienda solicitar permiso de lectura si sólo vamos a leer.
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
- Podemos afinar más, y comprobar si hay espacio suficiente disponible con la clase StatFs (en Android 4.3 hay métodos deprecated). En este ejemplo se obtiene el espacio total y el disponible en bytes y MB.
StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getAbsolutePath()); long available = ((long) stat.getAvailableBlocks() * (long) stat.getBlockSize()); long total = ((long) stat.getBlockCount() * (long) stat.getBlockSize()); float totalMB = (float)total/1024/1024; float availableMB = (float)available/1024/1024;
25/01/2013
Para guardar ficheros en un dispositivo Android es muy tentandor simplemente utilizar «/sdcard/» para acceder a la tarjeta de almacenamiento externa, o al menos al directorio que el dispositivo considere como tal ya que hoy en día algunos dispositivos carecen de esta funcionalidad pero ofrecen parte del almacenamiento interno accesible al usuario como si de una tarjeta SD se tratara.
Sin embargo, es una mala práctica ya que algún fabricante puede montar este directorio en otra ubicación, por ejemplo /media o /storage. La mejor solución es utilizar la clase Enviroment:
Si por curiosidad queremos saber si el almacenamiento externo es verdaderamente extraíble, podemos usar esta sentencia partir de API 9 (Gingerbread):
Environment.isExternalStorageRemovable();
Por ejemplo en la Nexus 7 devuelve falso, pero en la Galaxy Ace devuelve cierto (si la tarjeta de memoria está insertada y montada en el sistema de archivos).
Nota: si queremos almacenar datos internos de la aplicación no visibles por el usuario, y que además estos se eliminen tras su desinstalación deberemos utilizar el siguiente código en una Activity para obtener la ruta raiz (a partir de API 8 Froyo):
this.getExternalFilesDir(null).getAbsolutePath();
Este método devuelve rutas de este tipo: «/mnt/sdcard/Android/data/com.danieme.tipsandroid.demo/files».
Para probar este tip he creado un proyecto de ejemplo. Este es el resultado de su ejecución en tres dispositivos reales
HTC Desire con Froyo 2.2.2. Es un dispositivo que admite tarjetas SD pero no tiene insertada ninguna.
Samsung Galaxy ACE (Gingerbread 2.3.6) con una tarjeta SD insertada.
Samsung Galaxy Nexus (Jelly Bean 4.3), dispositivo que no admite tarjetas SD (vésae cómo simula la existencia del almacenamiento externo).
El proyecto completo para Eclise ADT se encuentra en Github. Para más información sobre cómo utilizar GitHub, consultar este artículo.