Scoped Storage — o que é, gerenciamento de arquivos e acesso ao armazenamento

Autor: IT Sectr Publicado: 2026-07-10 Tempo de leitura: 10 min

Scoped Storage é um modelo de acesso ao sistema de arquivos introduzido no Android 10 (API 29) que restringe o acesso arbitrário de aplicativos ao armazenamento compartilhado do dispositivo. De acordo com a Documentação para Desenvolvedores Android do Google (2024), o Scoped Storage substitui o antigo modelo de permissões READ_EXTERNAL_STORAGE e WRITE_EXTERNAL_STORAGE, concedendo aos aplicativos acesso apenas aos seus próprios arquivos em uma sandbox isolada e a coleções compartilhadas através do MediaStore. Esse modelo aumenta a privacidade dos dados do usuário e previne a coleta não autorizada de informações por aplicativos.

Principais pontos

  • Scoped Storage é um modelo de acesso a arquivos no Android 10+ que restringe a leitura arbitrária do armazenamento compartilhado.
  • O aplicativo possui sua própria sandbox com acesso total sem permissões adicionais.
  • Para acessar arquivos compartilhados (fotos, vídeos, áudio) é usada a API MediaStore.
  • Para acessar diretórios e arquivos arbitrários é usado o Storage Access Framework (SAF).
  • As permissões READ_EXTERNAL_STORAGE e WRITE_EXTERNAL_STORAGE perderam efeito para a maioria dos cenários.

O que é Scoped Storage no Android?

Scoped Storage é uma mudança arquitetural no Android 10 (API 29) que transforma fundamentalmente a forma como os aplicativos acessam o sistema de arquivos do dispositivo. Em vez de acesso total ao armazenamento compartilhado, o aplicativo obtém acesso apenas à sua própria sandbox e a coleções de mídia específicas através do MediaStore.

Antes do Scoped Storage, qualquer aplicativo com permissão READ_EXTERNAL_STORAGE podia ler todos os arquivos no armazenamento compartilhado — fotos, documentos, downloads, dados de outros aplicativos. Isso criava riscos de privacidade: aplicativos não confiáveis podiam coletar informações do usuário sem seu conhecimento.

De acordo com o Google I/O 2019, mais de 65% dos usuários do Android consideram a privacidade dos dados um fator crítico ao escolher um aplicativo. O Scoped Storage é uma resposta direta a essa demanda: cada aplicativo opera em um ambiente isolado e obtém acesso aos dados de outros aplicativos apenas com o consentimento explícito do usuário.

Importante: o Scoped Storage no Android 10 era opcional (o aplicativo podia desativá-lo através do requestLegacyExternalStorage). A partir do Android 11 (API 30), o Scoped Storage tornou-se obrigatório para todos os aplicativos, independentemente do target SDK.

Por que o Scoped Storage foi necessário

O Google introduziu o Scoped Storage para resolver três problemas fundamentais do antigo modelo de acesso a arquivos: privacidade, gerenciamento de permissões e limpeza de arquivos residuais.

Problema de privacidade

No modelo antigo, um aplicativo com READ_EXTERNAL_STORAGE podia escanear todo o armazenamento compartilhado e coletar metadados dos arquivos do usuário — coordenadas geográficas de fotos, nomes de documentos, estrutura de diretórios. O Scoped Storage elimina essa possibilidade: mesmo com permissão, o aplicativo vê apenas os arquivos que ele mesmo criou e os arquivos selecionados explicitamente pelo usuário através do SAF.

Problema de limpeza ao desinstalar o aplicativo

Antes do Scoped Storage, os aplicativos podiam deixar arquivos no armazenamento compartilhado após a desinstalação. Com o tempo, acumulavam-se diretórios lixo. O Scoped Storage resolve isso: todos os arquivos na sandbox do aplicativo são removidos junto com o aplicativo, e os arquivos através do MediaStore têm um proprietário e podem ser limpos pelo sistema.

AspectoModelo antigo (Legacy)Scoped Storage
Acesso ao armazenamento compartilhadoTotal (com permissão)Apenas sua sandbox
Arquivos de mídiaCaminho de arquivo diretoAtravés de URI do MediaStore
Arquivos de outros aplicativosSempre acessíveisApenas através do SAF
Limpeza ao desinstalarArquivos permanecemSandbox é removida
Controle do usuárioMínimoConsentimento explícito por arquivo

O Scoped Storage faz parte da estratégia geral de privacidade do Google no Android, que também inclui permissões "apenas enquanto em uso", indicadores de acesso à câmera e microfone e o Painel de Privacidade.

Diretório privado do aplicativo

Cada aplicativo no Android recebe seu próprio diretório privado, acessível através de Context.getFilesDir() e context.getCacheDir(). Para acessar o diretório privado externo (compartilhado), é usado Context.getExternalFilesDir().

