• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1page.title=Acesso a diretórios com escopo
2page.keywords=preview,sdk,scoped directory access
3page.tags=androidn
4
5@jd:body
6
7<div id="tb-wrapper">
8<div id="tb">
9  <h2>Neste documento</h2>
10  <ol>
11    <li><a href="#accessing">Acessar um diretório de armazenamento externo</a></li>
12    <li><a href="#removable">Acessar um diretório em uma mídia removível</a></li>
13    <li><a href="#best">Práticas recomendadas</a></li>
14  </ol>
15</div>
16</div>
17
18<p>Alguns aplicativos, como aplicativos de fotos, normalmente só precisam acessar diretórios específicos de um
19armazenamento externo, como o diretório <code>Pictures</code>. As abordagens
20existentes para o acesso de armazenamentos externos não foram desenvolvidas para fornecer com facilidade
21acesso direcionado a diretórios para esses tipos de aplicativos. Por exemplo:</p>
22
23<ul>
24<li>Solicitar {@link android.Manifest.permission#READ_EXTERNAL_STORAGE}
25ou {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} em seu manifesto
26permite o acesso a todos os diretórios públicos no armazenamento externo, o que pode ser mais do
27que o aplicativo precisa.</li>
28<li>Usar a
29<a href="{@docRoot}guide/topics/providers/document-provider.html">Estrutura de
30acesso ao armazenamento</a> geralmente faz com que o usuário selecione diretórios
31por meio de uma IU de sistema, o que é desnecessário se seu aplicativo sempre acessa o mesmo
32diretório externo.</li>
33</ul>
34
35<p>O Android N fornece uma nova API simplificada para acessar
36diretórios de armazenamento externo comuns. </p>
37
38<h2 id="accessing">Acessar um diretório de armazenamento externo</h2>
39
40<p>Use a classe <code>StorageManager</code> para obter a instância
41<code>StorageVolume</code> apropriada. Em seguida, crie uma intenção chamando o método
42<code>StorageVolume.createAccessIntent()</code> dessa instância.
43Use essa intenção para acessar os diretórios de armazenamento externo. Para obter uma lista de
44todos os volumes disponíveis, incluindo volumes de mídias removíveis, use
45<code>StorageManager.getVolumesList()</code>.</p>
46
47<p>Se você tiver informações sobre um arquivo específico, use
48<code>StorageManager.getStorageVolume(File)</code> para obter o
49<code>StorageVolume</code> que contém o arquivo. Chame
50<code>createAccessIntent()</code> neste <code>StorageVolume</code> para acessar
51o diretório de armazenamento externo para o arquivo.</p>
52
53<p>
54Em volumes secundários, como cartões SD externos, passe nulo ao chamar
55<code>StorageVolume.createAccessIntent()</code> para solicitar acesso ao
56volume todo em vez de um diretório específico.
57<code>StorageVolume.createAccessIntent()</code> retornará nulo se você passar
58nulo no volume principal ou se passar um nome de diretório inválido.
59</p>
60
61<p>O fragmento de código a seguir é um exemplo de como abrir o diretório
62<code>Pictures</code> no armazenamento compartilhado principal:</p>
63
64<pre>
65StorageManager sm = (StorageManager)getSystemService(Context.STORAGE_SERVICE);
66StorageVolume volume = sm.getPrimaryVolume();
67Intent intent = volume.createAccessIntent(Environment.DIRECTORY_PICTURES);
68startActivityForResult(intent, request_code);
69</pre>
70
71<p>O sistema tenta conceder acesso ao diretório externo e,
72se necessário, confirma o acesso com o usuário usando uma 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>Figura 1.</strong> Um aplicativo solicitando
77acesso ao diretório Pictures.</p>
78
79<p>Se o usuário conceder o acesso, o sistema chamará sua substituição de
80<code>onActivityResult()</code> com um código de resultado de
81<code>Activity.RESULT_OK</code> e os dados de intenção que contêm o URI. Use
82o URI fornecido para acessar as informações do diretório, o que é semelhante a usar URIs
83retornados pela
84<a href="{@docRoot}guide/topics/providers/document-provider.html">Estrutura de
85acesso ao armazenamento</a>.</p>
86
87<p>Se o usuário não conceder o acesso, o sistema chamará sua substituição de
88<code>onActivityResult()</code> com um código de resultado de
89<code>Activity.RESULT_CANCELED</code> e dados de intenção nulos.</p>
90
91<p class="note"><b>Observação</b>: Ao obter acesso a um diretório externo específico,
92você também obtém acesso aos subdiretórios dentro do diretório em questão.</p>
93
94<h2 id="removable">Acessar um diretório em uma mídia removível</h2>
95
96<p>Para usar o Acesso a diretórios com escopo para acessar diretórios em uma mídia removível,
97primeiro adicione um {@link android.content.BroadcastReceiver} que escute a notificação
98{@link android.os.Environment#MEDIA_MOUNTED}. Por exemplo:</p>
99
100<pre>
101&lt;receiver
102    android:name=".MediaMountedReceiver"
103    android:enabled="true"
104    android:exported="true" &gt;
105    &lt;intent-filter&gt;
106        &lt;action android:name="android.intent.action.MEDIA_MOUNTED" /&gt;
107        &lt;data android:scheme="file" /&gt;
108    &lt;/intent-filter&gt;
109&lt;/receiver&gt;
110</pre>
111
112<p>Quando o usuário monta uma mídia removível, como um cartão SD, o sistema envia uma notificação
113{@link android.os.Environment#MEDIA_MOUNTED}. Essa notificação
114fornece um objeto <code>StorageVolume</code> nos dados de intenção que
115você pode usar para acessar os diretórios na mídia removível. O exemplo a seguir
116acessa o diretório <code>Pictures</code> na mídia removível:</p>
117
118<pre>
119// BroadcastReceiver has already cached the MEDIA_MOUNTED
120// notification Intent in mediaMountedIntent
121StorageVolume volume = (StorageVolume)
122    mediaMountedIntent.getParcelableExtra(StorageVolume.EXTRA_STORAGE_VOLUME);
123volume.createAccessIntent(Environment.DIRECTORY_PICTURES);
124startActivityForResult(intent, request_code);
125</pre>
126
127<h2 id="best">Práticas recomendadas</h2>
128
129<p>Quando possível, mantenha o URI de acesso a diretórios externos para que você não precise
130solicitar acesso ao usuário várias vezes. Quando o usuário conceder o acesso, chame
131<code>getContentResolver().takePersistableUriPermssion()</code> com o
132URI de acesso ao diretório. O sistema manterá o URI e as solicitações de acesso
133subsequentes retornarão <code>RESULT_OK</code> e não mostrarão a IU de confirmação para o
134usuário.</p>
135
136<p>Se o usuário negar acesso a um diretório externo, não repita a
137solicitação imediatamente. Insistir em solicitações de acesso repetidas vezes gera uma experiência
138negativa para o usuário. Se uma solicitação for negada pelo usuário e o aplicativo solicitar acesso
139novamente, a IU exibirá uma caixa de seleção <b>Não perguntar novamente</b>.</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> Um aplicativo que faz uma
144segunda solicitação para acesso à mídia removível.</p>
145
146<p>Se o usuário selecionar <b>Não perguntar novamente</b> e negar a solicitação, todas
147as solicitações futuras para o diretório provenientes do aplicativo serão automaticamente
148negadas e a IU de solicitação não será apresentada ao usuário.</p>