Content Provider: arquitectura del componente y principio de funcionamiento

Autor: IT Sectr Publicado: 2026-06-17 Tiempo de lectura: 8 min

Content Provider es un componente de Android que proporciona una interfaz unificada para el acceso a datos entre aplicaciones. Abstrae el almacenamiento físico (SQLite, archivos, fuentes de red) y permite el intercambio seguro de información a través de ContentResolver. Según Android Developer Guide, 2026, Content Provider es uno de los cuatro componentes principales de una aplicación Android, junto con Activity, Service y BroadcastReceiver. Su tarea es hacer que los datos estén disponibles para otras aplicaciones con control de permisos de lectura y escritura.

Puntos clave

  • Content Provider es un componente estándar de Android para el intercambio de datos entre aplicaciones a través de la interfaz ContentResolver.
  • URI (content://) identifica una tabla o registro y se utiliza para todas las operaciones CRUD con el proveedor.
  • UriMatcher es una clase de utilidad que analiza las URI entrantes y determina qué tabla o fila se solicita.
  • Los permisos de lectura y escritura se definen en el manifiesto y se solicitan al usuario durante la instalación.
  • CursorLoader o Room con Content Provider permiten la carga asíncrona de datos desde el proveedor sin bloquear el hilo de la UI.

¿Qué es Content Provider?

Content Provider es un componente de Android que gestiona el acceso a un almacén de datos centralizado y lo proporciona a otras aplicaciones a través de una interfaz de contrato unificada. Oculta los detalles de implementación del almacenamiento: los datos pueden almacenarse en SQLite, en el sistema de archivos, en la nube o ser el resultado de una solicitud de red.

Android incluye Content Providers incorporados para datos del sistema — ContactsContract, MediaStore, CalendarContract, CallLog. Las aplicaciones de terceros también pueden crear sus propios proveedores para el intercambio seguro de datos. Cada proveedor se registra en AndroidManifest.xml con una authority — una cadena única que forma la primera parte de la URI.

Cómo funciona Content Provider

Content Provider opera en un modelo cliente-servidor. El proveedor actúa como servidor que implementa seis métodos obligatorios: query, insert, update, delete, getType y onCreate. El cliente (otra aplicación) accede al proveedor a través de ContentResolver, que traduce las llamadas a los métodos correspondientes del proveedor mediante el mecanismo IPC de Android.

URI y authority

Cada Content Provider se identifica mediante una URI del esquema content://. Por ejemplo, content://com.example.app.provider/items. La primera parte authority (com.example.app.provider) se vincula a la clase del proveedor en el manifiesto. La ruta /items apunta a una tabla, mientras que /items/5 apunta a un registro específico con ID=5.

Proceso de llamada

Cuando una aplicación llama a ContentResolver.query(URI), Android verifica los permisos del paquete llamante, encuentra el proveedor por su authority e inicia su proceso si aún no está en ejecución. El proveedor ejecuta la consulta y devuelve un Cursor — un objeto que contiene el resultado y permite al cliente iterar sobre los registros.

Métodos principales de Content Provider

La clase ContentProvider requiere la implementación de seis métodos abstractos. Cada método acepta una URI y devuelve un resultado correspondiente al tipo de operación. El sistema llama a estos métodos desde cualquier proceso, por lo que deben ser seguros para subprocesos y no bloquear la ejecución durante mucho tiempo.

Método query

El método query acepta una URI, una matriz de columnas projection, una cadena selection con argumentos y un orden de clasificación. Devuelve un Cursor con datos. En la implementación, es necesario analizar la URI con UriMatcher y ejecutar la consulta SQL correspondiente en la base de datos.

Métodos insert, update, delete

Estos métodos modifican datos en el almacén. insert recibe ContentValues — pares clave-valor — y devuelve la URI del nuevo registro. update y delete aceptan una selección para filtrar registros y devuelven la cantidad de filas afectadas. Después de cambiar los datos, el proveedor debe notificarlo a través de ContentResolver.notifyChange.

MétodoPropósitoRetorno
queryObtener datos por URICursor o null
insertAgregar un nuevo registroURI del nuevo registro
updateActualizar registros existentesint (cant. de filas)
deleteEliminar registrosint (cant. de filas)
getTypeTipo MIME para URIString
onCreateInicialización del proveedorboolean

ContentResolver y URI en Android

ContentResolver es un punto de acceso único para trabajar con todos los Content Providers del sistema. La aplicación cliente nunca llama a los métodos del proveedor directamente — solo a través de ContentResolver, que Android obtiene del contexto. Las operaciones CRUD en ContentResolver tienen los mismos nombres que en el proveedor, pero aceptan URI en lugar de referencias directas.

UriMatcher

Para analizar las URI entrantes dentro del proveedor, se utiliza UriMatcher. Permite asignar una URI a un código numérico — por ejemplo, la URI content://authority/items produce el código 1, y content://authority/items/# produce el código 2. Esto elimina la necesidad de analizar manualmente la cadena URI en cada método.

kotlin
// Usando ContentResolver para acceder a contactos
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("Contactos", "Nombre: $name")
    }
}