No Scoped Storage, um aplicativo tem acesso total ao seu diretório privado externo sem nenhuma permissão. Este é o local principal para armazenar arquivos que não devem ser acessíveis a outros aplicativos ou que o aplicativo cria para seu próprio uso.

kotlin
import android.os.Environment
import java.io.File
import java.io.IOException

class FileManager {

    fun saveToAppStorage(context: Context, fileName: String, data: ByteArray) {
        val appDir = context.getExternalFilesDir(null)
            ?: return
        val file = File(appDir, fileName)
        file.writeBytes(data)
    }

    fun readFromAppStorage(context: Context, fileName: String): ByteArray? {
        val appDir = context.getExternalFilesDir(null)
            ?: return null
        val file = File(appDir, fileName)
        return file.takeIf { it.exists() }?.readBytes()
    }
}

Caminho para o diretório privado externo: /storage/emulated/0/Android/data/{packageName}/files/. A partir do Android 11, o caminho de arquivo direto não está disponível — apenas através da API. Esta é mais uma melhoria de segurança do Scoped Storage.

MediaStore — acesso a arquivos de mídia

MediaStore é a API principal para acessar arquivos de mídia compartilhados (imagens, vídeos, áudio) no Scoped Storage. O aplicativo não trabalha com caminhos de arquivo, mas com content URIs fornecidos pelo provedor MediaStore.

O MediaStore é dividido em três coleções principais: Images, Video e Audio. Cada coleção suporta operações CRUD através do ContentResolver. Para inserir um novo arquivo na coleção Images, é usado MediaStore.Images.Media; para consultar os existentes — query com a URI correspondente.

kotlin
import android.content.ContentValues
import android.provider.MediaStore
import android.os.Environment
import java.io.OutputStream

fun saveImageToGallery(context: Context, bitmap: Bitmap, title: String) {
    val values = ContentValues().apply {
        put(MediaStore.Images.Media.DISPLAY_NAME, "$title.jpg")
        put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")
        put(
            MediaStore.Images.Media.RELATIVE_PATH,
            "${Environment.DIRECTORY_PICTURES}/MyApp"
        )
    }

    val uri = context.contentResolver
        .insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
        ?: return

    context.contentResolver.openOutputStream(uri)?.use { output: OutputStream ->
        bitmap.compress(
            Bitmap.CompressFormat.JPEG,
            95,
            output
        )
    }
}

Importante: o MediaStore não suporta caminhos de arquivo arbitrários — apenas content URIs. Tentar obter um caminho de arquivo de uma URI através de MediaStore.Files.getContentUri() não dará um caminho direto para o arquivo no Android 11+. Em vez disso, use ContentResolver.openInputStream() e openOutputStream() para trabalhar com o conteúdo.

Storage Access Framework (SAF)

Storage Access Framework (SAF) é uma API para acessar arquivos e diretórios arbitrários fora da sandbox do aplicativo. O SAF fornece ao usuário uma interface de seleção de arquivo ou diretório, após a qual o aplicativo recebe um content URI com acesso temporário.

O SAF é usado para cenários não cobertos pelo MediaStore: trabalhar com documentos arbitrários (PDF, ZIP, APK), acessar diretórios no cartão SD, importar e exportar arquivos de outros aplicativos. O usuário seleciona explicitamente um arquivo através do seletor de arquivos do sistema — isso garante seu consentimento para o acesso.

kotlin
import android.app.Activity
import android.content.Intent
import android.net.Uri
import android.provider.DocumentsContract

const val REQUEST_CODE_PICK_DIR = 1001

fun pickDirectory(activity: Activity) {
    val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
    activity.startActivityForResult(intent, REQUEST_CODE_PICK_DIR)
}

fun handlePickResult(requestCode: Int, data: Intent?) {
    if (requestCode == REQUEST_CODE_PICK_DIR && data != null) {
        val treeUri: Uri = data.data ?: return

        // Take persistent URI permission
        val flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or
                       Intent.FLAG_GRANT_WRITE_URI_PERMISSION
        contentResolver.takePersistableUriPermission(treeUri, flags)
    }
}

O SAF concede ao aplicativo acesso ao diretório selecionado pelo usuário até a reinicialização do dispositivo (ao usar takePersistableUriPermission). Esta é a única maneira de obter acesso a arquivos arbitrários no armazenamento compartilhado no Android 11+.

Migrando seu aplicativo para o Scoped Storage

Migrar um aplicativo Android existente para o Scoped Storage requer mudanças em várias áreas principais. O Google recomenda uma abordagem em fases com testes no Android 11+.

Substituir caminhos de arquivo por content URIs

