Para dar aos usuários mais controle sobre os arquivos e limitar a desorganização dos arquivos, o Android 10 introduziu um novo modelo de armazenamento para apps chamado armazenamento com escopo. O armazenamento com escopo muda a forma como os apps armazenam e acessam arquivos no armazenamento externo de um dispositivo. Para migrar seu app para oferecer suporte ao armazenamento com escopo, siga as práticas recomendadas para casos de uso de armazenamento comuns descritas neste guia. Os casos de uso são organizados em duas categorias: gerenciamento de arquivos de mídia e gerenciamento de arquivos que não são de mídia.
Para saber mais sobre como armazenar e acessar arquivos no Android, consulte os guias de treinamento de armazenamento.
Gerenciar arquivos de mídia
Esta seção descreve alguns dos casos de uso comuns para lidar com arquivos de mídia (arquivos de vídeo, imagem e áudio) e explica a abordagem de alto nível que seu app pode usar. A tabela a seguir resume cada um desses casos de uso e links para cada uma das seções que contêm mais detalhes.
Caso de uso | Resumo |
---|---|
Mostrar todos os arquivos de imagem ou vídeo | Use a mesma abordagem para todas as versões do Android. |
Mostrar imagens ou vídeos de uma pasta específica | Use a mesma abordagem para todas as versões do Android. |
Acessar informações de localização a partir de fotos | Use uma abordagem se o app usar armazenamento com escopo. Use uma abordagem diferente se o app desativar o armazenamento com escopo. |
Modificar ou excluir vários arquivos de mídia em uma única operação | Use uma abordagem para o Android 11. Para o Android 10, desative o armazenamento com escopo e use a abordagem para o Android 9 e versões anteriores. |
Importar uma única imagem que já existe | Use a mesma abordagem para todas as versões do Android. |
Capturar uma única imagem | Use a mesma abordagem para todas as versões do Android. |
Compartilhar arquivos de mídia com outros apps | Use a mesma abordagem para todas as versões do Android. |
Compartilhar arquivos de mídia com um app específico | Use a mesma abordagem para todas as versões do Android. |
Acessar arquivos de código ou bibliotecas que usam caminhos de arquivo diretos | Use uma abordagem para o Android 11. Para o Android 10, desative o armazenamento com escopo e use a abordagem para o Android 9 e versões anteriores. |
Mostrar arquivos de imagem ou vídeo de várias pastas
Consulte uma coleção de mídia usando a API query()
. Para filtrar ou classificar os arquivos de mídia, ajuste os parâmetros projection
, selection
, selectionArgs
e sortOrder
.
Mostrar imagens ou vídeos de uma pasta específica
Use esta abordagem:
- Seguindo as práticas recomendadas descritas em Solicitar permissões do app, solicite a permissão
READ_EXTERNAL_STORAGE
. - Recupere arquivos de mídia com base no valor de
MediaColumns.DATA
, que contém o caminho absoluto do sistema de arquivos para o item de mídia no disco.
Acessar informações de local a partir de fotos
Se seu app usa armazenamento com escopo, siga as etapas na seção Informações de localização em fotografias do guia de armazenamento de mídia.
Modificar ou excluir vários arquivos de mídia em uma única operação
Incorpore a lógica com base nas versões do Android em que seu app é executado.
Em execução no Android 11
Use esta abordagem:
- Crie uma intent pendente para a solicitação de gravação ou exclusão do app usando
MediaStore.createWriteRequest()
ouMediaStore.createTrashRequest()
e solicite ao usuário permissão para editar um conjunto de arquivos invocando essa intent. Avalie a resposta do usuário:
- Se a permissão foi concedida, prossiga com a operação de modificação ou exclusão.
- Se a permissão não foi concedida, explique ao usuário por que o recurso no seu app precisa da permissão.
Saiba mais sobre como executar operações em lote usando esses métodos disponíveis no Android 11.
Em execução no Android 10
Se o app for destinado ao Android 10 (API de nível 29), desative o armazenamento com escopo e continue usando a abordagem para o Android 9 e versões anteriores para realizar essa operação.
Em execução no Android 9 ou versões anteriores
Use esta abordagem:
- Seguindo as práticas recomendadas descritas em Solicitar permissões do app, solicite a permissão
WRITE_EXTERNAL_STORAGE
. - Use a API
MediaStore
para modificar ou excluir os arquivos de mídia.
Importar uma única imagem que já existe
Quando você quer importar uma única imagem que já existe (por exemplo, para usar como foto no perfil de um usuário), seu app poderá usar a própria IU para a operação ou o seletor do sistema.
Apresentar sua própria interface do usuário
Use esta abordagem:
- Seguindo as práticas recomendadas descritas em Solicitar permissões do app, solicite a permissão
READ_EXTERNAL_STORAGE
. - Use a API
query()
para consultar uma coleção de mídia. - Exiba os resultados na IU personalizada do seu app.
Usar o seletor de sistema
Use a intent ACTION_GET_CONTENT
, que solicita que o usuário escolha uma imagem para importar.
Se você quiser filtrar os tipos de imagens que o seletor de sistema apresenta para o usuário, use setType()
ou EXTRA_MIME_TYPES
.
Capturar uma única imagem
Quando você quiser capturar uma única imagem para usar no app (por exemplo, para usar como foto no perfil de um usuário), use a intent ACTION_IMAGE_CAPTURE
para pedir ao usuário para tirar uma foto usando a câmera do dispositivo. O sistema armazena a foto capturada na tabela MediaStore.Images
.
Compartilhar arquivos de mídia com outros apps
Use o método insert()
para adicionar registros diretamente ao MediaStore. Para mais informações, consulte a seção Adicionar um item do guia de armazenamento de mídia.
Compartilhar arquivos de mídia com um app específico
Use o componente FileProvider
do Android, conforme descrito no guia Como configurar o compartilhamento de arquivos.
Acessar arquivos de código ou bibliotecas que usam caminhos de arquivo diretos
Incorpore a lógica com base nas versões do Android em que seu app é executado.
Em execução no Android 11
Use esta abordagem:
- Seguindo as práticas recomendadas descritas em Solicitar permissões do app, solicite a permissão
READ_EXTERNAL_STORAGE
. - Acesse os arquivos usando caminhos de arquivo diretos.
Para mais informações, consulte Acessar arquivos usando caminhos brutos.
Em execução no Android 10
Se o app for destinado ao Android 10 (API de nível 29), desative o armazenamento com escopo e continue usando a abordagem para o Android 9 e versões anteriores para realizar essa operação.
Em execução no Android 9 ou versões anteriores
Use esta abordagem:
- Seguindo as práticas recomendadas descritas em Solicitar permissões do app, solicite a permissão
WRITE_EXTERNAL_STORAGE
. - Acesse os arquivos usando caminhos de arquivo diretos.
Gerenciar arquivos que não são de mídia
Esta seção descreve alguns dos casos de uso comuns para gerenciar arquivos que não são de mídia e explica a abordagem de alto nível que seu app pode usar. A tabela a seguir resume cada um desses casos de uso e links para cada uma das seções que contêm mais detalhes.
Caso de uso | Resumo |
---|---|
Abrir um arquivo de documento | Use a mesma abordagem para todas as versões do Android. |
Migrar arquivos existentes de um local de armazenamento legado | Migre seus arquivos para o armazenamento com escopo quando possível. Desative o armazenamento com escopo para o Android 10 quando necessário. |
Compartilhar conteúdo com outros apps | Use a mesma abordagem para todas as versões do Android. |
Armazenar em cache arquivos que não sejam de mídia | Use a mesma abordagem para todas as versões do Android. |
Abrir um arquivo de documento
Use a intent ACTION_OPEN_DOCUMENT
para solicitar que o usuário escolha um arquivo para abrir usando o seletor do sistema. Se você quiser filtrar os tipos de arquivos que o seletor de sistema apresentará ao usuário, use setType()
ou EXTRA_MIME_TYPES
.
Por exemplo, você pode encontrar todos os arquivos PDF, ODT e TXT usando o seguinte código:
Kotlin
startActivityForResult( Intent(Intent.ACTION_OPEN_DOCUMENT).apply { addCategory(Intent.CATEGORY_OPENABLE) type = "*/*" putExtra(Intent.EXTRA_MIME_TYPES, arrayOf( "application/pdf", // .pdf "application/vnd.oasis.opendocument.text", // .odt "text/plain" // .txt )) }, REQUEST_CODE )
Java
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); intent.addCategory(Intent.CATEGORY_OPENABLE); intent.setType("*/*"); intent.putExtra(Intent.EXTRA_MIME_TYPES, new String[] { "application/pdf", // .pdf "application/vnd.oasis.opendocument.text", // .odt "text/plain" // .txt }); startActivityForResult(intent, REQUEST_CODE);
Migrar arquivos existentes de um local de armazenamento legado
Um diretório é considerado um local de armazenamento legado se não for um diretório específico do app ou um diretório compartilhado público. Se o app criar ou consumir arquivos em um local de armazenamento legado, recomendamos que você migre os arquivos do app para locais acessíveis com armazenamento com escopo e faça as mudanças necessárias no app para trabalhar com arquivos no escopo.
Manter o acesso ao local de armazenamento legado para a migração de dados
Seu app precisa manter o acesso ao local de armazenamento legado para migrar os arquivos do app para locais acessíveis com armazenamento com escopo. A abordagem a ser usada depende do nível de API de destino do seu app.
Se seu app for destinado ao Android 11
Use a sinalização
preserveLegacyExternalStorage
para preservar o modelo de armazenamento legado para que o app possa migrar os dados de um usuário quando ele fizer upgrade para a nova versão do app direcionado ao Android 11.Continue a desativar o armazenamento com escopo para que o app possa continuar acessando seus arquivos no local de armazenamento legado em dispositivos Android 10.
Se o app for direcionado ao Android 10
Desative o armazenamento com escopo para facilitar a manutenção do comportamento do app nas versões do Android.
Migrar dados do app
Quando o app estiver pronto para migrar, use a seguinte abordagem:
- Verifique se os arquivos de trabalho do app estão localizados no diretório
/sdcard/
ou em qualquer um dos subdiretórios. - Mova todos os arquivos particulares do app do local atual em
/sdcard/
para o diretório retornado pelo métodogetExternalFilesDir()
. - Mova todos os arquivos compartilhados que não sejam de mídia do local atual em
/sdcard/
para um subdiretório dedicado ao app do diretórioDownloads/
. - Remova os diretórios de armazenamento legados do app do diretório
/sdcard/
.
Compartilhar conteúdo com outros apps
Para compartilhar os arquivos do seu app com outro app, use um FileProvider
. Para apps que precisam compartilhar arquivos entre si, recomendamos usar um provedor de conteúdo para cada app e sincronizar os dados à medida que eles forem adicionados à coleção.
Armazenar em cache arquivos que não sejam de mídia
A abordagem a ser usada depende do tipo de arquivo que você precisa armazenar em cache.
- Arquivos pequenos ou que contêm informações confidenciais: use
Context#getCacheDir()
. - Arquivos grandes ou que não contêm informações confidenciais: use
Context#getExternalCacheDir()
.
Desativar temporariamente o armazenamento com escopo
Antes que o app seja totalmente compatível com o armazenamento com escopo, é possível desativá-lo temporariamente usando um dos métodos a seguir:
- Direcione-o ao Android 9 (API de nível 28) ou versão anterior.
Se você direcionar ao Android 10 (API de nível 29) ou versão mais recente, defina o valor de
requestLegacyExternalStorage
comotrue
no arquivo de manifesto do app:<manifest ... > <!-- This attribute is "false" by default on apps targeting Android 10 or higher. --> <application android:requestLegacyExternalStorage="true" ... > ... </application> </manifest>
Para testar como um app direcionado ao Android 9 ou versão anterior se comporta ao usar o armazenamento com escopo, ative o comportamento definindo o valor de requestLegacyExternalStorage
como false
. Se você estiver testando em um dispositivo Android 11, também poderá usar sinalizações de compatibilidade de apps para testar o comportamento do app com ou sem armazenamento com escopo.