Cordova - Contacts
Cordova - Managing Device Contacts
Section titled “Cordova - Managing Device Contacts”The cordova-plugin-contacts plugin provides access to the device’s contact database. You can use it to find, create, and delete contacts. Note: This plugin requires user permission to access contacts.
Step 1 - Install Contacts Plugin
Section titled “Step 1 - Install Contacts Plugin”Install the plugin using the Cordova CLI:
cordova plugin add cordova-plugin-contactsAfter adding the plugin, rebuild your project for the platform(s) you are targeting (e.g., cordova build android).
Step 2 - Prepare the UI
Section titled “Step 2 - Prepare the UI”In www/index.html, add buttons for contact operations and a div to display results:
<body> <h1>Contacts Demo</h1> <button id="createContactBtn">ADD CONTACT</button> <button id="findContactBtn">FIND CONTACTS</button> <button id="deleteContactBtn">DELETE 'Test User'</button> <div id="contactResults"></div>
<script src="cordova.js"></script> <script src="js/index.js"></script></body>Step 3 - Implement JavaScript Logic
Section titled “Step 3 - Implement JavaScript Logic”In www/js/index.js, within onDeviceReady, set up event listeners. All navigator.contacts API calls must be made after deviceready.
document.addEventListener('deviceready', onDeviceReady, false);
function onDeviceReady() { console.log('Device is ready. Contacts API available.'); document.getElementById('createContactBtn').addEventListener('click', createContact); document.getElementById('findContactBtn').addEventListener('click', findContacts); document.getElementById('deleteContactBtn').addEventListener('click', deleteTestContact);
// It's good practice to check for permissions explicitly if needed, // though the plugin often handles the initial prompt. // For advanced scenarios, refer to permission plugins.}
const displayResults = (message) => { document.getElementById('contactResults').innerHTML = `<p>${message}</p>`; console.log(message);};
const displayError = (error) => { let errorMessage = 'Operation failed.'; if (error && error.code) { switch (error.code) { case ContactError.UNKNOWN_ERROR: errorMessage = 'Unknown error.'; break; case ContactError.INVALID_ARGUMENT_ERROR: errorMessage = 'Invalid argument.'; break; case ContactError.TIMEOUT_ERROR: errorMessage = 'Timeout error.'; break; case ContactError.PENDING_OPERATION_ERROR: errorMessage = 'Pending operation error.'; break; case ContactError.IO_ERROR: errorMessage = 'I/O error.'; break; case ContactError.NOT_SUPPORTED_ERROR: errorMessage = 'Not supported error.'; break; case ContactError.PERMISSION_DENIED_ERROR: errorMessage = 'Permission denied.'; break; default: errorMessage = `Error code: ${error.code}`; } } document.getElementById('contactResults').innerHTML = `<p style="color: red;">Error: ${errorMessage}</p>`; console.error('Contacts Error:', errorMessage, error);};
// 3A - Create Contactasync function createContact() { try { const contact = navigator.contacts.create(); contact.displayName = "Test User"; contact.nickname = "Tester"; // Same as displayName by default
const name = new ContactName(); name.givenName = "Test"; name.familyName = "User"; contact.name = name;
const phoneNumbers = []; phoneNumbers[0] = new ContactField('mobile', '123-456-7890', true); // preferred number contact.phoneNumbers = phoneNumbers;
await new Promise((resolve, reject) => { contact.save(() => resolve(), (err) => reject(err)); }); displayResults("Contact 'Test User' saved successfully!"); } catch (err) { displayError(err); }}
// 3B - Find Contactsasync function findContacts() { try { const options = new ContactFindOptions(); options.filter = ""; // Empty filter to find all, or specify a search term e.g., "Test" options.multiple = true; // options.desiredFields = [navigator.contacts.fieldType.id, navigator.contacts.fieldType.displayName, navigator.contacts.fieldType.name]; // Specify fields if needed const fields = ["displayName", "name", "phoneNumbers"]; // Fields to search within and retrieve
const contactsFound = await new Promise((resolve, reject) => { navigator.contacts.find(fields, (contacts) => resolve(contacts), (err) => reject(err), options); });
if (contactsFound.length === 0) { displayResults("No contacts found."); return; }
let html = '<h3>Found Contacts:</h3><ul>'; contactsFound.forEach(contact => { html += `<li>${contact.displayName || (contact.name ? contact.name.formatted : 'N/A')}`; if (contact.phoneNumbers && contact.phoneNumbers.length > 0) { html += ` (${contact.phoneNumbers[0].value})`; } html += `</li>`; }); html += '</ul>'; document.getElementById('contactResults').innerHTML = html; console.log('Found contacts:', contactsFound);
} catch (err) { displayError(err); }}
// 3C - Delete a Specific Contactasync function deleteTestContact() { try { const options = new ContactFindOptions(); options.filter = "Test User"; // Name of the contact to delete options.multiple = false; // We expect to find one or rely on the first match const fields = ["displayName"];
const contactsFound = await new Promise((resolve, reject) => { navigator.contacts.find(fields, (contacts) => resolve(contacts), (err) => reject(err), options); });
if (!contactsFound || contactsFound.length === 0) { displayResults("Contact 'Test User' not found to delete."); return; }
const contactToDelete = contactsFound[0]; await new Promise((resolve, reject) => { contactToDelete.remove(() => resolve(), (err) => reject(err)); }); displayResults(`Contact '${contactToDelete.displayName}' deleted successfully.`);
} catch (err) { displayError(err); }}Important Considerations
Section titled “Important Considerations”- Permissions: Accessing contacts is a sensitive operation. The plugin will typically trigger a permission request dialog from the OS. Your app should handle cases where permission is denied. The
ContactError.PERMISSION_DENIED_ERRORcode can indicate this. Consider using a dedicated permissions plugin for more granular control over permission requests and status checking. - Asynchronous Operations: All contact operations (save, find, remove) are asynchronous. The examples above use
async/awaitwith Promises for cleaner code. The original plugin API uses success and error callbacks. - Error Handling: Always provide error callback functions or use
try/catchwith Promises to handle potential issues, such as permission denial, I/O errors, or invalid arguments. ContactFindOptions: Usefilterto search for specific contacts. An empty string""typically attempts to fetch all contacts (which can be slow if many contacts exist).multiple: trueallows returning multiple matches.- Data Structure: Contacts can have complex data (multiple phone numbers, emails, addresses). Familiarize yourself with
ContactName,ContactField,ContactAddress, etc. objects. - Platform Differences: While Cordova aims for cross-platform consistency, there might be subtle differences in how contacts are handled or what data is available on different operating systems.
Practical Applications
Section titled “Practical Applications”Managing contacts is useful in:
- Social networking apps for finding friends.
- Communication apps for initiating calls or messages.
- CRM or business apps for managing client information.
- Apps that allow users to select contacts for sharing or other interactions.
For more details, consult the Cordova Contacts Plugin documentation.