Storage Access Framework è un framework Android per l'accesso sicuro a file e documenti tramite un dialogo di selezione del sistema. Invece di richiedere ampi permessi di lettura dell'archiviazione, l'app riceve un link URI al file scelto dall'utente. Secondo Android Developers (2026), SAF supporta l'archiviazione locale, i servizi cloud Google Drive e Dropbox tramite DocumentProvider. Il framework è stato introdotto in Android 4.4 ed è diventato lo standard per lavorare con i documenti a partire da Android 10.
Punti chiave
Storage Access Framework è una parte dell'SDK Android che fornisce un'interfaccia unificata per selezionare e creare documenti tramite un dialogo di sistema. SAF astrae la posizione fisica dei file: l'app non sa da dove viene letto il file — disco locale, Google Drive o Dropbox.
L'architettura SAF comprende tre componenti: l'app client che avvia la richiesta, il selettore di sistema — un dialogo standard di selezione file, e il DocumentProvider — un content provider che implementa l'accesso ai file di un'archiviazione specifica. L'utente vede un'interfaccia unificata indipendentemente dalla fonte dei dati.
SAF è disponibile da Android 4.4 (API 19). Inizialmente, il framework supportava solo documenti, ma Android 5.0 ha aggiunto il supporto per le directory tramite ACTION_OPEN_DOCUMENT_TREE. Da Android 10, SAF è diventato il metodo consigliato per accedere a qualsiasi file al di fuori dell'archiviazione specifica dell'app.
SAF avvia un dialogo di selezione file di sistema tramite un Intent con l'azione ACTION_OPEN_DOCUMENT. L'utente vede un elenco di fonti disponibili: archiviazione interna, Google Drive, Dropbox e altri provider registrati. Dopo aver selezionato un file, il sistema restituisce un content URI con diritti di accesso temporanei.
Il content URI ha il formato content://com.android.externalstorage.documents/document/primary/Download/file.pdf. A differenza di un URI file://, il content URI non rivela il percorso reale del file e funziona tramite DocumentProvider. L'app legge il file tramite ContentResolver.openInputStream utilizzando l'URI ottenuto.
Il selettore di sistema supporta automaticamente ricerca, ordinamento e filtraggio dei file per tipi MIME. Lo sviluppatore specifica i tipi necessari tramite Intent.putExtra(Intent.EXTRA_MIME_TYPES, arrayOf("application/pdf", "image/*")), e il selettore mostra solo i file pertinenti.
Per impostazione predefinita, l'URI è valido fino al riavvio dell'app o del dispositivo. Per l'accesso a lungo termine, l'app richiede takePersistableUriPermission — ciò consente di leggere il file nelle esecuzioni successive senza doverlo riselezionare tramite il dialogo.
SAF fornisce tre azioni principali per lavorare con i file: aprire, creare e selezionare albero di cartelle. ACTION_OPEN_DOCUMENT apre il selettore di sistema per scegliere un file esistente. ACTION_CREATE_DOCUMENT crea un nuovo file — l'utente inserisce un nome nel dialogo e l'app riceve un URI per la scrittura.
ACTION_OPEN_DOCUMENT_TREE consente di selezionare un'intera directory e ottenere l'accesso a tutti i file al suo interno. Viene utilizzato in file manager, app di backup e sincronizzazione. L'app riceve un URI di directory e può enumerare ricorsivamente il contenuto tramite DocumentFile.
| Azione | Scopo | Flag |
|---|---|---|
| ACTION_OPEN_DOCUMENT | Selezionare un file esistente | READ_FLAG |
| ACTION_CREATE_DOCUMENT | Creare un nuovo file | WRITE_FLAG |
| ACTION_OPEN_DOCUMENT_TREE | Selezionare una directory | READ + WRITE |
Per ogni azione, i tipi MIME vengono specificati tramite EXTRA_MIME_TYPES. È possibile specificare più tipi: "application/pdf", "image/*", "text/plain". Se non vengono specificati tipi, il selettore mostra tutti i file.
Persistent URI permissions è un meccanismo SAF che consente di mantenere l'accesso a un file dopo la fine della sessione corrente. Senza questo flag, l'URI è valido solo fino al riavvio dell'app. L'app richiede il flag FLAG_GRANT_PERSISTABLE_URI_PERMISSION insieme ai flag READ e WRITE.
Per salvare i permessi, viene utilizzato il metodo ContentResolver.takePersistableUriPermission. Il sistema salva l'URI in un registro speciale e ripristina l'accesso al successivo avvio dell'app. Per verificare se l'app ha accesso persistente a un URI, si utilizza ContentResolver.persistedUriPermissions.
L'utente può revocare i permessi salvati tramite Impostazioni → App → Permessi. L'app deve gestire lo scenario in cui l'accesso a un file viene perso inaspettatamente. Si consiglia di verificare l'accesso tramite ContentResolver.openInputStream prima di iniziare il lavoro e gestire correttamente SecurityException.
SAF viene avviato tramite un Intent standard. Il codice è minimo: creare un Intent con ACTION_OPEN_DOCUMENT, specificare i tipi MIME e avviarlo tramite ActivityResultContracts.StartActivityForResult. Dopo aver selezionato un file, il callback riceve l'URI in data.data, che viene poi utilizzato per la lettura.
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)
Per scrivere un nuovo file, utilizzare ACTION_CREATE_DOCUMENT. L'Intent accetta il tipo MIME e il nome del file tramite EXTRA_TITLE. Dopo aver selezionato una cartella e confermato, l'utente restituisce un URI nel quale l'app scrive i dati tramite ContentResolver.openOutputStream. Il sistema crea automaticamente il file nella posizione scelta.
SAF si differenzia dal tradizionale READ_EXTERNAL_STORAGE per un approccio fondamentalmente diverso alla sicurezza. Invece di richiedere l'accesso all'intera archiviazione in una volta, SAF richiede l'accesso solo a un file specifico. Ciò riduce al minimo la superficie di attacco e aumenta la fiducia dell'utente.
READ_EXTERNAL_STORAGE concede l'accesso a tutti i file sul dispositivo, inclusi foto e documenti di altre app. Su Android 10+, questo approccio è limitato. SAF, al contrario, fornisce l'accesso solo al file selezionato dall'utente e richiede una conferma esplicita per ogni file. Per operazioni batch sui media, utilizzare MediaStore; per documenti individuali, utilizzare SAF.
Lo svantaggio principale di SAF è la necessità di selezionare ogni file individualmente. Per operazioni di massa (backup, sincronizzazione cartelle), viene utilizzato ACTION_OPEN_DOCUMENT_TREE, che concede l'accesso a tutti i file nella directory selezionata. La soluzione dipende dallo scenario: SAF è ottimale per la selezione dell'utente, MediaStore per l'accesso programmatico ai media.
Domande frequenti
Storage Access Framework è un framework Android per l'accesso sicuro ai file tramite un dialogo di selezione del sistema. L'app riceve un content URI per il file selezionato senza richiedere ampi permessi di lettura dell'archiviazione.
Creare un Intent con ACTION_OPEN_DOCUMENT, specificare il tipo MIME tramite setType e avviarlo tramite ActivityResultContracts. Nel callback, ottenere l'URI da data.data e leggere tramite ContentResolver.openInputStream.
Persistent URI permissions è un meccanismo per mantenere l'accesso a un URI dopo il riavvio dell'app. Viene richiesto tramite il flag FLAG_GRANT_PERSISTABLE_URI_PERMISSION e il metodo takePersistableUriPermission.
SAF supporta qualsiasi tipo MIME: application/pdf, image/*, text/plain, application/zip e altri. I tipi vengono specificati tramite Intent.putExtra con un array EXTRA_MIME_TYPES.
SAF è progettato per selezionare file individuali dall'utente tramite un dialogo di sistema. MediaStore fornisce accesso programmatico a tutti i file multimediali del dispositivo tramite un database multimediale senza intervento dell'utente.
Riepilogo
Svilupperemo un'applicazione mobile chiavi in mano
IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.
Leggi anche