1 page.title=Acceso a directorios determinados 2 page.keywords=preview,sdk,scoped directory access 3 page.tags=androidn 4 5 @jd:body 6 7 <div id="tb-wrapper"> 8 <div id="tb"> 9 <h2>En este documento</h2> 10 <ol> 11 <li><a href="#accessing">Acceder a un directorio de almacenamiento externo</a></li> 12 <li><a href="#removable">Acceder a un directorio de un medio extrable</a></li> 13 <li><a href="#best">Prcticas recomendadas</a></li> 14 </ol> 15 </div> 16 </div> 17 18 <p>Las aplicaciones como las aplicaciones de fotografa generalmente solo necesitan acceso a directorios de 19 almacenamiento externo, como el directorio <code>Pictures</code>. Los mtodos 20 existentes para acceder a almacenamiento externo no estn diseados para brindar un 21 acceso fcil a determinados directorios para estos tipos de aplicaciones. Por ejemplo:</p> 22 23 <ul> 24 <li>Solicitar {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} 25 o {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} en tu manifiesto 26 permite el acceso a todos los directorios pblicos de un almacenamiento externo, lo cual podra ser 27 un acceso mayor que el que necesita tu aplicacin.</li> 28 <li>Usar el 29 <a href="{@docRoot}guide/topics/providers/document-provider.html">framework 30 de acceso al almacenamiento</a> generalmente implica que el usuario seleccione directorios 31 mediante un sistema de IU, lo cual no es necesario si tu aplicacin siempre accede al mismo 32 directorio externo.</li> 33 </ul> 34 35 <p>Android N brinda una API nueva y simplificada para acceder a 36 directorios de almacenamiento externo comunes. </p> 37 38 <h2 id="accessing">Acceder a un directorio de almacenamiento externo</h2> 39 40 <p>Usa la clase <code>StorageManager</code> para obtener la instancia de 41 <code>StorageVolume</code> correcta. Luego, crea una intent llamando al 42 mtodo <code>StorageVolume.createAccessIntent()</code> de esa instancia. 43 Usa esta intencin para acceder a directorios de almacenamiento externo. Para obtener una lista de 44 todos los volmenes disponibles, incluidos los volmenes de medios extrables, usa 45 <code>StorageManager.getVolumesList()</code>.</p> 46 47 <p>Si tienes informacin sobre un archivo especfico, usa 48 <code>StorageManager.getStorageVolume(File)</code> para obtener el 49 <code>StorageVolume</code> que contiene el archivo. Llama a 50 <code>createAccessIntent()</code> en este <code>StorageVolume</code> para acceder al 51 directorio de almacenamiento externo del archivo.</p> 52 53 <p> 54 En el caso de los volmenes secundarios, como las tarjetas SD externas, pasa un valor nulo cuando llames a 55 <code>StorageVolume.createAccessIntent()</code> para solicitar acceso al volumen 56 completo, en lugar de un directorio especfico. 57 <code>StorageVolume.createAccessIntent()</code> regresa un valor nulo si pasas un 58 valor nulo para el volumen principal o si pasas un nombre de directorio no vlido. 59 </p> 60 61 <p>El siguiente fragmento de cdigo es un ejemplo de cmo abrir el 62 directorio <code>Pictures</code> en el almacenamiento compartido principal:</p> 63 64 <pre> 65 StorageManager sm = (StorageManager)getSystemService(Context.STORAGE_SERVICE); 66 StorageVolume volume = sm.getPrimaryVolume(); 67 Intent intent = volume.createAccessIntent(Environment.DIRECTORY_PICTURES); 68 startActivityForResult(intent, request_code); 69 </pre> 70 71 <p>El sistema intenta otorgar acceso al directorio externo y, si 72 es necesario, confirma el acceso con el usuario usando una IU simplificada:</p> 73 74 <img src="{@docRoot}images/android-7.0/scoped-directory-access-framed.png" srcset="{@docRoot}images/android-7.0/scoped-directory-access-framed.png 1x, 75 {@docRoot}images/android-7.0/scoped-directory-access-framed_2x.png 2x" /> 76 <p class="img-caption"><strong>Imagen 1.</strong> Una aplicacin solicitando 77 acceso al directorio Pictures.</p> 78 79 <p>Si el usuario otorga el acceso, el sistema llama a tu 80 anulacin de <code>onActivityResult()</code> con un cdigo resultante de 81 <code>Activity.RESULT_OK</code> y datos de intents que contienen el URI. Usa 82 el URI brindado para acceder a la informacin del directorio. Es similar a usar URI 83 generados por el 84 <a href="{@docRoot}guide/topics/providers/document-provider.html">framework 85 de acceso al almacenamiento</a>.</p> 86 87 <p>Si el usuario no otorga el acceso, el sistema llama a tu 88 anulacin de <code>onActivityResult()</code> con un cdigo resultante de 89 <code>Activity.RESULT_CANCELED</code> y datos de intents nulos.</p> 90 91 <p class="note"><b>Nota</b>: Obtener acceso a un directorio externo especfico 92 tambin otorga el acceso a los subdirectorios de ese directorio.</p> 93 94 <h2 id="removable">Acceder a un directorio de un medio extrable</h2> 95 96 <p>Para usar el acceso a directorios determinados para acceder a directorios de medios extrables, 97 primero debes agregar un {@link android.content.BroadcastReceiver} que escuche la 98 notificacin{@link android.os.Environment#MEDIA_MOUNTED}, por ejemplo:</p> 99 100 <pre> 101 <receiver 102 android:name=".MediaMountedReceiver" 103 android:enabled="true" 104 android:exported="true" > 105 <intent-filter> 106 <action android:name="android.intent.action.MEDIA_MOUNTED" /> 107 <data android:scheme="file" /> 108 </intent-filter> 109 </receiver> 110 </pre> 111 112 <p>Cuando el usuario conecta un medio extrable, como una tarjeta SD, el sistema enva una 113 notificacin{@link android.os.Environment#MEDIA_MOUNTED}. Esta notificacin 114 brinda un objeto <code>StorageVolume</code> en los datos de intents que puedes 115 usar para acceder a directorios del medio extrable. El siguiente ejemplo 116 accede al directorio <code>Pictures</code> de medios extrables:</p> 117 118 <pre> 119 // BroadcastReceiver has already cached the MEDIA_MOUNTED 120 // notification Intent in mediaMountedIntent 121 StorageVolume volume = (StorageVolume) 122 mediaMountedIntent.getParcelableExtra(StorageVolume.EXTRA_STORAGE_VOLUME); 123 volume.createAccessIntent(Environment.DIRECTORY_PICTURES); 124 startActivityForResult(intent, request_code); 125 </pre> 126 127 <h2 id="best">Prcticas recomendadas</h2> 128 129 <p>Cuando sea posible, sigue usando el URI de acceso a directorios externos de modo que no tengas 130 que solicitarle acceso al usuario continuamente. Una vez que el usuario haya otorgado el acceso, llama a 131 <code>getContentResolver().takePersistableUriPermssion()</code> con el 132 URI de acceso a directorios. El sistema continuar el URI, y las siguientes solicitudes 133 de acceso generarn <code>RESULT_OK</code> y no le mostrarn una IU de confirmacin al 134 usuario.</p> 135 136 <p>Si el usuario deniega el acceso a un directorio externo, no vuelvas a solicitar el 137 acceso inmediatamente. Hacer esto provocara una mala experiencia 138 de usuario. Si el usuario deniega una solicitud y la aplicacin solicita acceso 139 nuevamente, aparece la casilla de verificacin <b>Don't ask again</b> en la IU:</p> 140 141 <img src="{@docRoot}images/android-7.0/scoped-directory-access-dont-ask.png" srcset="{@docRoot}images/android-7.0/scoped-directory-access-dont-ask.png 1x, 142 {@docRoot}images/android-7.0/scoped-directory-access-dont-ask_2x.png 2x" /> 143 <p class="img-caption"><strong>Figura 1.</strong> Una aplicacin que presenta una 144 segunda solicitud para obtener acceso a medios extrables.</p> 145 146 <p>Si el usuario selecciona <b>Don't ask again</b> y deniega la solicitud, todas las 147 solicitudes futuras que presente la aplicacin para el directorio determinado se denegarn 148 automticamente, y el usuario no recibir ninguna IU de solicitud.</p>