Google Play’s Contacts Permissions policy means that, from January 27, 2027, apps targeting Android 17 (API level 37) or later may only request READ_CONTACTS if the Android Contact Picker cannot support a core feature, and must justify it with a Play Console declaration. For most Capacitor apps that read contacts to invite a friend, share a file or fill in a phone number, the fix is to switch to the Contact Picker and remove the permission. This guide explains the policy, shows how to do that with @capgo/capacitor-contactsy cubre qué hacer si realmente necesitas el libro de contactos completo.
¿Qué dice la política?
Google anunció la política el 15 de abril de 2026, como parte de un conjunto de actualizaciones de privacidad. Los puntos clave, desde las páginas de ayuda de la Consola de Play:
- Ámbito: aplicaciones que se dirigen a Android 17 (API 37) o superior y solicitan
READ_CONTACTS. - Regla: sólo puede solicitar
READ_CONTACTSsi el selector de contactos de Android no es suficiente para una característica fundamental de su aplicación. - Declaración: las aplicaciones que mantengan la autorización deben llenar una declaración en la Consola de Play describiendo qué características necesitan y por qué el selector no es suficiente.
- Cronograma: Consola de Play comenzó a solicitar a las aplicaciones que declaren
READ_CONTACTSen septiembre de 2026. La conformidad es obligatoria el 27 de enero de 2027. Google menciona una extensión de autoatención de 30 días en la Consola de Play. - Exenciones: Las aplicaciones privadas y la administración de dispositivos de empresa están fuera del alcance.
- Datos: Los datos de contactos son personales y sensibles según la política de datos del usuario, y no se pueden publicar datos de contactos no públicos sin autorización de las personas a las que se refieren.
Uso de casos que pueden mantener READ_CONTACTS:
Google enumera características básicas como aplicaciones de gestión de contactos, marcadores y aplicaciones de SMS, historial de llamadas y pantalla de llamadas, CRM, características de accesibilidad, asistentes personales, coincidencia de amigos, respaldo y restauración, y teclados o autocompletado.
Uso de casos que deben cambiar a el selector:
Invitar o referir a alguien, compartir archivos, colaborar o elegir un contacto para enviar dinero. Si es por eso que su aplicación lee contactos, la declaración no será aceptada. Utilice el selector.
¿Qué cambia en Android 17:
Android 17 envía un nuevo sistema Selector de Contactos. Las aplicaciones obtienen una URI de sesión temporal y de solo lectura que solo expone los contactos y campos que el usuario seleccionó, sin ninguna autorización. Para las aplicaciones que se dirigen a Android 17, el sistema actualiza automáticamente el clásico Intent.ACTION_PICK intento de contactos a este nuevo selector. Las aplicaciones también pueden solicitar campos de datos específicos (teléfono, correo electrónico, dirección postal) y selección múltiple a través de una nueva acción de intento.
En versiones de Android más antiguas, seleccionar una fila de datos específica (por ejemplo, un número de teléfono) a través del selector de contactos siempre ha devuelto una URI que la aplicación puede leer sin READ_CONTACTSEso es lo que hace posible un flujo sin permisos en todas las versiones de Android.
¿Por qué "seleccionar un contacto" requería READ_CONTACTS
Muchos plugins Capacitor implementan "seleccionar contacto" abriendo el selector para un contacto completo, luego consultando el libro de direcciones para los números de teléfono y correos electrónicos del contacto. Esa segunda consulta necesitaba READ_CONTACTSIncluso las aplicaciones que solo querían un número de teléfono terminaron declarando la permiso, lo cual es exactamente lo que la política busca.
La solución es preguntar al selector por el campo específico que necesitas, de modo que la URI del resultado ya contenga la información.
Selecciona un teléfono, correo electrónico o dirección sin READ_CONTACTS
@capgo/capacitor-contacts se agregó una property opción en la versión 8.1.0. Cuando está configurada, Android abre el selector contra la tabla de teléfonos, correos electrónicos o direcciones postales y lee la fila seleccionada de la URI concedida. No READ_CONTACTS es necesario en ninguna versión de Android. En iOS, el selector del sistema nunca necesita una permiso de contactos.
bun add @capgo/capacitor-contacts
bunx cap sync
import { CapacitorContacts, ContactProperty } from '@capgo/capacitor-contacts';
export async function pickPhoneNumber(): Promise<string | undefined> {
const { contacts } = await CapacitorContacts.pickContacts({
property: ContactProperty.PhoneNumber,
});
const picked = contacts[0];
return picked?.phoneNumbers?.[0]?.value;
}
export async function pickEmail(): Promise<string | undefined> {
const { contacts } = await CapacitorContacts.pickContacts({
property: ContactProperty.EmailAddress,
});
return contacts[0]?.emailAddresses?.[0]?.value;
}
Con property, el resultado contiene el contacto id, displayName y la propiedad seleccionada solo. La selección múltiple se ignora, la selección de propiedad siempre devuelve un valor. Si el usuario cancela, verifica un array vacío.
The plugin no declara READ_CONTACTS o WRITE_CONTACTS Su propio manifiesto, por lo que si solo utiliza la propiedad de selección, su manifiesto combinado queda limpio.
Cuando todavía necesitas leer contactos
Estos métodos de plugins leen el libro de direcciones y siguen requiriendo la autorización:
pickContacts()opickContact()cuandopropertycuando desees el registro de contacto completogetContacts(),getContactById(),countContacts()getGroups(),getGroupById(),getAccounts()
If your app is a CRM, a backup tool or a friend matching feature, that is a legitimate core use. Add the permission yourself and file the declaration:
<!-- android/app/src/main/AndroidManifest.xml -->
<uses-permission android:name="android.permission.READ_CONTACTS" />
import { CapacitorContacts } from '@capgo/capacitor-contacts';
const perm = await CapacitorContacts.requestPermissions({ permissions: ['readContacts'] });
if (perm.readContacts === 'granted' || perm.readContacts === 'limited') {
const { contacts } = await CapacitorContacts.getContacts({
fields: ['displayName', 'phoneNumbers'],
limit: 200,
offset: 0,
});
console.log(contacts.length);
}
. Escribe contactos con READ_CONTACTSEscribiendo contactos con WRITE_CONTACTS cuando createContact, updateContactById, deleteContactByIdno es el objeto de esta política, pero solo agregue si utiliza esos métodos.
Plan de migración para una aplicación Capacitor
-
Realice un auditorio del manifiesto fusionado. Construya su versión de lanzamiento y abra
android/app/build/intermediates/merged_manifest/(o utilice la pestaña de Manifiesto fusionado de Android Studio). Algunos plugins agreganREAD_CONTACTSsin que usted lo note. Si un plugin lo agrega y usted no lo necesita, elimine contools:node="remove":<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <uses-permission android:name="android.permission.READ_CONTACTS" tools:node="remove" /> </manifest> -
Liste cada lugar donde toque contactos. Para cada uno, decida: selector de contactos con una propiedad, o libro de direcciones completo.
-
Sustituya los flujos de invitación y compartir con
pickContacts({ property }). -
Mantenga la autorización solo para características principales, y prepara el texto de declaración: ¿qué característica, por qué el selector no es suficiente, un video si la característica es difícil de encontrar.
-
Envíe una compilación nativa. Cambios en el manifiesto y el plugin requieren una nueva versión de Play. Si construye en CI, Capgo Compilación puede producir builds de Android firmados, y el Generador de llave de Android ayuda si estás configurando la firma para la primera vez.
-
ayuda si está configurando la firma por primera vez. Una vez que el nuevo plugin nativo esté disponible, se pueden realizar ajustes en el texto y flujo del selector. Capgo live updates.
__CAPGO_KEEP_0__ actualizaciones en vivo
Si utilizas @capacitor-community/contacts Si utiliza el (8.0.0 en el momento de escribir), su Android pickContact solicita el grupo de permisos de contactos antes de abrir el selector, luego lee el contacto completo desde el libro de direcciones. No hay propiedad de modo. Los nombres de método también difieren (getContact vs getContactById, objetos de proyecto vs un fields array). Nuestra comparación del plugin de contactos de la comunidad y el plugin Capgo muestra cada llamada.
Si todavía utiliza un plugin de contactos de Cordova dentro de Capacitor, ahora es un buen momento para reemplazarlo. Consulte migrar desde Cordova a Capacitor.
Solución de problemas
El selector devuelve un contacto sin número de teléfono. Tú llamaste pickContacts() without property y la aplicación no tiene READ_CONTACTS. Solo id y displayName (vienen de nuevo (y los campos de selección concedidos en Android 17+) property.
El Console de Play todavía indica que la aplicación declara READ_CONTACTS. El Console de Play todavía dice que la aplicación declara READ_CONTACTS. tools:node="remove"Una biblioteca lo agrega. Revisa el manifiesto fusionado y elimínalo con
Rechazo de la declaración. Invites, referrals and sharing are listed as cases for the picker. Rework the feature or show clearly why the full list is core (for example friend matching that runs against the whole address book).
iOS solicita permiso de contactos. Llama llama una función que lee el libro de direcciones. No necesita nunca. Eliminar NSContactsUsageDescription si solo seleccionas.
Fecha clave
| Fecha | ¿Qué sucede |
|---|---|
| 15 de abril de 2026 | Anunciada la política |
| Septiembre de 2026 | Aplicaciones que declaran READ_CONTACTS para presentar una declaración |
| 27 de enero de 2027 | Cumplimiento obligatorio para aplicaciones que se dirijan a Android 17 (API 37) o posterior. |
Verifique la página de ayuda de la Consola de Play antes de enviar, Google puede actualizar los plazos y el lenguaje.