Content Provider: architettura del componente e principio di funzionamento

Autore: IT Sectr Pubblicato: 2026-06-17 Tempo di lettura: 8 min

Content Provider è un componente Android che fornisce un'interfaccia unificata per l'accesso ai dati tra applicazioni. Astrae l'archiviazione fisica (SQLite, file, fonti di rete) e consente lo scambio sicuro di informazioni tramite ContentResolver. Secondo Android Developer Guide, 2026, Content Provider è uno dei quattro componenti principali di un'applicazione Android, insieme ad Activity, Service e BroadcastReceiver. Il suo compito è rendere i dati disponibili ad altre applicazioni con controllo dei permessi di lettura e scrittura.

Punti chiave

  • Content Provider è un componente Android standard per lo scambio di dati tra applicazioni tramite l'interfaccia ContentResolver.
  • URI (content://) identifica una tabella o un record e viene utilizzato per tutte le operazioni CRUD con il provider.
  • UriMatcher è una classe di utilità che analizza gli URI in entrata e determina quale tabella o riga viene richiesta.
  • I permessi di lettura e scrittura sono definiti nel manifest e richiesti all'utente durante l'installazione.
  • CursorLoader o Room con Content Provider consentono il caricamento asincrono dei dati dal provider senza bloccare il thread UI.

Cos'è Content Provider?

Content Provider è un componente Android che gestisce l'accesso a un archivio dati centralizzato e lo fornisce ad altre applicazioni tramite un'interfaccia contrattuale unificata. Nasconde i dettagli implementativi dell'archiviazione: i dati possono essere memorizzati in SQLite, nel filesystem, nel cloud o essere il risultato di una richiesta di rete.

Android include Content Provider integrati per i dati di sistema — ContactsContract, MediaStore, CalendarContract, CallLog. Le applicazioni di terze parti possono anche creare propri provider per lo scambio sicuro di dati. Ogni provider viene registrato in AndroidManifest.xml con un authority — una stringa univoca che forma la prima parte dell'URI.

Come funziona Content Provider

Content Provider opera secondo un modello client-server. Il provider agisce come server che implementa sei metodi obbligatori: query, insert, update, delete, getType e onCreate. Il client (un'altra applicazione) accede al provider tramite ContentResolver, che traduce le chiamate nei metodi corrispondenti del provider attraverso il meccanismo IPC di Android.

URI e authority

Ogni Content Provider è identificato da un URI dello schema content://. Ad esempio, content://com.example.app.provider/items. La prima parte authority (com.example.app.provider) è legata alla classe del provider nel manifest. Il percorso /items punta a una tabella, mentre /items/5 punta a un record specifico con ID=5.

Processo di chiamata

Quando un'applicazione chiama ContentResolver.query(URI), Android verifica i permessi del pacchetto chiamante, trova il provider tramite l'authority e avvia il suo processo se non è già in esecuzione. Il provider esegue la query e restituisce un Cursor — un oggetto che contiene il risultato e consente al client di iterare sui record.

Metodi principali di Content Provider

La classe ContentProvider richiede l'implementazione di sei metodi astratti. Ogni metodo accetta un URI e restituisce un risultato corrispondente al tipo di operazione. Il sistema chiama questi metodi da qualsiasi processo, quindi devono essere thread-safe e non bloccare l'esecuzione a lungo.

Metodo query

Il metodo query accetta un URI, un array di colonne projection, una stringa selection con argomenti e un ordinamento. Restituisce un Cursor con i dati. Nell'implementazione, è necessario analizzare l'URI con UriMatcher ed eseguire la query SQL corrispondente nel database.

Metodi insert, update, delete

Questi metodi modificano i dati nell'archivio. insert riceve ContentValues — coppie chiave-valore — e restituisce l'URI del nuovo record. update e delete accettano una selection per filtrare i record e restituiscono il numero di righe interessate. Dopo aver modificato i dati, il provider deve notificarlo tramite ContentResolver.notifyChange.

MetodoScopoRestituisce
queryOttenere dati per URICursor o null
insertAggiungere un nuovo recordURI del nuovo record
updateAggiornare record esistentiint (n. righe)
deleteEliminare recordint (n. righe)
getTypeTipo MIME per URIString
onCreateInizializzazione del providerboolean

ContentResolver e URI in Android

ContentResolver è un punto di accesso unico per lavorare con tutti i Content Provider nel sistema. L'applicazione client non chiama mai direttamente i metodi del provider — solo tramite ContentResolver, che Android ottiene dal contesto. Le operazioni CRUD in ContentResolver hanno gli stessi nomi che nel provider ma accettano URI invece di riferimenti diretti.

UriMatcher

Per analizzare gli URI in entrata all'interno del provider, si usa UriMatcher. Permette di mappare un URI a un codice numerico — ad esempio, l'URI content://authority/items produce il codice 1, e content://authority/items/# produce il codice 2. Ciò elimina la necessità di analisi manuale della stringa URI in ogni metodo.

kotlin
// Usare ContentResolver per accedere ai contatti
val uri = ContactsContract.Contacts.CONTENT_URI
val cursor = contentResolver.query(
    uri,
    arrayOf(ContactsContract.Contacts.DISPLAY_NAME),
    null, null, null
)
cursor?.use {
    while (it.moveToNext()) {
        val name = it.getString(it.getColumnIndexOrThrow(
            ContactsContract.Contacts.DISPLAY_NAME
        ))
        Log.d("Contatti", "Nome: $name")
    }
}

Il Cursor deve essere sempre chiuso dopo l'uso — nell'esempio sopra, la funzione use (estensione Kotlin) lo fa. Se il Cursor non viene chiuso, si verifica una perdita di memoria perché mantiene un riferimento ai dati nel pool Binder. Per scenari UI, usa CursorLoader o Room con LiveData/Flow.

Esempio di Content Provider in Kotlin

La creazione di un proprio Content Provider inizia con l'estensione della classe ContentProvider. Il provider lavora con un database SQLite tramite SQLiteOpenHelper e usa UriMatcher per determinare il tipo di query. Considera un'implementazione minima per gestire un elenco di note.

Registrazione nel manifest

Il provider viene registrato in AndroidManifest.xml all'interno del tag application. L'attributo authorities imposta un identificatore univoco, e exported determina se altre applicazioni possono accedere al provider. Senza exported=true, il provider è accessibile solo all'interno dell'applicazione.

kotlin
// Esempio di Content Provider per note
class NotesProvider : ContentProvider() {

    companion object {
        const val AUTHORITY = "com.example.app.notes"
        const val NOTES_PATH = "notes"
        const val NOTES_URI = "content://$AUTHORITY/$NOTES_PATH"
        const val NOTES_ID = "content://$AUTHORITY/$NOTES_PATH/#"

        private val uriMatcher = UriMatcher(UriMatcher.NO_MATCH).apply {
            addURI(AUTHORITY, NOTES_PATH, 1)
            addURI(AUTHORITY, "$NOTES_PATH/#", 2)
        }
    }

    override fun query(uri: Uri, projection: Array<String>?,
        selection: String?, args: Array<String>?, sort: String?): Cursor? {
        return when (uriMatcher.match(uri)) {
            1 -> dbHelper.readableDatabase.query(TABLE_NOTES,
                projection, selection, args, null, null, sort)
            2 -> dbHelper.readableDatabase.query(TABLE_NOTES,
                projection, "_id=?", arrayOf(uri.lastPathSegment), null, null, null)
            else -> throw IllegalArgumentException("Unknown URI: $uri")
        }
    }

    override fun insert(uri: Uri, values: ContentValues?): Uri? {
        val id = dbHelper.writableDatabase.insert(TABLE_NOTES, null, values)
        context?.contentResolver?.notifyChange(uri, null)
        return ContentUris.withAppendedId(uri, id)
    }

    override fun delete(uri: Uri, selection: String?, args: Array<String>?): Int {
        val count = dbHelper.writableDatabase.delete(TABLE_NOTES, selection, args)
        context?.contentResolver?.notifyChange(uri, null)
        return count
    }

    // getType, update, onCreate omessi per brevità
}

Dopo aver creato la classe del provider, deve essere registrata nel manifest con gli attributi android:authorities e android:exported (true se il provider è pubblico). Il sistema crea un'istanza del provider al primo accesso — ciò avviene nel thread UI, quindi onCreate deve eseguire rapidamente.

Protezione dei dati tramite permessi

Content Provider consente di gestire l'accesso ai dati a due livelli: permessi di lettura e permessi di scrittura. Sono impostati nel manifest con gli attributi android:readPermission e android:writePermission. Se l'applicazione client non dispone del permesso corrispondente, il sistema rifiuta la chiamata con una SecurityException.

Permessi a livello di URI

Android supporta permessi temporanei tramite i flag FLAG_GRANT_READ_URI_PERMISSION e FLAG_GRANT_WRITE_URI_PERMISSION. Ciò è utile quando un'applicazione passa un URI di file a un'altra applicazione tramite Intent — il destinatario ottiene accesso solo a quell'URI specifico per un tempo limitato. Il sistema revoca il permesso temporaneo dopo la chiusura dell'applicazione ricevente.

Per i provider di sistema, Android richiede la specifica di permessi concreti nel manifest dell'applicazione. Ad esempio, accedere ai contatti richiede READ_CONTACTS, e accedere al calendario richiede READ_CALENDAR. A partire da Android 6, questi permessi vengono richiesti in fase di esecuzione, non durante l'installazione.

Domande frequenti

Cos'è Content Provider in Android?

Content Provider è un componente Android che fornisce un'interfaccia standard per lo scambio di dati tra applicazioni tramite ContentResolver. Astrae il metodo di archiviazione (SQLite, file, rete) e garantisce un accesso sicuro ai dati con controllo dei permessi di lettura e scrittura.

Cos'è l'authority in Content Provider?

Authority è una stringa identificativa univoca del provider specificata in AndroidManifest.xml. Forma la prima parte dell'URI content://authority/path e viene utilizzata dal sistema per instradare le chiamate ContentResolver al provider corretto. L'authority deve essere univoca tra tutte le applicazioni sul dispositivo.

Come funziona UriMatcher in Content Provider?

UriMatcher mappa gli URI a codici numerici. Aggiungi pattern tramite addURI, poi chiami match per ottenere il codice di un URI in entrata. Ciò consente ai metodi query, insert, update e delete di determinare quale tabella o record viene richiesto ed eseguire l'operazione corrispondente nel database.

È necessario chiudere il Cursor dopo aver lavorato con ContentResolver?

Sì, il Cursor deve essere sempre chiuso dopo l'uso. Se il Cursor non viene chiuso, si verifica una perdita di memoria perché mantiene un riferimento Binder ai dati del provider. In Kotlin, usa la funzione use per la chiusura automatica, e in Java — try-with-resources o cursor.close() in un blocco finally.

Qual è la differenza tra Content Provider e SQLiteDatabase?

Content Provider è un componente per l'accesso ai dati tra applicazioni, mentre SQLiteDatabase è un meccanismo di archiviazione interno per una singola applicazione. Content Provider fornisce un'interfaccia URI e controllo dei permessi, mentre SQLiteDatabase lavora direttamente con il database senza meccanismi di sicurezza a livello di sistema operativo.

Riepilogo

  • Content Provider è un componente Android standard per lo scambio sicuro di dati tra applicazioni tramite l'interfaccia unificata ContentResolver.
  • L'URI dello schema content://authority/path/id identifica il provider, la tabella e il record specifico — ogni segmento ha uno scopo preciso.
  • UriMatcher semplifica l'analisi degli URI in entrata all'interno del provider, eliminando l'analisi manuale delle stringhe in ogni metodo CRUD.
  • Il provider viene registrato in AndroidManifest.xml con gli attributi authorities e exported — questo è un meccanismo di sistema senza il quale il provider non funzionerà.
  • ContentValues vengono passati a insert e update come coppie chiave-valore, e un Cursor viene restituito da query per iterare sui risultati.
  • readPermission e writePermission nel manifest controllano l'accesso ai dati, mentre FLAG_GRANT_URI_PERMISSION fornisce accesso temporaneo a un URI specifico.
  • Per il caricamento asincrono dei dati da Content Provider, usa CursorLoader, Room con ContentProvider o LoaderManager — questo evita il blocco del thread UI.

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.

Discuti il progetto

Leggi anche