Die Contacts-Permission-Richtlinie von Google Play besagt, dass Apps, die ab dem 27. Januar 2027 Android 17 (API Level 37) oder höher als Ziel haben, nur noch READ_CONTACTS , wenn der Android Contact Picker eine Kernfunktion nicht unterstützen kann, und müssen dies mit einer Play-Console-Erklärung begründen. Für die meisten Capacitor-Apps, die Kontakte lesen, um Freunde einzuladen, Dateien zu teilen oder eine Telefonnummer einzutragen, ist die Lösung, auf den Contact Picker umzusteigen und die Berechtigung zu entfernen. Dieser Leitfaden erklärt die Richtlinie und zeigt, wie man das mit @capgo/capacitor-contactsumsetzt, und erklärt, was zu tun ist, wenn man wirklich das vollständige Adressbuch benötigt.
Inhalt der Richtlinie
Google hat die Richtlinie am 15. April 2026 im Rahmen einer Reihe von Datenschutz-Updates angekündigt. Die wichtigsten Punkte aus den Play-Console-Hilfeseiten:
- Umfang: Apps, die auf Android 17 (API 37) oder höher abzielen und die Berechtigung anfordern
READ_CONTACTS. - Regel: Sie dürfen die Berechtigung nur anfordern,
READ_CONTACTSwenn der Android Contact Picker für eine Kernfunktion Ihrer App nicht ausreicht. - Erklärung: Apps, die die Berechtigung beibehalten, müssen in der Play Console eine Erklärung abgeben, die beschreibt, welche Funktionen sie benötigen und warum der Picker nicht ausreicht.
- Zeitplan: Die Play Console begann im September 2026, Apps, die
READ_CONTACTSdeklarieren, darauf hinzuweisen. Die Einhaltung ist ab dem 27. Januar 2027 verpflichtend. Google erwähnt eine 30-tägige Selbstbedienungserweiterung in der Play Console. - Ausnahmen: Private Apps und Apps für das Enterprise-Geräte-Management sind nicht betroffen.
- Daten: Kontaktdaten sind gemäß der User Data Policy persönlich und sensibel, und du darfst nicht öffentliche Kontaktdaten nicht ohne Genehmigung der betroffenen Personen veröffentlichen.
Anwendungsfälle, die READ_CONTACTS behalten können
Google listet Kernfunktionen wie Kontaktmanagement-Apps, Dialer und SMS-Apps, Anrufliste und Anrufscreening, CRM, Barrierefreiheitsfunktionen, persönliche Assistenten, Freundes-Matching, Backup und Restore sowie Tastaturen oder Autovervollständigung auf.
Anwendungsfälle, die auf den Picker umsteigen sollten
Jemanden einladen oder weiterempfehlen, Dateien teilen, zusammenarbeiten oder einen Kontakt auswählen, um Geld zu senden. Wenn das der Grund ist, warum deine App Kontakte liest, wird die Erklärung nicht akzeptiert. Verwende den Picker.
Änderungen unter Android 17
Android 17 bringt einen neuen systemeigenen Contact Picker. Apps erhalten eine temporäre, schreibgeschützte Session-URI, die nur die vom Benutzer ausgewählten Kontakte und Felder offenlegt – ganz ohne Berechtigung. Für Apps, die Android 17 als Ziel haben, aktualisiert das System automatisch das klassische Intent.ACTION_PICK contacts-Intent auf diesen neuen Picker. Apps können zudem über eine neue Intent-Action bestimmte Datenfelder (Telefon, E-Mail, Postadresse) und Mehrfachauswahl anfordern.
Auf älteren Android-Versionen hat das Auswählen einer bestimmten Datenzeile (z. B. einer Telefonnummer) über den Kontakte-Picker immer eine URI zurückgegeben, die die App ohne READ_CONTACTSlesen kann. Genau das macht einen berechtigungsfreien Flow auf jeder Android-Version möglich.
Warum „Kontakt wählen“ früher READ_CONTACTS brauchte
Viele Capacitor-Plugins implementieren „Kontakt auswählen“, indem sie den Picker für einen gesamten Kontakt öffnen und anschließend das Adressbuch nach den Telefonnummern und E-Mails dieses Kontakts abfragen. Diese zweite Abfrage benötigt READ_CONTACTS. Selbst Apps, die nur eine Telefonnummer wollten, mussten daher die Berechtigung deklarieren – genau das zielt die neue Richtlinie an.
Die Lösung: Fordere den Picker direkt um das benötigte Feld an, damit die Ergebnis-URI bereits die Daten enthält.
Telefonnummer, E-Mail oder Adresse wählen ohne READ_CONTACTS
@capgo/capacitor-contacts hat eine property Option in Version 8.1.0 hinzugefügt. Wenn gesetzt, öffnet Android den Picker gegen die Tabelle für Telefon, E-Mail oder Postadresse und liest die ausgewählte Zeile aus der erteilten URI. Kein READ_CONTACTS ist auf jeder Android-Version erforderlich. Auf iOS benötigt der System-Picker nie eine Kontakte-Berechtigung.
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;
}
Mit property, enthält das Ergebnis den Kontakt id, displayName und nur die ausgewählte Eigenschaft. Mehrfachauswahl wird ignoriert, das Auswählen von Eigenschaften gibt immer einen Wert zurück. Wenn der Benutzer abbricht, prüfe auf ein leeres Array.
deklariert das Plugin nicht READ_CONTACTS oder WRITE_CONTACTS in seinem eigenen Manifest, sodass dein gemergtes Manifest sauber bleibt, wenn du nur Property Picking verwendest.
Wenn du trotzdem READ_CONTACTS benötigst
Diese Plugin-Methoden lesen das Adressbuch und erfordern weiterhin die Berechtigung:
pickContacts()oderpickContact()ohneproperty, wenn du den vollständigen Kontakt-Eintrag möchtestgetContacts(),getContactById(),countContacts()getGroups(),getGroupById(),getAccounts()
Wenn deine App ein CRM, ein Backup-Tool oder eine Freundesvermittlung ist, ist das ein legitimer Kernzweck. Füge die Berechtigung selbst hinzu und reiche die Erklärung ein:
<!-- 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);
}
Die Richtlinie richtet sich an READ_CONTACTS. Das Schreiben von Kontakten mit WRITE_CONTACTS (für createContact, updateContactById, deleteContactById) ist nicht Gegenstand dieser Richtlinie, füge sie aber nur hinzu, wenn du diese Methoden verwendest.
Migrationsplan für eine Capacitor-App
-
Prüfe das gemergte Manifest. Baue dein Release und öffne
android/app/build/intermediates/merged_manifest/(oder nutze den Tab „Merged Manifest“ in Android Studio). Manche Plugins fügenREAD_CONTACTShinzu, ohne dass du es merkst. Wenn ein Plugin es hinzufügt und du es nicht brauchst, entferne es mittools: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 jeden Ort auf, an dem du Kontakte berührst. Entscheide für jeden: Picker mit einer Eigenschaft oder vollständiges Adressbuch.
-
Einladungs- und Sharing-Flows ersetzen mit
pickContacts({ property }). -
Berechtigung nur für Kernfunktionen beibehalten, und bereite den Erklärungstext vor: welche Funktion, warum der Picker nicht ausreicht, ein Video, falls die Funktion schwer zu finden ist.
-
Einen Native Build ausliefern. Manifest- und Plugin-Änderungen erfordern ein neues Play-Release. Wenn du in der CI baust, Capgo Build signierte Android-Builds erstellen, und die Android Keystore Generator hilft dir bei der erstmaligen Einrichtung der Signierung.
-
UI-Änderungen via Live Update ausliefern. Sobald das neue native Plugin live ist, können Text- und Flow-Anpassungen rund um den Picker über Capgo Live Updates.
Migration von einem anderen Contacts-Plugin
Wenn du @capacitor-community/contacts (8.0.0 zum Zeitpunkt der Erstellung), sein Android pickContact fordert die Berechtigungsgruppe für Kontakte an, bevor der Picker geöffnet wird, und liest dann den vollständigen Kontakt aus dem Adressbuch. Es gibt keine Eigenschaft mode. Auch die Methodennamen unterscheiden sich (getContact vs getContactById, Projektionsobjekte vs. ein fields Array). Unser Vergleich des Community-Kontakte-Plugins und des Capgo-Plugins ordnet jeden Aufruf zu.
Wenn Sie in Capacitor noch ein Cordova-Kontakte-Plugin verwenden, ist jetzt ein guter Zeitpunkt, es zu ersetzen. Siehe Migration von Cordova zu Capacitor.
Fehlerbehebung
Der Picker gibt einen Kontakt ohne Telefonnummer zurück. Du hast pickContacts() ohne property und die App hat keine READ_CONTACTS. Nur id und displayName (und unter Android 17+ vom Picker freigegebene Felder) zurück. Füge property.
Die Play Console meldet weiterhin, dass die App READ_CONTACTS deklariert. Eine Library fügt es hinzu. Prüfe das merged Manifest und entferne es mit tools:node="remove". Prüfe auch ältere Releases in anderen Tracks; jedes aktive Artefakt zählt.
Deklaration abgelehnt. Einladungen, Empfehlungen und Teilen werden als Anwendungsfälle für den Picker aufgeführt. Überarbeite das Feature oder zeige klar, warum die vollständige Liste unverzichtbar ist (z. B. Friend Matching gegen das gesamte Adressbuch).
iOS fragt nach der Kontaktberechtigung. Du rufst eine Methode auf, die das Adressbuch ausliest. Der Picker benötigt das nie. Entferne NSContactsUsageDescription wenn du nur auswählst.
Wichtige Termine
| Datum | Was passiert |
|---|---|
| 15. April 2026 | Richtlinie angekündigt |
| September 2026 | Play Console fordert Apps auf, die angeben, READ_CONTACTS eine Erklärung abzugeben |
| 27. Januar 2027 | Compliance verpflichtend für Apps, die auf Android 17 (API 37) oder höher abzielen |
Prüfe vor dem Einreichen die Hilfeseite der Play Console zur Richtlinie; Google kann Fristen und Formulierungen ändern.