El Cursor debe cerrarse siempre después de su uso — en el ejemplo anterior, la función use (extensión de Kotlin) lo hace. Si el Cursor no se cierra, se produce una fuga de memoria porque mantiene una referencia a los datos en el grupo de Binder. Para escenarios de UI, use CursorLoader o Room con LiveData/Flow.

Ejemplo de Content Provider en Kotlin

La creación de su propio Content Provider comienza con la extensión de la clase ContentProvider. El proveedor trabaja con una base de datos SQLite a través de SQLiteOpenHelper y utiliza UriMatcher para determinar el tipo de consulta. Considere una implementación mínima para gestionar una lista de notas.

Registro en el manifiesto

El proveedor se registra en AndroidManifest.xml dentro de la etiqueta application. El atributo authorities establece un identificador único, y exported determina si otras aplicaciones pueden acceder al proveedor. Sin exported=true, el proveedor solo es accesible dentro de su aplicación.

kotlin
// Ejemplo 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 brevedad
}

Después de crear la clase del proveedor, debe registrarse en el manifiesto con los atributos android:authorities y android:exported (true si el proveedor es público). El sistema crea una instancia del proveedor al primer acceso — esto ocurre en el hilo de la UI, por lo que onCreate debe ejecutarse rápidamente.

Protección de datos mediante permisos

Content Provider permite gestionar el acceso a los datos en dos niveles: permisos de lectura y permisos de escritura. Se establecen en el manifiesto con los atributos android:readPermission y android:writePermission. Si la aplicación cliente no tiene el permiso correspondiente, el sistema rechaza la llamada con una SecurityException.

Permisos a nivel de URI

Android admite permisos temporales mediante las banderas FLAG_GRANT_READ_URI_PERMISSION y FLAG_GRANT_WRITE_URI_PERMISSION. Esto es útil cuando una aplicación pasa una URI de archivo a otra aplicación a través de un Intent — el destinatario obtiene acceso solo a esa URI específica durante un tiempo limitado. El sistema revoca el permiso temporal después de que la aplicación receptora finaliza.

Para los proveedores del sistema, Android requiere especificar permisos concretos en el manifiesto de la aplicación. Por ejemplo, acceder a los contactos requiere READ_CONTACTS, y acceder al calendario requiere READ_CALENDAR. A partir de Android 6, estos permisos se solicitan en tiempo de ejecución, no durante la instalación.

Preguntas frecuentes

¿Qué es Content Provider en Android?

Content Provider es un componente de Android que proporciona una interfaz estándar para el intercambio de datos entre aplicaciones a través de ContentResolver. Abstrae el método de almacenamiento (SQLite, archivos, red) y garantiza un acceso seguro a los datos con control de permisos de lectura y escritura.

¿Qué es authority en Content Provider?

Authority es una cadena identificadora única del proveedor que se especifica en AndroidManifest.xml. Forma la primera parte de la URI content://authority/path y el sistema la utiliza para enrutar las llamadas de ContentResolver al proveedor correcto. La authority debe ser única entre todas las aplicaciones del dispositivo.

¿Cómo funciona UriMatcher en Content Provider?

UriMatcher asigna URI a códigos numéricos. Agrega patrones mediante addURI, luego llama a match para obtener el código de una URI entrante. Esto permite que los métodos query, insert, update y delete determinen qué tabla o registro se solicita y realicen la operación correspondiente en la base de datos.

¿Es necesario cerrar el Cursor después de trabajar con ContentResolver?

Sí, el Cursor debe cerrarse siempre después de su uso. Si no se cierra, se produce una fuga de memoria porque mantiene una referencia Binder a los datos del proveedor. En Kotlin, use la función use para el cierre automático, y en Java — try-with-resources o cursor.close() en un bloque finally.

¿En qué se diferencia Content Provider de SQLiteDatabase?

Content Provider es un componente para el acceso a datos entre aplicaciones, mientras que SQLiteDatabase es un mecanismo de almacenamiento interno para una sola aplicación. Content Provider proporciona una interfaz URI y control de permisos, mientras que SQLiteDatabase trabaja directamente con la base de datos sin mecanismos de seguridad a nivel de sistema operativo.

Resumen

  • Content Provider es un componente estándar de Android para el intercambio seguro de datos entre aplicaciones a través de la interfaz unificada ContentResolver.
  • La URI del esquema content://authority/path/id identifica el proveedor, la tabla y el registro específico — cada segmento tiene un propósito estricto.
  • UriMatcher simplifica el análisis de las URI entrantes dentro del proveedor, eliminando el análisis manual de cadenas en cada método CRUD.
  • El proveedor se registra en AndroidManifest.xml con los atributos authorities y exported — este es un mecanismo del sistema sin el cual el proveedor no funcionará.
  • ContentValues se pasan a insert y update como pares clave-valor, y un Cursor se devuelve de query para iterar sobre los resultados.
  • readPermission y writePermission en el manifiesto controlan el acceso a los datos, mientras que FLAG_GRANT_URI_PERMISSION proporciona acceso temporal a una URI específica.
  • Para la carga asíncrona de datos desde Content Provider, use CursorLoader, Room con ContentProvider o LoaderManager — esto evita bloquear el hilo de la UI.

Desarrollaremos una aplicación móvil llave en mano

IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.

Discutir el proyecto

Lea también