Substitua todas as operações diretas com File no armazenamento compartilhado por ContentResolver.openInputStream / openOutputStream. Para arquivos na sandbox do aplicativo (getExternalFilesDir), os caminhos de arquivo continuam funcionando.

Atualizar o AndroidManifest

Remova READ_EXTERNAL_STORAGE e WRITE_EXTERNAL_STORAGE se não forem necessários para cenários específicos (por exemplo, gerenciamento de arquivos — para isso existe a permissão especial MANAGE_EXTERNAL_STORAGE).

CenárioAbordagem antigaAbordagem Scoped Storage
Salvar uma fotoFile(path).writeBytes()MediaStore + ContentResolver
Ler PDFFile(path).inputStream()SAF ACTION_OPEN_DOCUMENT
Arquivos própriosEnvironment.getExternalStorageDirectory()context.getExternalFilesDir()
CacheFile(cacheDir).writeBytes()context.cacheDir (sem alterações)

Após a migração, teste o aplicativo no Android 11+ (API 30), definindo targetSdk = 30 ou superior no build.gradle. Certifique-se de que todas as operações com arquivos no armazenamento compartilhado funcionem através do MediaStore ou SAF, e não através de caminhos de arquivo diretos.

kotlin
import android.os.Build

fun isScopedStorage(): Boolean {
    return Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
}

fun compatReadFile(context: Context, uri: Uri): ByteArray? {
    return if (isScopedStorage()) {
        context.contentResolver
            .openInputStream(uri)?.readBytes()
    } else {
        File(uri.path ?: return null)
            .takeIf { it.exists() }
            ?.readBytes()
    }
}

De acordo com o Google Play Console (2024), mais de 78% dos dispositivos Android ativos executam Android 10+ com Scoped Storage. A migração é uma etapa obrigatória para publicar atualizações no Google Play: novos aplicativos devem ter target API 31+, atualizações — API 30+.

Perguntas frequentes

É possível desativar o Scoped Storage no Android 11?

Não, a partir do Android 11 (API 30) o Scoped Storage é obrigatório para todos os aplicativos. O flag requestLegacyExternalStorage, disponível no Android 10, não funciona na API 30+. A única maneira de obter acesso amplo ao sistema de arquivos é a permissão MANAGE_EXTERNAL_STORAGE, mas ela é destinada apenas para gerenciadores de arquivos e antivírus.

O que é MANAGE_EXTERNAL_STORAGE e como obtê-lo?

MANAGE_EXTERNAL_STORAGE é uma permissão especial para aplicativos que precisam de acesso total ao sistema de arquivos (gerenciadores de arquivos, ferramentas de backup). A solicitação de permissão abre uma tela do sistema com um aviso para o usuário. Ao publicar no Google Play, é necessário preencher um formulário de Declaração sobre a necessidade dessa permissão.

Como obter um caminho de arquivo de um content URI no Scoped Storage?

No Scoped Storage no Android 11+, não é possível obter um caminho de arquivo direto de um content URI. Em vez disso, use ContentResolver.openInputStream() para leitura e openOutputStream() para escrita. Se precisar de um caminho de arquivo para compatibilidade com uma biblioteca de terceiros, crie uma cópia do arquivo em getCacheDir() e trabalhe com a cópia.

Como o Scoped Storage afeta o FileProvider?

O FileProvider continua funcionando sem alterações — ele é usado para fornecer acesso a arquivos da sandbox do aplicativo a outros aplicativos através de content URIs. O Scoped Storage não afeta o FileProvider, pois o FileProvider funciona no nível de content URIs, não de caminhos de arquivo diretos.

Como verificar se um dispositivo suporta Scoped Storage?

Verifique Build.VERSION.SDK_INT: se for >= Build.VERSION_CODES.Q (29), então o dispositivo suporta Scoped Storage. No entanto, no Android 10, o Scoped Storage pode ser desativado através de requestLegacyExternalStorage. No Android 11+, verifique se o flag de manifesto requestLegacyExternalStorage está definido — se não, o Scoped Storage está ativo.

Resumo

  • Scoped Storage é um modelo de acesso a arquivos no Android 10+ que restringe a leitura arbitrária do armazenamento compartilhado.
  • O aplicativo tem acesso total à sua sandbox privada sem permissões adicionais.
  • Para acessar arquivos de mídia compartilhados, é usada a API MediaStore com content URIs.
  • Para acessar arquivos e diretórios arbitrários, é usado o Storage Access Framework (SAF).
  • A partir do Android 11, o Scoped Storage é obrigatório para todos os aplicativos.
  • As permissões READ_EXTERNAL_STORAGE e WRITE_EXTERNAL_STORAGE não funcionam na maioria dos cenários no Android 11+.
  • Ao migrar, substitua caminhos de arquivo diretos por ContentResolver.openInputStream / openOutputStream.

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também