page.title=Acceso a directorios determinados page.keywords=preview,sdk,scoped directory access page.tags=androidn @jd:body

En este documento

  1. Acceder a un directorio de almacenamiento externo
  2. Acceder a un directorio de un medio extraíble
  3. Prácticas recomendadas

Las aplicaciones como las aplicaciones de fotografía generalmente solo necesitan acceso a directorios de almacenamiento externo, como el directorio Pictures. Los métodos existentes para acceder a almacenamiento externo no están diseñados para brindar un acceso fácil a determinados directorios para estos tipos de aplicaciones. Por ejemplo:

Android N brinda una API nueva y simplificada para acceder a directorios de almacenamiento externo comunes.

Acceder a un directorio de almacenamiento externo

Usa la clase StorageManager para obtener la instancia de StorageVolume correcta. Luego, crea una intent llamando al método StorageVolume.createAccessIntent() de esa instancia. Usa esta intención para acceder a directorios de almacenamiento externo. Para obtener una lista de todos los volúmenes disponibles, incluidos los volúmenes de medios extraíbles, usa StorageManager.getVolumesList().

Si tienes información sobre un archivo específico, usa StorageManager.getStorageVolume(File) para obtener el StorageVolume que contiene el archivo. Llama a createAccessIntent() en este StorageVolume para acceder al directorio de almacenamiento externo del archivo.

En el caso de los volúmenes secundarios, como las tarjetas SD externas, pasa un valor nulo cuando llames a StorageVolume.createAccessIntent() para solicitar acceso al volumen completo, en lugar de un directorio específico. StorageVolume.createAccessIntent() regresa un valor nulo si pasas un valor nulo para el volumen principal o si pasas un nombre de directorio no válido.

El siguiente fragmento de código es un ejemplo de cómo abrir el directorio Pictures en el almacenamiento compartido principal:

StorageManager sm = (StorageManager)getSystemService(Context.STORAGE_SERVICE);
StorageVolume volume = sm.getPrimaryVolume();
Intent intent = volume.createAccessIntent(Environment.DIRECTORY_PICTURES);
startActivityForResult(intent, request_code);

El sistema intenta otorgar acceso al directorio externo y, si es necesario, confirma el acceso con el usuario usando una IU simplificada:

Imagen 1. Una aplicación solicitando acceso al directorio Pictures.

Si el usuario otorga el acceso, el sistema llama a tu anulación de onActivityResult() con un código resultante de Activity.RESULT_OK y datos de intents que contienen el URI. Usa el URI brindado para acceder a la información del directorio. Es similar a usar URI generados por el framework de acceso al almacenamiento.

Si el usuario no otorga el acceso, el sistema llama a tu anulación de onActivityResult() con un código resultante de Activity.RESULT_CANCELED y datos de intents nulos.

Nota: Obtener acceso a un directorio externo específico también otorga el acceso a los subdirectorios de ese directorio.

Acceder a un directorio de un medio extraíble

Para usar el acceso a directorios determinados para acceder a directorios de medios extraíbles, primero debes agregar un {@link android.content.BroadcastReceiver} que escuche la notificación{@link android.os.Environment#MEDIA_MOUNTED}, por ejemplo:

<receiver
    android:name=".MediaMountedReceiver"
    android:enabled="true"
    android:exported="true" >
    <intent-filter>
        <action android:name="android.intent.action.MEDIA_MOUNTED" />
        <data android:scheme="file" />
    </intent-filter>
</receiver>

Cuando el usuario conecta un medio extraíble, como una tarjeta SD, el sistema envía una notificación{@link android.os.Environment#MEDIA_MOUNTED}. Esta notificación brinda un objeto StorageVolume en los datos de intents que puedes usar para acceder a directorios del medio extraíble. El siguiente ejemplo accede al directorio Pictures de medios extraíbles:

// BroadcastReceiver has already cached the MEDIA_MOUNTED
// notification Intent in mediaMountedIntent
StorageVolume volume = (StorageVolume)
    mediaMountedIntent.getParcelableExtra(StorageVolume.EXTRA_STORAGE_VOLUME);
volume.createAccessIntent(Environment.DIRECTORY_PICTURES);
startActivityForResult(intent, request_code);

Prácticas recomendadas

Cuando sea posible, sigue usando el URI de acceso a directorios externos de modo que no tengas que solicitarle acceso al usuario continuamente. Una vez que el usuario haya otorgado el acceso, llama a getContentResolver().takePersistableUriPermssion() con el URI de acceso a directorios. El sistema continuará el URI, y las siguientes solicitudes de acceso generarán RESULT_OK y no le mostrarán una IU de confirmación al usuario.

Si el usuario deniega el acceso a un directorio externo, no vuelvas a solicitar el acceso inmediatamente. Hacer esto provocaría una mala experiencia de usuario. Si el usuario deniega una solicitud y la aplicación solicita acceso nuevamente, aparece la casilla de verificación Don't ask again en la IU:

Figura 1. Una aplicación que presenta una segunda solicitud para obtener acceso a medios extraíbles.

Si el usuario selecciona Don't ask again y deniega la solicitud, todas las solicitudes futuras que presente la aplicación para el directorio determinado se denegarán automáticamente, y el usuario no recibirá ninguna IU de solicitud.