1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
|
page.title=Salvando arquivos
page.tags=armazenamento de dados
helpoutsWidget=true
trainingnavtop=true
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>Esta lição ensina a</h2>
<ol>
<li><a href="#InternalVsExternalStorage">Escolher entre armazenamento interno e externo</a></li>
<li><a href="#GetWritePermission">Obter permissões para armazenamento externo</a></li>
<li><a href="#WriteInternalStorage">Salvar arquivos em armazenamento interno</a></li>
<li><a href="#WriteExternalStorage">Salvar arquivos em armazenamento externo</a></li>
<li><a href="#GetFreeSpace">Consultar espaço livre</a></li>
<li><a href="#DeleteFile">Excluir um arquivo</a></li>
</ol>
<h2>Leia também</h2>
<ul>
<li><a href="{@docRoot}guide/topics/data/data-storage.html#filesInternal">Utilizando armazenamento
interno</a></li>
<li><a href="{@docRoot}guide/topics/data/data-storage.html#filesExternal">Utilizando armazenamento
externo</a></li>
</ul>
</div>
</div>
<p>O Android usa um sistema de arquivos
parecido com sistemas de arquivos em disco de outras plataformas. Esta lição explica
como trabalhar com o sistema de arquivos Android para ler e gravar arquivos com APIs {@link java.io.File}
.</p>
<p>Um objeto {@link java.io.File} é adequado para ler ou gravar grandes quantidades de dados em
ordens crescente sem pular nenhum item. Por exemplo, é bom para arquivos de imagens ou
qualquer troca executada por uma rede.</p>
<p>Esta lição demonstra como executar tarefas básicas relacionadas a arquivos em seu aplicativo.
Assume-se que você já esteja familiarizado com os fundamentos do sistema de arquivos Linux e com
APIs de entrada/saída de arquivos padrão no {@link java.io}.</p>
<h2 id="InternalVsExternalStorage">Escolher entre armazenamento interno e externo</h2>
<p>Todos os dispositivos Android têm duas áreas de armazenamento de arquivos: armazenamento “interno” e “externo”. Estes nomes
têm origem no início do Android, quando a maior parte de seus dispositivos oferecia memória embutida não volátil
(armazenamento interno), além de uma mídia de armazenamento removível, como micro cartões SD (armazenamento externo).
Alguns dispositivos dividem o espaço de armazenamento permanente em partições “interna” e “externa”. Assim, mesmo
sem uma mídia de armazenamento removível, sempre há dois espaços de armazenamento e
o comportamento da API permanece inalterado independentemente da remoção do armazenamento externo.
A lista a seguir resume as principais informações sobre cada tipo de espaço de armazenamento.</p>
<div class="col-5" style="margin-left:0">
<p><b>Armazenamento interno:</b></p>
<ul>
<li>Está sempre disponível.</li>
<li>Por padrão, os arquivos salvos aqui podem apenas ser acessados pelo seu aplicativo.</li>
<li>Quando o usuário desinstala o aplicativo, o sistema exclui todos os arquivos do aplicativo salvos no
armazenamento interno.</li>
</ul>
<p>O armazenamento interno funciona melhor quando você deseja garantir que o usuário nem outros aplicativos
tenham acesso aos seus arquivos.</p>
</div>
<div class="col-7" style="margin-right:0">
<p><b>Armazenamento externo:</b></p>
<ul>
<li>Não está sempre disponível porque o usuário pode montar o armazenamento externo, como um armazenamento USB,
e em alguns casos, removê-lo do dispositivo.</li>
<li>É de leitura universal, ou seja,
arquivos salvos aqui podem ser lidos em outros dispositivos.</li>
<li>Quando o usuário desinstala o aplicativo, o sistema exclui todos os arquivos do aplicativo salvos aqui
apenas se estiverem salvos no diretório de {@link android.content.Context#getExternalFilesDir
getExternalFilesDir()}.</li>
</ul>
<p>O armazenamento externo é o melhor
local para arquivos que não exigem acesso restrito e para os arquivos que você deseja compartilhar
com outros aplicativos ou permitir que o usuário acesse através com um computador.</p>
</div>
<p class="note" style="clear:both">
<strong>Dica:</strong> embora os aplicativos sejam instalados no armazenamento interno por
padrão, é possível especificar o atributo <a href="{@docRoot}guide/topics/manifest/manifest-element.html#install">{@code
android:installLocation}</a> em seu manifesto para que o aplicativo
seja instalado no armazenamento externo. Os usuários se beneficiam dessa opção quando o tamanho do APK é muito grande e
ele dispõe de maior espaço em armazenamento externo do que interno. Para obter mais
informações, consulte <a href="{@docRoot}guide/topics/data/install-location.html">Local de instalação do aplicativo</a>.</p>
<h2 id="GetWritePermission">Obter permissões para armazenamento externo</h2>
<p>Para gravar no armazenamento externo, você deve solicitar a
permissão {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} em seu <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">arquivo de manifesto</a>:</p>
<pre>
<manifest ...>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
...
</manifest>
</pre>
<div class="caution"><p><strong>Cuidado:</strong>
atualmente, os aplicativos podem ler o armazenamento externo
sem precisar de permissão especial. No entanto, isso será alterado em lançamentos futuros. Se seu aplicativo precisar
ler o armazenamento externo (mas não gravar nele), será necessário declarar a permissão {@link
android.Manifest.permission#READ_EXTERNAL_STORAGE}. Para garantir que o aplicativo continue
a funcionar adequadamente, declare essa permissão agora antes que as mudanças entrem em vigor.</p>
<pre>
<manifest ...>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
...
</manifest>
</pre>
<p>No entanto, se seu aplicativo usa a permissão {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE}
, já existe uma permissão implícita para leitura do armazenamento externo.</p>
</div>
<p>Não é necessária permissão para salvar arquivos no armazenamento
interno. Seu aplicativo sempre terá permissão para ler e
gravar arquivos em seu diretório de armazenamento interno.</p>
<h2 id="WriteInternalStorage">Salvar arquivos em armazenamento interno</h2>
<p>Ao salvar um arquivo no armazenamento interno, você pode obter o diretório adequado como um
{@link java.io.File} chamando um destes dois métodos:</p>
<dl>
<dt>{@link android.content.Context#getFilesDir}</dt>
<dd>Retorna um {@link java.io.File} que representa um diretório interno para seu aplicativo.</dd>
<dt>{@link android.content.Context#getCacheDir}</dt>
<dd>Retorna um {@link java.io.File} que representa um diretório interno para os arquivos de cache temporários
de seu aplicativo. Certifique-se de excluir cada arquivo assim que não
for mais necessário e estabeleça um limite de tamanho razoável para a quantidade de memória usada em um determinado
período de tempo, como 1MB. Se o sistema começar a ficar com pouco espaço de armazenamento, ele poderá excluir arquivos de cache
sem avisar.</dd>
</dl>
<p>Para criar um novo arquivo em um desses diretórios, use o construtor {@link
android.Manifest.permission#READ_EXTERNAL_STORAGE}, transmitindo o {@link java.io.File} fornecido por um
dos métodos acima que especifica o diretório de armazenamento interno. Por exemplo:</p>
<pre>
File file = new File(context.getFilesDir(), filename);
</pre>
<p>Uma outra alternativa é chamar {@link
android.content.Context#openFileOutput openFileOutput()} para obter um {@link java.io.FileOutputStream}
que grave em um arquivo salvo no seu diretório interno. O exemplo a seguir
mostra como gravar texto em um arquivo:</p>
<pre>
String filename = "myfile";
String string = "Hello world!";
FileOutputStream outputStream;
try {
outputStream = openFileOutput(filename, Context.MODE_PRIVATE);
outputStream.write(string.getBytes());
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
</pre>
<p>Em alternativa, caso precise colocar arquivos em cache, use {@link
java.io.File#createTempFile createTempFile()}. Por exemplo, o método a seguir extrai o
nome do arquivo de {@link java.net.URL} e cria um arquivo com o mesmo nome
no diretório de cache interno de seu aplicativo.</p>
<pre>
public File getTempFile(Context context, String url) {
File file;
try {
String fileName = Uri.parse(url).getLastPathSegment();
file = File.createTempFile(fileName, null, context.getCacheDir());
catch (IOException e) {
// Error while creating file
}
return file;
}
</pre>
<p class="note"><strong>Observação:</strong>
o diretório de armazenamento interno do seu aplicativo é especificado
pelo nome do pacote do aplicativo em um local específico do sistema de arquivos Android.
Teoricamente, outros aplicativos poderão ler seus arquivos internos se você definir
o arquivo para modo leitura. No entanto, o outro aplicativo também precisaria saber o nome do pacote
do seu aplicativo e os nomes dos arquivos. Outros aplicativos não podem navegar nos diretórios internos e não têm
permissão para ler ou gravar a menos que os arquivos sejam explicitamente definidos para permitir tais ações. Portanto,
desde que você utilize {@link android.content.Context#MODE_PRIVATE} para seus arquivos no armazenamento interno,
eles não ficarão acessíveis a outros aplicativos.</p>
<h2 id="WriteExternalStorage">Salvar arquivos em armazenamento externo</h2>
<p>Como o armazenamento externo pode ficar indisponível, como se o usuário ativar o
armazenamento no PC ou remover o cartão SD que fornece armazenamento externo,
você deve sempre verificar se o volume está disponível antes de acessá-lo. Consulte o estado de armazenamento
externo chamando {@link android.os.Environment#getExternalStorageState}. Se o estado
retornado for igual a {@link android.os.Environment#MEDIA_MOUNTED}, os arquivos poderão ser lidos
e gravados. Os métodos a seguir ajudam a determinar a disponibilidade
de armazenamento:</p>
<pre>
/* Checks if external storage is available for read and write */
public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
return false;
}
/* Checks if external storage is available to at least read */
public boolean isExternalStorageReadable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state) ||
Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
return true;
}
return false;
}
</pre>
<p>Embora o usuário e outros aplicativos possam modificar o armazenamento externo, há duas
categorias de arquivos que deverão ser salvas aqui:</p>
<dl>
<dt>Arquivos públicos</dt>
<dd>Arquivos que
precisam estar livremente disponíveis ao usuário e outros aplicativos. Ao desinstalar o aplicativo,
o usuário deve continuar a ter acesso a esses arquivos.
<p>Por exemplo, fotos capturadas pelo aplicativo ou outros arquivos baixados.</p>
</dd>
<dt>Arquivos privados</dt>
<dd>Arquivos que pertencem ao aplicativo e que devem ser excluídos na desinstalação
. Embora esses arquivos estejam teoricamente à disposição do usuário e de outros aplicativo por estarem
no armazenamento externo, na verdade são arquivos que não têm valor para o usuário
fora do aplicativo. Ao desinstalar o aplicativo, o sistema exclui
todos os arquivos no diretório privado externo do aplicativo.
<p>Por exemplo, recursos adicionais baixados através do aplicativo ou arquivos de mídia temporários.</p>
</dd>
</dl>
<p>Para salvar arquivos públicos no armazenamento externo, use o método
{@link android.os.Environment#getExternalStoragePublicDirectory
getExternalStoragePublicDirectory()} para obter um {@link java.io.File} que representa
o diretório correto no armazenamento externo. O método exige um argumento que especifica
o tipo de arquivo que se deseja salvar para que possa ser logicamente organizado com outros arquivos públicos
, como {@link android.os.Environment#DIRECTORY_MUSIC} ou {@link
android.os.Environment#DIRECTORY_PICTURES}. Por exemplo:</p>
<pre>
public File getAlbumStorageDir(String albumName) {
// Get the directory for the user's public pictures directory.
File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
Log.e(LOG_TAG, "Directory not created");
}
return file;
}
</pre>
<p>Se você deseja salvar arquivos privados do aplicativo, obtenha o
diretório correto chamando {@link
android.content.Context#getExternalFilesDir getExternalFilesDir()} e informe um nome indicando
o tipo de diretório desejado. Cada diretório criado dessa forma é adicionado ao diretório principal
que contém todos os arquivos do armazenamento externo do aplicativo que o sistema exclui quando o
usuário faz a desinstalação.</p>
<p>Por exemplo, este é um método que pode ser usado para criar um diretório para um álbum de fotos individual:</p>
<pre>
public File getAlbumStorageDir(Context context, String albumName) {
// Get the directory for the app's private pictures directory.
File file = new File(context.getExternalFilesDir(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
Log.e(LOG_TAG, "Directory not created");
}
return file;
}
</pre>
<p>Se nenhum dos nomes de subdiretórios predefinidos se adequa aos arquivos, chame {@link
android.content.Context#getExternalFilesDir getExternalFilesDir()} e transmita {@code null}. Isso
retorna o diretório raiz para o diretório privado do aplicativo no armazenamento externo.</p>
<p>Lembre-se de que {@link android.content.Context#getExternalFilesDir getExternalFilesDir()}
cria um diretório dentro de um diretório que é excluído quando o usuário desinstala o aplicativo.
Se os arquivos salvos precisarem estar disponíveis após a desinstalação do
aplicativo, como
quando seu aplicativo é uma câmera e o usuário deseja manter as fotos, use {@link android.os.Environment#getExternalStoragePublicDirectory
getExternalStoragePublicDirectory()}.</p>
<p>Independentemente do uso de {@link
android.os.Environment#getExternalStoragePublicDirectory
getExternalStoragePublicDirectory()} para arquivos compartilhados ou
{@link android.content.Context#getExternalFilesDir
getExternalFilesDir()} para arquivos privados do aplicativo, é importante usar
os nomes de diretório fornecidos pelas constantes de API, como
{@link android.os.Environment#DIRECTORY_PICTURES}. Esses nomes de diretório garantem
que os arquivos sejam tratados de forma adequada pelo sistema. Por exemplo, arquivos salvos em {@link
android.os.Environment#DIRECTORY_RINGTONES} são categorizados pelo scanner de mídia dos sistema como toques
e não como música.</p>
<h2 id="GetFreeSpace">Consultar espaço livre</h2>
<p>Se você já souber antecipadamente a quantidade de dados a ser salvo, descubra se
há espaço disponível suficiente sem fazer com que um {@link
java.io.IOException} chame {@link java.io.File#getFreeSpace} ou {@link
java.io.File#getTotalSpace}. Esses métodos informam o espaço disponível atual e o
espaço total no volume de armazenamento. Essa informação ajuda a evitar o preenchimento
do volume de armazenamento além de um determinado limite.</p>
<p>No entanto, o sistema não garante que será possível gravar a quantidade de bytes indicada
por {@link java.io.File#getFreeSpace}. Se o número retornado tiver
alguns MB além do tamanho dos dados que deseja salvar ou se o sistema de arquivos
estiver abaixo de 90% cheio, é possível continuar com segurança.
Caso contrário, não grave no armazenamento.</p>
<p class="note"><strong>Observação:</strong> não é obrigatório verificar a quantidade de espaço disponível
antes de salvar o arquivo. É possível tentar gravar o arquivo diretamente e depois
obter um {@link java.io.IOException}, se houver. Essa ação é recomendada
caso você não saiba exatamente quanto espaço será necessário. Por exemplo, se
você alterar a codificação do arquivo antes de salvá-lo convertendo uma imagem PNG em
JPEG, não é possível saber o tamanho do arquivo antecipadamente.</p>
<h2 id="DeleteFile">Excluir um arquivo</h2>
<p>Sempre exclua arquivos que não sejam mais necessários. A forma mais simples de apagar um
arquivo é fazer com que o arquivo de referência aberto chame {@link java.io.File#delete} por conta própria.</p>
<pre>
myFile.delete();
</pre>
<p>Se o arquivo estiver salvo em armazenamento interno, é possível solicitar ao {@link android.content.Context} para localizar e
excluir o arquivo chamando {@link android.content.Context#deleteFile deleteFile()}:</p>
<pre>
myContext.deleteFile(fileName);
</pre>
<div class="note">
<p><strong>Observação:</strong> quando o usuário desinstala o aplicativo, o sistema Android também
exclui:</p>
<ul>
<li>Todos os arquivos salvos no armazenamento interno</li>
<li>Todos os arquivos salvos no armazenamento externo usando {@link
android.content.Context#getExternalFilesDir getExternalFilesDir()}.</li>
</ul>
<p>No entanto, recomenda-se exclui manualmente todos os arquivos em cache criados com
{@link android.content.Context#getCacheDir()} regularmente e
outros arquivos que não sejam mais necessários.</p>
</div>
|