Content Provider: arquitetura do componente e princípio de funcionamento

Autor: IT Sectr Publicado: 2026-06-17 Tempo de leitura: 8 min

Content Provider é um componente Android que fornece uma interface unificada para acesso a dados entre aplicações. Ele abstrai o armazenamento físico (SQLite, arquivos, fontes de rede) e permite a troca segura de informações através do ContentResolver. De acordo com o Android Developer Guide, 2026, o Content Provider é um dos quatro componentes principais de uma aplicação Android, juntamente com Activity, Service e BroadcastReceiver. Sua tarefa é disponibilizar dados para outras aplicações com controle de permissões de leitura e escrita.

Pontos principais

  • Content Provider é um componente Android padrão para troca de dados entre aplicações através da interface ContentResolver.
  • URI (content://) identifica uma tabela ou registro e é usada para todas as operações CRUD com o provedor.
  • UriMatcher é uma classe utilitária que analisa URIs de entrada e determina qual tabela ou linha está sendo solicitada.
  • As permissões de leitura e escrita são definidas no manifesto e solicitadas ao usuário durante a instalação.
  • CursorLoader ou Room com Content Provider permitem carregamento assíncrono de dados do provedor sem bloquear a thread da UI.

O que é Content Provider?

Content Provider é um componente Android que gerencia o acesso a um armazenamento de dados centralizado e o disponibiliza para outras aplicações através de uma interface de contrato unificada. Ele oculta os detalhes de implementação do armazenamento: os dados podem ser armazenados em SQLite, no sistema de arquivos, na nuvem ou ser o resultado de uma requisição de rede.

O Android inclui Content Providers integrados para dados do sistema — ContactsContract, MediaStore, CalendarContract, CallLog. Aplicações de terceiros também podem criar seus próprios provedores para troca segura de dados. Cada provedor é registrado no AndroidManifest.xml com uma authority — uma string única que forma a primeira parte da URI.

Como o Content Provider funciona

O Content Provider opera em um modelo cliente-servidor. O provedor atua como um servidor que implementa seis métodos obrigatórios: query, insert, update, delete, getType e onCreate. O cliente (outra aplicação) acessa o provedor através do ContentResolver, que traduz as chamadas nos métodos correspondentes do provedor através do mecanismo IPC do Android.

URI e authority

Cada Content Provider é identificado por uma URI do esquema content://. Por exemplo, content://com.example.app.provider/items. A primeira parte authority (com.example.app.provider) é vinculada à classe do provedor no manifesto. O caminho /items aponta para uma tabela, enquanto /items/5 aponta para um registro específico com ID=5.

Processo de chamada

Quando uma aplicação chama ContentResolver.query(URI), o Android verifica as permissões do pacote chamador, encontra o provedor pela authority e inicia seu processo se ele ainda não estiver em execução. O provedor executa a consulta e retorna um Cursor — um objeto que contém o resultado e permite ao cliente iterar sobre os registros.

Métodos principais do Content Provider

A classe ContentProvider requer a implementação de seis métodos abstratos. Cada método aceita uma URI e retorna um resultado correspondente ao tipo de operação. O sistema chama esses métodos de qualquer processo, portanto eles devem ser thread-safe e não bloquear a execução por muito tempo.

Método query

O método query aceita uma URI, uma matriz de colunas projection, uma string selection com argumentos e uma ordem de classificação. Ele retorna um Cursor com dados. Na implementação, você precisa analisar a URI usando UriMatcher e executar a consulta SQL correspondente no banco de dados.

Métodos insert, update, delete

Esses métodos modificam dados no armazenamento. insert recebe ContentValues — pares chave-valor — e retorna a URI do novo registro. update e delete aceitam uma selection para filtrar registros e retornam o número de linhas afetadas. Após alterar os dados, o provedor deve notificar através de ContentResolver.notifyChange.

MétodoFinalidadeRetorno
queryObter dados por URICursor ou null
insertAdicionar novo registroURI do novo registro
updateAtualizar registros existentesint (qtd. de linhas)
deleteExcluir registrosint (qtd. de linhas)
getTypeTipo MIME para URIString
onCreateInicialização do provedorboolean

ContentResolver e URI no Android

ContentResolver é um ponto de acesso único para trabalhar com todos os Content Providers no sistema. A aplicação cliente nunca chama os métodos do provedor diretamente — apenas através do ContentResolver, que o Android obtém do contexto. As operações CRUD no ContentResolver têm os mesmos nomes que no provedor, mas aceitam URIs em vez de referências diretas.

UriMatcher

Para analisar URIs de entrada dentro do provedor, usa-se UriMatcher. Ele permite mapear uma URI para um código numérico — por exemplo, a URI content://authority/items produz o código 1, e content://authority/items/# produz o código 2. Isso elimina a necessidade de análise manual da string URI em cada método.

kotlin
// Usando ContentResolver para acessar contatos
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("Contatos", "Nome: $name")
    }
}

