Wenn du eine Alternative zu Capacitor Community Contacts suchst, ist das vollständigste Drop-in-Replacement: @capgo/capacitor-contacts. Es deckt das ab, was @capacitor-community/contacts liest, erstellt, löscht und wählt Kontakte aus und ergänzt das Aktualisieren eines Kontakts ohne Änderung seiner ID, Paginierung, Gruppen, Konten, native Kontaktansichten und das Auswählen ohne Berechtigung auf Android. Das ist relevant für die Google-Play-Kontakt-Richtlinie 2027. Dieser Guide vergleicht beide und mappt jeden Aufruf, damit du in einem Nachmittag migrieren kannst.
Warum eine Alternative suchen?
@capacitor-community/contacts wird gepflegt und hat eine Capacitor 8-Release. Es ist eine gute Wahl für einfache Lese- und Erstellungs-Flows. Teams wachsen es meist aus folgenden Gründen über den Kopf:
- Keine Update-Methode. Du kannst Kontakte erstellen und löschen, aber nicht bearbeiten. Löschen und Neuerschaffen gibt dem Kontakt eine neue ID, was jede gespeicherte Referenz bricht und Daten verlieren kann, die das Plugin nicht liest.
- Keine Paginierung.
getContactsgibt das gesamte Adressbuch in einem einzigen Aufruf zurück. Auf einem Gerät mit 5.000 Kontakten und Fotos ist das langsam und speicherintensiv. - Das Auswählen erfordert auf Android die Berechtigung. Android
pickContactfordert die Berechtigungsgruppe für Kontakte an, bevor der Picker geöffnet wird, und liest dann den Kontakt aus dem Adressbuch. Unter der Kontakte-Berechtigungsrichtlinie von Google Playkönnen Apps, die Android 17 als Ziel haben, nurREAD_CONTACTSfür Kernfunktionen beibehalten. - Keine Gruppen, Konten oder nativen Bildschirme. Keine Möglichkeit, Gruppen aufzulisten, das Konto auszuwählen, in dem ein neuer Kontakt gespeichert wird, oder das Systemformular „Neuer Kontakt“ zu öffnen.
Feature-Vergleich
| Funktion | @capacitor-community/contacts 8.0 | @capgo/capacitor-contacts 8.1 |
|---|---|---|
| Ein / alle Kontakte lesen | getContact, getContacts |
getContactById, getContacts |
| Feldauswahl | projection Objekt |
fields Array |
| Paginierung | Nein | limit, offset |
| Kontakte zählen | Nein | countContacts |
| Erstellen | createContact |
createContact |
| In-Place-Update | Nein | updateContactById |
| Löschen | deleteContact |
deleteContactById |
| Einen Kontakt auswählen | pickContact |
pickContact |
| Mehrere auswählen | Nein | pickContacts({ multiple: true }) |
| Eine Telefonnummer/E-Mail/Adresse ohne Berechtigung auswählen | Nein | pickContacts({ property }) |
| Gruppen | Nein | getGroups, getGroupById, createGroup, deleteGroupById |
| Konten | Nein | getAccounts |
| Native Create-/View-/Edit-Screens | Nein | displayCreateContact, displayContactById, displayUpdateContactById |
| Getrennte Zustände für Lese- und Schreibberechtigungen | Nein (einzelner Alias) | readContacts, writeContacts |
| Eingeschränkter Zugriffszustand auf iOS | limited |
limited |
| Einstellungen öffnen | Nein | openSettings |
Installieren
bun add @capgo/capacitor-contacts
bunx cap sync
Das Plugin fügt keine Berechtigungen zu deinem Android-Manifest hinzu. Füge nur hinzu, was du nutzt:
<!-- Needed for getContacts, getContactById, countContacts, groups, accounts -->
<uses-permission android:name="android.permission.READ_CONTACTS" />
<!-- Needed for createContact, updateContactById, deleteContactById, groups writes -->
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
Füge auf iOS hinzu NSContactsUsageDescription zu Info.plist wenn du das Adressbuch liest oder schreibst. Für das Auswählen ist es nicht nötig.
Migrationsguide, Call für Call
Berechtigungen
// Before
import { Contacts } from '@capacitor-community/contacts';
const perm = await Contacts.requestPermissions();
if (perm.contacts !== 'granted') return;
// After
import { CapacitorContacts } from '@capgo/capacitor-contacts';
const status = await CapacitorContacts.requestPermissions({ permissions: ['readContacts'] });
if (status.readContacts !== 'granted' && status.readContacts !== 'limited') {
await CapacitorContacts.openSettings();
return;
}
Ab iOS 18 können Nutzer Zugriff auf eine Teilmenge der Kontakte gewähren. Das Plugin meldet das als limited. Behandeln Sie es als gewährt und erwarten Sie nur die freigegebenen Kontakte.
Alle Kontakte lesen
// Before: whole address book, projection object
const { contacts } = await Contacts.getContacts({
projection: { name: true, phones: true, emails: true },
});
const first = contacts[0];
console.log(first.name?.display, first.phones?.[0]?.number);
// After: fields array, paginated
const pageSize = 200;
let offset = 0;
for (;;) {
const { contacts } = await CapacitorContacts.getContacts({
fields: ['displayName', 'givenName', 'familyName', 'phoneNumbers', 'emailAddresses'],
limit: pageSize,
offset,
});
render(contacts);
if (contacts.length < pageSize) break;
offset += pageSize;
}
declare function render(list: unknown[]): void;
Nutzt countContacts() zuerst, wenn Sie einen Fortschrittsbalken anzeigen möchten.
Einen Kontakt lesen
// Before
const { contact } = await Contacts.getContact({
contactId: id,
projection: { name: true, phones: true },
});
// After
const { contact } = await CapacitorContacts.getContactById({
id,
fields: ['displayName', 'phoneNumbers'],
});
if (!contact) console.log('Not found');
Kontakt erstellen
// Before
const { contactId } = await Contacts.createContact({
contact: {
name: { given: 'Ada', family: 'Lovelace' },
phones: [{ type: PhoneType.Mobile, number: '+44 20 7946 0000' }],
emails: [{ type: EmailType.Work, address: 'ada@example.com' }],
},
});
// After
const { id } = await CapacitorContacts.createContact({
contact: {
givenName: 'Ada',
familyName: 'Lovelace',
phoneNumbers: [{ type: 'MOBILE', value: '+44 20 7946 0000' }],
emailAddresses: [{ type: 'WORK', value: 'ada@example.com' }],
},
});
displayName ist im Capgo-Plugin schreibgeschützt. Schreibe givenName und familyName, und das Gerät formatiert den Anzeigenamen.
Kontakt aktualisieren (neu)
await CapacitorContacts.updateContactById({
id,
contact: {
givenName: 'Ada',
familyName: 'King',
jobTitle: 'Analyst',
phoneNumbers: [{ type: 'MOBILE', value: '+44 20 7946 0000' }],
},
});
Die ID bleibt gleich, sodass alle gespeicherten Referenzen weiterhin funktionieren. Lies den Kontakt zuerst und sende die Felder zurück, die du behalten möchtest, um nichts versehentlich zu löschen.
Wenn der Nutzer den Kontakt selbst bearbeiten soll, öffne den System-Editor:
await CapacitorContacts.displayUpdateContactById({ id });
Kontakt löschen
// Before
await Contacts.deleteContact({ contactId: id });
// After
await CapacitorContacts.deleteContactById({ id });
Kontakt auswählen
// Before: requests the contacts permission on Android first
const { contact } = await Contacts.pickContact({
projection: { name: true, phones: true },
});
// After: one phone number, no permission on Android or iOS
import { ContactProperty } from '@capgo/capacitor-contacts';
const { contacts } = await CapacitorContacts.pickContacts({
property: ContactProperty.PhoneNumber,
});
const phone = contacts[0]?.phoneNumbers?.[0]?.value;
Wenn du den vollständigen Datensatz aus dem Picker benötigst, rufe pickContact() ohne propertyauf. Unter Android gibt das den vollständigen Kontakt nur zurück, wenn READ_CONTACTS wird erteilt.
Feldzuordnung
| Community-Payload | Capgo Contact |
|---|---|
contactId |
id |
name.display |
displayName (nur lesbar) |
name.given / middle / family |
givenName / middleName / familyName |
name.prefix / suffix |
namePrefix / nameSuffix |
organization.company |
organizationName |
organization.jobTitle |
jobTitle |
birthday { day, month, year } |
birthday { day, month, year } |
note |
note |
phones[].number |
phoneNumbers[].value |
emails[].address |
emailAddresses[].value |
urls[] (Strings) |
urlAddresses[].value |
postalAddresses[].region / postcode |
postalAddresses[].state / postalCode |
image.base64String |
photo (base64-String) |
Auch die Typwerte ändern sich: Das Capgo-Plugin verwendet Großbuchstaben-Strings wie 'MOBILE', 'HOME', 'WORK' für Telefonnummern und E-Mails.
Screens einzeln migrieren
Die beiden Plugins registrieren sich unter unterschiedlichen nativen Namen (Contacts und CapacitorContacts, sodass sie parallel installiert werden können, während du die Aufrufstellen migrierst. Ein kleiner Adapter hält den Rest deiner App unverändert:
import { CapacitorContacts } from '@capgo/capacitor-contacts';
export interface AppContact {
id: string;
name: string;
phones: string[];
}
export async function listContacts(limit = 200, offset = 0): Promise<AppContact[]> {
const { contacts } = await CapacitorContacts.getContacts({
fields: ['displayName', 'phoneNumbers'],
limit,
offset,
});
return contacts.map((c) => ({
id: c.id ?? '',
name: c.displayName ?? '',
phones: (c.phoneNumbers ?? []).map((p) => p.value),
}));
}
Sobald die letzte Aufrufstelle verschoben wurde, entferne das Community-Plugin und führe bunx cap syncaus. Prüfe das zusammengeführte Android-Manifest, um sicherzustellen, dass nur die benötigten Berechtigungen übrig bleiben.
Fehlerbehebung
getContacts gibt auf iOS eine leere Liste zurück. Der Nutzer hat eingeschränkten Zugriff gewährt und keine Kontakte freigegeben oder den Zugriff verweigert. Prüfe readContacts und biete openSettings().
Ein erstellter Kontakt wird in einem bestimmten Konto auf Android nicht angezeigt. Übergib einen account (aus getAccounts()) in dem Kontakt, den du erstellst.
Fotos machen Listen langsam. Nicht anfordern photo in Listenansichten. Lade sie mit getContactById wenn der User einen Kontakt öffnet.
Play Console-Warnungen READ_CONTACTS. Verschiebe Invite- und Share-Flows zu pickContacts({ property }) und entferne die Permission, falls sie sonst nicht gebraucht wird.
Veröffentlichen
Plugins auszutauschen ist eine native Änderung und erfordert einen Store-Build. Capgo Build kann iOS- und Android-Builds in der Cloud erstellen. Danach sind Fixes für deine Kontakt-Screens reines JavaScript und können mit Capgo Live Updatesausgeliefert werden. Das vollständige API findest du im Contacts-Plugin-Doku.