Saltar al contenido

Getting Started with Contacts

Este contenido aún no está disponible en tu idioma.

This guide will walk you through integrating the Capacitor Contacts plugin into your application.

Installation

Install the plugin using npm:

Terminal window
npm install @capgo/capacitor-contacts
npx cap sync

iOS Configuration

Add the following to your Info.plist:

<key>NSContactsUsageDescription</key>
<string>This app needs access to contacts to let you select recipients</string>

Android Configuration

Add the following permissions to your AndroidManifest.xml:

<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />

Basic Usage

Import the Plugin

import { Contacts } from '@capgo/capacitor-contacts';

Request Permissions

const requestPermissions = async () => {
const permission = await Contacts.requestPermissions();
console.log('Permission status:', permission.contacts);
};

Get All Contacts

const getAllContacts = async () => {
const result = await Contacts.getContacts({
projection: {
name: true,
phones: true,
emails: true,
image: true
}
});
console.log('Contacts:', result.contacts);
};

Search Contacts

const searchContacts = async (query: string) => {
const result = await Contacts.getContacts({
projection: {
name: true,
phones: true,
emails: true
},
query: query
});
console.log('Search results:', result.contacts);
};

Create Contact

const createContact = async () => {
const newContact = {
name: {
given: 'John',
family: 'Doe'
},
phones: [{
type: 'mobile',
number: '+1234567890'
}],
emails: [{
type: 'work',
address: 'john.doe@example.com'
}]
};
const result = await Contacts.createContact(newContact);
console.log('Contact created:', result);
};

Update Contact

const updateContact = async (contactId: string) => {
const updates = {
contactId: contactId,
name: {
given: 'Jane',
family: 'Doe'
}
};
await Contacts.updateContact(updates);
console.log('Contact updated');
};

Delete Contact

const deleteContact = async (contactId: string) => {
await Contacts.deleteContact({ contactId });
console.log('Contact deleted');
};

Complete Example

Here’s a complete example with a contact service:

import { Contacts } from '@capgo/capacitor-contacts';
interface Contact {
contactId: string;
name: {
display?: string;
given?: string;
family?: string;
};
phones?: Array<{ type: string; number: string }>;
emails?: Array<{ type: string; address: string }>;
image?: { base64String: string };
}
class ContactsService {
async checkPermissions(): Promise<boolean> {
const permission = await Contacts.checkPermissions();
if (permission.contacts === 'granted') {
return true;
}
const requested = await Contacts.requestPermissions();
return requested.contacts === 'granted';
}
async getAllContacts(): Promise<Contact[]> {
const hasPermission = await this.checkPermissions();
if (!hasPermission) {
throw new Error('Contacts permission denied');
}
const result = await Contacts.getContacts({
projection: {
name: true,
phones: true,
emails: true,
image: true
}
});
return result.contacts;
}
async searchContacts(query: string): Promise<Contact[]> {
if (!query || query.length < 2) {
return [];
}
const result = await Contacts.getContacts({
projection: {
name: true,
phones: true,
emails: true
},
query: query
});
return result.contacts;
}
async getContactById(contactId: string): Promise<Contact | null> {
const result = await Contacts.getContacts({
projection: {
name: true,
phones: true,
emails: true,
image: true,
organization: true,
birthday: true,
note: true,
urls: true,
postalAddresses: true
},
contactId: contactId
});
return result.contacts.length > 0 ? result.contacts[0] : null;
}
async createContact(contact: Partial<Contact>): Promise<string> {
const hasPermission = await this.checkPermissions();
if (!hasPermission) {
throw new Error('Contacts permission denied');
}
const result = await Contacts.createContact(contact);
return result.contactId;
}
async updateContact(contactId: string, updates: Partial<Contact>): Promise<void> {
await Contacts.updateContact({
contactId,
...updates
});
}
async deleteContact(contactId: string): Promise<void> {
await Contacts.deleteContact({ contactId });
}
formatPhoneNumber(phone: string): string {
// Remove non-numeric characters
const cleaned = phone.replace(/\D/g, '');
// Format as (XXX) XXX-XXXX
if (cleaned.length === 10) {
return `(${cleaned.slice(0, 3)}) ${cleaned.slice(3, 6)}-${cleaned.slice(6)}`;
}
return phone;
}
getContactInitials(contact: Contact): string {
const given = contact.name?.given || '';
const family = contact.name?.family || '';
if (given && family) {
return `${given[0]}${family[0]}`.toUpperCase();
}
const display = contact.name?.display || '';
const parts = display.split(' ');
if (parts.length >= 2) {
return `${parts[0][0]}${parts[1][0]}`.toUpperCase();
}
return display.slice(0, 2).toUpperCase();
}
}
// Usage
const contactsService = new ContactsService();
// Get all contacts
const contacts = await contactsService.getAllContacts();
console.log('Contacts:', contacts);
// Search contacts
const results = await contactsService.searchContacts('john');
console.log('Search results:', results);
// Create contact
const newContactId = await contactsService.createContact({
name: { given: 'Jane', family: 'Smith' },
phones: [{ type: 'mobile', number: '+1234567890' }]
});
// Update contact
await contactsService.updateContact(newContactId, {
emails: [{ type: 'work', address: 'jane@example.com' }]
});

Understanding Projection

The projection parameter controls which fields to fetch:

const result = await Contacts.getContacts({
projection: {
name: true, // Contact name
phones: true, // Phone numbers
emails: true, // Email addresses
image: true, // Contact photo
organization: true, // Company/organization
birthday: true, // Birth date
note: true, // Notes
urls: true, // Websites
postalAddresses: true // Physical addresses
}
});

Tip: Only request fields you need to improve performance.

Contact Picker UI

Many apps prefer using the native contact picker:

const pickContact = async () => {
try {
const result = await Contacts.pickContact({
projection: {
name: true,
phones: true,
emails: true
}
});
if (result.contacts.length > 0) {
const contact = result.contacts[0];
console.log('Selected contact:', contact);
}
} catch (error) {
console.error('Contact picker cancelled or failed:', error);
}
};

Best Practices

  1. Request Minimal Permissions: Only request contacts permission when needed
  2. Use Projection: Only fetch fields you actually use
  3. Handle Denials: Provide fallback when permissions denied
  4. Cache Wisely: Contacts can change, don’t cache too long
  5. Respect Privacy: Be transparent about contact usage
  6. Async Operations: All contact operations are async

Common Issues

Permission Denied

const handlePermissionDenied = async () => {
const permission = await Contacts.checkPermissions();
if (permission.contacts === 'denied') {
// Show dialog explaining why permission is needed
showPermissionDialog();
// Direct user to settings
// On iOS: Settings > [App] > Contacts
// On Android: Settings > Apps > [App] > Permissions
}
};

Large Contact Lists

const loadContactsInBatches = async () => {
// Get count first (lightweight)
const projection = { name: true }; // Minimal projection
// Implement pagination if needed
const allContacts = await Contacts.getContacts({ projection });
// Process in chunks
const chunkSize = 100;
for (let i = 0; i < allContacts.contacts.length; i += chunkSize) {
const chunk = allContacts.contacts.slice(i, i + chunkSize);
await processContactChunk(chunk);
}
};

Next Steps

  • Explore the API Reference for complete method documentation
  • Check out the example app for advanced usage
  • See the tutorial for complete implementation examples