Storage Access Framework é um framework Android para acesso seguro a arquivos e documentos através de um diálogo de seleção do sistema. Em vez de solicitar permissões amplas de leitura do armazenamento, o aplicativo recebe um link URI para o arquivo escolhido pelo usuário. De acordo com Android Developers (2026), o SAF suporta armazenamento local, serviços em nuvem Google Drive e Dropbox através do DocumentProvider. O framework foi introduzido no Android 4.4 e tornou-se o padrão para trabalhar com documentos a partir do Android 10.
Principais pontos
Storage Access Framework é uma parte do SDK Android que fornece uma interface unificada para selecionar e criar documentos através de um diálogo do sistema. O SAF abstrai a localização física dos arquivos: o aplicativo não sabe de onde o arquivo está sendo lido — disco local, Google Drive ou Dropbox.
A arquitetura do SAF inclui três componentes: o aplicativo cliente que inicia a solicitação, o seletor do sistema — um diálogo padrão de seleção de arquivos, e o DocumentProvider — um provedor de conteúdo que implementa o acesso a arquivos de um armazenamento específico. O usuário vê uma interface unificada independentemente da fonte de dados.
O SAF está disponível desde Android 4.4 (API 19). Inicialmente, o framework suportava apenas documentos, mas o Android 5.0 adicionou suporte para diretórios via ACTION_OPEN_DOCUMENT_TREE. Desde o Android 10, o SAF tornou-se a maneira recomendada de acessar qualquer arquivo fora do armazenamento específico do aplicativo.
SAF inicia um diálogo de seleção de arquivos do sistema através de um Intent com a ação ACTION_OPEN_DOCUMENT. O usuário vê uma lista de fontes disponíveis: armazenamento interno, Google Drive, Dropbox e outros provedores registrados. Após selecionar um arquivo, o sistema retorna um content URI com direitos de acesso temporários.
O content URI tem o formato content://com.android.externalstorage.documents/document/primary/Download/file.pdf. Ao contrário de um URI file://, o content URI não revela o caminho real do arquivo e funciona através do DocumentProvider. O aplicativo lê o arquivo via ContentResolver.openInputStream usando o URI obtido.
O seletor do sistema suporta automaticamente pesquisa, classificação e filtragem de arquivos por tipos MIME. O desenvolvedor especifica os tipos necessários via Intent.putExtra(Intent.EXTRA_MIME_TYPES, arrayOf("application/pdf", "image/*")), e o seletor mostra apenas os arquivos relevantes.
Por padrão, o URI é válido até o aplicativo ser reiniciado ou o dispositivo ser reinicializado. Para acesso de longo prazo, o aplicativo solicita takePersistableUriPermission — isso permite ler o arquivo em execuções subsequentes sem precisar selecioná-lo novamente através do diálogo.
SAF fornece três ações principais para trabalhar com arquivos: abrir, criar e selecionar árvore de pastas. ACTION_OPEN_DOCUMENT abre o seletor do sistema para escolher um arquivo existente. ACTION_CREATE_DOCUMENT cria um novo arquivo — o usuário insere um nome no diálogo, e o aplicativo recebe um URI para escrita.
ACTION_OPEN_DOCUMENT_TREE permite selecionar um diretório inteiro e obter acesso a todos os arquivos dentro dele. Isso é usado em gerenciadores de arquivos, aplicativos de backup e sincronização. O aplicativo recebe um URI de diretório e pode enumerar recursivamente o conteúdo através do DocumentFile.
| Ação | Propósito | Flag |
|---|---|---|
| ACTION_OPEN_DOCUMENT | Selecionar um arquivo existente | READ_FLAG |
| ACTION_CREATE_DOCUMENT | Criar um novo arquivo | WRITE_FLAG |
| ACTION_OPEN_DOCUMENT_TREE | Selecionar um diretório | READ + WRITE |
Para cada ação, os tipos MIME são especificados através de EXTRA_MIME_TYPES. Vários tipos podem ser especificados: "application/pdf", "image/*", "text/plain". Se nenhum tipo for especificado, o seletor mostra todos os arquivos.
Persistent URI permissions é um mecanismo do SAF que permite preservar o acesso a um arquivo após o término da sessão atual. Sem esta flag, o URI é válido apenas até o aplicativo ser reiniciado. O aplicativo solicita a flag FLAG_GRANT_PERSISTABLE_URI_PERMISSION junto com as flags READ e WRITE.
Para salvar as permissões, utiliza-se o método ContentResolver.takePersistableUriPermission. O sistema salva o URI em um registro especial e restaura o acesso na próxima inicialização do aplicativo. Para verificar se o aplicativo tem acesso persistente a um URI, usa-se ContentResolver.persistedUriPermissions.
O usuário pode revogar as permissões salvas através de Configurações → Aplicativos → Permissões. O aplicativo deve lidar com o cenário em que o acesso a um arquivo é perdido inesperadamente. Recomenda-se verificar o acesso através de ContentResolver.openInputStream antes de começar a trabalhar e tratar corretamente SecurityException.
SAF é iniciado através de um Intent padrão. O código é mínimo: criar um Intent com ACTION_OPEN_DOCUMENT, especificar os tipos MIME e iniciá-lo através de ActivityResultContracts.StartActivityForResult. Após selecionar um arquivo, o callback recebe o URI em data.data, que é então usado para leitura.
val pickFile = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result ->
result.data?.data?.let { uri ->
val inputStream = contentResolver?.openInputStream(uri)
// read from inputStream
}
}
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
setType("application/pdf")
putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
}
pickFile.launch(intent)
Para escrever um novo arquivo, use ACTION_CREATE_DOCUMENT. O Intent aceita o tipo MIME e o nome do arquivo através de EXTRA_TITLE. Após selecionar uma pasta e confirmar, o usuário retorna um URI no qual o aplicativo escreve dados através de ContentResolver.openOutputStream. O sistema cria automaticamente o arquivo no local escolhido.
SAF difere do tradicional READ_EXTERNAL_STORAGE em uma abordagem fundamentalmente diferente para segurança. Em vez de solicitar acesso a todo o armazenamento de uma vez, o SAF solicita acesso apenas a um arquivo específico. Isso minimiza a superfície de ataque e aumenta a confiança do usuário.
READ_EXTERNAL_STORAGE concede acesso a todos os arquivos no dispositivo, incluindo fotos e documentos de outros aplicativos. No Android 10+, esta abordagem é restrita. O SAF, por outro lado, fornece acesso apenas ao arquivo selecionado pelo usuário e requer confirmação explícita para cada arquivo. Para operações em lote com mídia, use MediaStore; para documentos individuais, use SAF.
A principal desvantagem do SAF é a necessidade de selecionar cada arquivo individualmente. Para operações em massa (backup, sincronização de pastas), utiliza-se ACTION_OPEN_DOCUMENT_TREE, que concede acesso a todos os arquivos no diretório selecionado. A solução depende do cenário: SAF é ideal para seleção do usuário, MediaStore para acesso programático a mídia.
Perguntas frequentes
Storage Access Framework é um framework Android para acesso seguro a arquivos através de um diálogo de seleção do sistema. O aplicativo recebe um content URI para o arquivo selecionado sem solicitar permissões amplas de leitura do armazenamento.
Crie um Intent com ACTION_OPEN_DOCUMENT, especifique o tipo MIME através de setType e inicie-o através de ActivityResultContracts. No callback, obtenha o URI de data.data e leia através de ContentResolver.openInputStream.
Persistent URI permissions é um mecanismo para preservar o acesso a um URI após reiniciar o aplicativo. É solicitado através da flag FLAG_GRANT_PERSISTABLE_URI_PERMISSION e do método takePersistableUriPermission.
O SAF suporta qualquer tipo MIME: application/pdf, image/*, text/plain, application/zip e outros. Os tipos são especificados através de Intent.putExtra com um array EXTRA_MIME_TYPES.
SAF é projetado para selecionar arquivos individuais pelo usuário através de um diálogo do sistema. MediaStore fornece acesso programático a todos os arquivos de mídia do dispositivo através de um banco de dados de mídia sem interação do usuário.
Resumo
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.
Leia também