Se ti serve un'alternativa a community contacts per Capacitor, il sostituto drop-in più completo è @capgo/capacitor-contacts. Copre tutto ciò che @capacitor-community/contacts permette di leggere, creare, eliminare e selezionare i contatti, e aggiunge l'aggiornamento di un contatto senza cambiarne l'ID, la paginazione, i gruppi, gli account, le schermate native dei contatti e la selezione senza permessi su Android, un aspetto importante per la policy sui contatti di Google Play del 2027. Questa guida confronta entrambi e mappa ogni chiamata per permetterti di migrare in un pomeriggio.
Perché cercare un'alternativa
@capacitor-community/contacts è mantenuto e ha una release Capacitor 8. È una buona scelta per flussi semplici di lettura e creazione. Di solito i team passano ad altro per questi motivi:
- Nessun metodo di aggiornamento. Puoi creare ed eliminare contatti, ma non modificarne uno. Eliminare e ricreare assegna al contatto un nuovo ID, il che invalida ogni riferimento salvato e può farti perdere dati che il plugin non legge.
- Nessuna paginazione.
getContactsrestituisce l'intera rubrica in una sola chiamata. Su un dispositivo con 5.000 contatti e foto, è lento e pesante per la memoria. - La selezione richiede il permesso su Android. Android
pickContactrichiede il gruppo di permessi contatti prima di aprire il picker, quindi legge il contatto dalla rubrica. Sotto la policy Contacts Permissions di Google Play, le app per Android 17 possono solo mantenereREAD_CONTACTSper le funzionalità core. - Niente gruppi, account o schermate native. Impossibile elencare i gruppi, scegliere l'account in cui salvare un nuovo contatto o aprire il form di sistema “nuovo contatto”.
Confronto funzionalità
| Funzionalità | @capacitor-community/contacts 8.0 | @capgo/capacitor-contacts 8.1 |
|---|---|---|
| Leggi un contatto / tutti i contatti | getContact, getContacts |
getContactById, getContacts |
| Selezione dei campi | projection oggetto |
fields array |
| Paginazione | No | limit, offset |
| Conta i contatti | No | countContacts |
| Crea | createContact |
createContact |
| Aggiorna in place | No | updateContactById |
| Elimina | deleteContact |
deleteContactById |
| Seleziona un contatto | pickContact |
pickContact |
| Seleziona più contatti | No | pickContacts({ multiple: true }) |
| Seleziona un telefono/email/indirizzo senza autorizzazione | No | pickContacts({ property }) |
| Gruppi | No | getGroups, getGroupById, createGroup, deleteGroupById |
| Account | No | getAccounts |
| Native create / view / edit screens | No | displayCreateContact, displayContactById, displayUpdateContactById |
| Stati separati per i permessi di lettura e scrittura | No (alias singolo) | readContacts, writeContacts |
| Stato di accesso limitato su iOS | limited |
limited |
| Apri impostazioni | No | openSettings |
Installa
bun add @capgo/capacitor-contacts
bunx cap sync
Il plugin non aggiunge autorizzazioni al manifest Android. Aggiungi solo quelle che usi:
<!-- 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" />
Su iOS, aggiungi NSContactsUsageDescription a Info.plist se leggi o scrivi nella rubrica. La selezione non lo richiede.
Guida alla migrazione, chiamata per chiamata
Permessi
// 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;
}
Su iOS 18 e versioni successive, gli utenti possono concedere l'accesso a un sottoinsieme di contatti. Il plugin lo segnala come limited. Trattalo come concesso e aspettati solo i contatti condivisi.
Leggi tutti i contatti
// 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;
Usa countContacts() prima, se vuoi mostrare una barra di avanzamento.
Leggi un contatto
// 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');
Crea un contatto
// 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 è in sola lettura nel plugin Capgo. Scrivi givenName e familyName, e il dispositivo formatta il nome visualizzato.
Aggiorna un contatto (nuovo)
await CapacitorContacts.updateContactById({
id,
contact: {
givenName: 'Ada',
familyName: 'King',
jobTitle: 'Analyst',
phoneNumbers: [{ type: 'MOBILE', value: '+44 20 7946 0000' }],
},
});
L'ID rimane invariato, quindi ogni riferimento salvato continuerà a funzionare. Leggi prima il contatto e rimanda i campi che vuoi mantenere, per evitare di cancellare dati accidentalmente.
Se preferisci lasciar modificare all'utente, apri l'editor di sistema:
await CapacitorContacts.displayUpdateContactById({ id });
Elimina un contatto
// Before
await Contacts.deleteContact({ contactId: id });
// After
await CapacitorContacts.deleteContactById({ id });
Seleziona un contatto
// 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;
Se ti serve l'intero record dal picker, chiama pickContact() senza property. Su Android, questo restituisce il contatto completo solo quando READ_CONTACTS viene concessa.
Mappatura dei campi
| Payload della community | Capgo Contact |
|---|---|
contactId |
id |
name.display |
displayName (sola lettura) |
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[] (stringhe) |
urlAddresses[].value |
postalAddresses[].region / postcode |
postalAddresses[].state / postalCode |
image.base64String |
photo (stringa base64) |
Cambiano anche i valori: il plugin Capgo usa stringhe in maiuscolo come 'MOBILE', 'HOME', 'WORK' per telefoni ed email.
Migra una schermata alla volta
I due plugin si registrano con nomi nativi diversi (Contacts e CapacitorContacts), così possono essere installati insieme mentre sposti i punti di chiamata. Un piccolo adapter mantiene il resto dell'app invariato:
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),
}));
}
Quando l'ultimo punto di chiamata è stato spostato, rimuovi il plugin della community ed esegui bunx cap sync, e controlla il manifest Android unificato per confermare che rimangano solo i permessi necessari.
Risoluzione problemi
getContacts restituisce una lista vuota su iOS. L'utente ha concesso un accesso limitato senza condividere contatti, o ha negato l'accesso. Controlla readContacts e offri openSettings().
Il contatto creato non appare in un account specifico su Android. Passa un account (da getAccounts()) nel contatto che crei.
Le foto rallentano le liste. Non richiedere photo nelle viste elenco. Caricalo con getContactById quando l'utente apre un contatto.
Play Console segnala READ_CONTACTS. Sposta i flussi di invito e condivisione su pickContacts({ property }) e rimuovi il permesso se non serve ad altro.
Pubblica
Sostituire i plugin è una modifica nativa, quindi serve una build per lo store. Build Capgo può generare build iOS e Android nel cloud. Successivamente, le correzioni alle schermate dei contatti sono in JavaScript e possono essere rilasciate con Live updates di Capgo. Il API completo è nel documentazione plugin contacts.