O Cursor deve ser sempre fechado após o uso — no exemplo acima, a função use (extensão do Kotlin) faz isso. Se o Cursor não for fechado, ocorre um vazamento de memória porque ele mantém uma referência aos dados no pool de Binder. Para cenários de UI, use CursorLoader ou Room com LiveData/Flow.

Exemplo de Content Provider em Kotlin

Criar seu próprio Content Provider começa com a extensão da classe ContentProvider. O provedor trabalha com um banco de dados SQLite através do SQLiteOpenHelper e usa UriMatcher para determinar o tipo de consulta. Considere uma implementação mínima para gerenciar uma lista de notas.

Registro no manifesto

O provedor é registrado no AndroidManifest.xml dentro da tag application. O atributo authorities define um identificador único, e exported determina se outras aplicações podem acessar o provedor. Sem exported=true, o provedor é acessível apenas dentro da sua aplicação.

kotlin
// Exemplo de Content Provider para notas
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 omitidos por brevidade
}

Após criar a classe do provedor, ela deve ser registrada no manifesto com os atributos android:authorities e android:exported (true se o provedor for público). O sistema cria uma instância do provedor no primeiro acesso — isso ocorre na thread da UI, portanto o onCreate deve executar rapidamente.

Proteção de dados através de permissões

O Content Provider permite gerenciar o acesso aos dados em dois níveis: permissões de leitura e permissões de escrita. Elas são definidas no manifesto com os atributos android:readPermission e android:writePermission. Se a aplicação cliente não tiver a permissão correspondente, o sistema rejeita a chamada com uma SecurityException.

Permissões em nível de URI

O Android suporta permissões temporárias através das flags FLAG_GRANT_READ_URI_PERMISSION e FLAG_GRANT_WRITE_URI_PERMISSION. Isso é útil quando uma aplicação passa uma URI de arquivo para outra aplicação via Intent — o destinatário obtém acesso apenas àquela URI específica por um tempo limitado. O sistema revoga a permissão temporária após a aplicação receptora terminar.

Para provedores do sistema, o Android exige a especificação de permissões específicas no manifesto da aplicação. Por exemplo, acessar contatos requer READ_CONTACTS, e acessar o calendário requer READ_CALENDAR. A partir do Android 6, essas permissões são solicitadas em tempo de execução, não durante a instalação.

Perguntas frequentes

O que é Content Provider no Android?

Content Provider é um componente Android que fornece uma interface padrão para troca de dados entre aplicações através do ContentResolver. Ele abstrai o método de armazenamento (SQLite, arquivos, rede) e garante acesso seguro aos dados com controle de permissões de leitura e escrita.

O que é authority no Content Provider?

Authority é uma string identificadora única do provedor especificada no AndroidManifest.xml. Ela forma a primeira parte da URI content://authority/path e é usada pelo sistema para rotear chamadas do ContentResolver ao provedor correto. A authority deve ser única entre todas as aplicações no dispositivo.

Como o UriMatcher funciona no Content Provider?

UriMatcher mapeia URIs para códigos numéricos. Você adiciona padrões via addURI, depois chama match para obter o código de uma URI de entrada. Isso permite que os métodos query, insert, update e delete determinem qual tabela ou registro está sendo solicitado e realizem a operação correspondente no banco de dados.

Preciso fechar o Cursor após trabalhar com ContentResolver?

Sim, o Cursor deve ser sempre fechado após o uso. Se o Cursor não for fechado, ocorre um vazamento de memória porque ele mantém uma referência Binder aos dados do provedor. Em Kotlin, use a função use para fechamento automático, e em Java — try-with-resources ou cursor.close() em um bloco finally.

Qual a diferença entre Content Provider e SQLiteDatabase?

Content Provider é um componente para acesso a dados entre aplicações, enquanto SQLiteDatabase é um mecanismo de armazenamento interno para uma única aplicação. O Content Provider fornece uma interface URI e controle de permissões, enquanto o SQLiteDatabase trabalha diretamente com o banco de dados sem mecanismos de segurança em nível de sistema operacional.

Resumo

  • Content Provider é um componente Android padrão para troca segura de dados entre aplicações através da interface unificada ContentResolver.
  • A URI do esquema content://authority/path/id identifica o provedor, a tabela e o registro específico — cada segmento tem uma finalidade estrita.
  • UriMatcher simplifica a análise de URIs de entrada dentro do provedor, eliminando a análise manual de strings em cada método CRUD.
  • O provedor é registrado no AndroidManifest.xml com os atributos authorities e exported — este é um mecanismo do sistema sem o qual o provedor não funcionará.
  • ContentValues são passados para insert e update como pares chave-valor, e um Cursor é retornado de query para iterar sobre os resultados.
  • readPermission e writePermission no manifesto controlam o acesso aos dados, enquanto FLAG_GRANT_URI_PERMISSION fornece acesso temporário a uma URI específica.
  • Para carregamento assíncrono de dados do Content Provider, use CursorLoader, Room com ContentProvider ou LoaderManager — isso evita bloquear a thread da UI.

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