A plugin that allows you to access Contacts directory on iOS and Android. You can pick a contact, update it, delete it, or add a new one.
- @nativescript/contacts
- Contents
- Installation
- Use @nativescript/contacts
- Get a contact
- Create a new contact
- Update a contact
- Delete a contact
- Check if a contact is unified/linked (iOS Specific)
- Get contacts by name
- Get all the contacts
- Get a contact by id
- Get a group or groups of contacts
- Create a new contacts group
- Delete a group of contacts
- Add a contact to a group
- Remove a contact from a group
- Get all the contacts of a group
- Contact class
- PhoneNumber/EmailAddress structure
- Url structure
- PostalAddress structure
- Known Labels (for Urls, Addresses and Phones)
- Group object structure
- GetFetchResult object structure
- iOS contact object
- Credits
- License
Run the following command to install the plugin:
npm install @nativescript/contacts
For the app to access the user's Contacts app, the user must grant it the permission to do. Before requesting for permissions, ensure that the following requirements are met.
- To clarify why your app needs the permission to access the user's contacts, add the
NSContactsUsageDescription
key to theApp_Resources/iOS/Info.plist
file, and your clarification as its value.
<key>NSContactsUsageDescription</key>
<string>Kindly provide permission to access contacts on your device.</string>
- For iOS 13+, add the com.apple.developer.contacts.notes entitlement to the
App_Resources/iOS/app.entitlements
file. If the file does not exist, you should create it.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.developer.contacts.notes</key>
<true/>
</dict>
</plist>
For API level 23+
, inform Android about which permissions your app needs from the user in order to access contacts by listing the following permissions in the AndroidManifest.xml
:
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.GLOBAL_SEARCH" />
Once you've indicated the permissions your app needs from a user, you can request the permissions from the user by calling the request()
method from the @nativescript-community/perms
plugin.
import { Contact } from '@nativescript/contacts';
import { request } from '@nativescript-community/perms';
const contact = new Contact();
// build a new contact...
requestPermissions({
"contacts": {},
"android.permission.GET_ACCOUNTS": {},
"android.permission.READ_CONTACTS": {},
"android.permission.WRITE_CONTACTS": {},
"android.permission.GLOBAL_SEARCH": {},
}).then(() => {
contact.save();
})
To get a selected contact, call the getContact()
method of the Contacts
class.
import { Contact } from '@nativescript/contacts';
Contacts.getContact().then(function (args) {
/// Returns args:
/// args.data: Generic cross platform JSON object
/// args.reponse: "selected" or "cancelled" depending on wheter the user selected a contact.
if (args.response === 'selected') {
const contact = args.data; //See data structure below
console.log(contact.name.given + ' ' + contact.name.family);
contact.phoneNumbers.forEach(function (phone) {
console.log(phone.value);
});
//lets say you want to get the addresses
contact.postalAddresses.forEach(function (address) {
console.log(address.location.street);
});
}
});
To create a new contact, first instantiate the Contact
class, set the various data of the contact and then to save the contact, call the save()
method on the instance.
import { Contact, KnownLabel } from '@nativescript/contacts';
import { ImageSource } from '@nativescript/core';
const newContact = new Contact();
newContact.name.given = 'John';
newContact.name.family = 'Doe';
newContact.phoneNumbers.push({
label: KnownLabel.HOME,
value: '123457890',
}); // See below for known labels
newContact.phoneNumbers.push({ label: 'My Custom Label', value: '11235813' });
newContact.photo = ImageSource.fromFileOrResource('~/photo.png');
newContact.save();
To update an existing contact, get it with the getContact()
method, edit it and then call the save()
method to update it.
import { Application, ImageSource } from '@nativescript/core';
import { Contacts } from '@nativescript/contacts';
Contacts.getContact().then(function (args) {
if (args.response === 'selected') {
const contact = args.data;
contact.name.given = 'Jane';
contact.name.family = 'Doe';
ImageSource.fromUrl('http://www.google.com/images/errors/logo_sm_2.png').then(function (src) {
contact.photo = src;
contact.save();
});
}
});
To delete a contact, get it with the getContact()
method and then call the delete()
method on it.
import { Contacts } from '@nativescript/contacts';
Contacts.getContact().then(function (args) {
/// args.data: Generic cross platform JSON object
/// args.reponse: "selected" or "cancelled" depending on wheter the user selected a contact.
if (args.response === 'selected') {
const contact = args.data; //See data structure below
contact.delete();
}
});
To check if a contact is unified, call the isUnified()
on the contact.
import { Contacts } from '@nativescript/contacts';
Contacts.getContact().then(function (args) {
/// args.data: Generic cross platform JSON object
/// args.reponse: "selected" or "cancelled" depending on whether the user selected a contact.
if (args.response === 'selected') {
const contact = args.data; //See data structure below
console.log(contact.isUnified() ? 'Contact IS unified' : 'Contact is NOT unified');
}
});
To find all the contacts matching a certain name, use the getContactsByName()
method. Returns an array of contact data.
import { Contacts } from '@nativescript/contacts';
/*
contactFields contains the fields to retrieve from native backend to reduce processing time
const contactFields = ['name','organization','nickname','notes','photo','urls','phoneNumbers','emailAddresses','postalAddresses']
*/
const contactFields = ['name', 'phoneNumbers'];
Contacts.getContactsByName('Hicks', contactFields).then(
function (args) {
console.log('getContactsByName Complete');
/// Returns args:
/// args.data: Generic cross platform JSON object, null if no contacts were found.
/// args.reponse: "fetch"
},
function (err) {
console.log('Error: ' + err);
}
);
To read all the contacts, use the getAllContacts()
method. It returns a a promise with an array of Contact
instances.
import { Contacts } from '@nativescript/contacts';
/*
Optional: contactFields contains the fields to retrieve from native backend to reduce processing time
const contactFields = ['name','organization','nickname','notes','photo','urls','phoneNumbers','emailAddresses','postalAddresses']
If not supplied, all available contactFields will be returned.
*/
const contactFields = ['name', 'phoneNumbers'];
Contacts.getAllContacts(contactFields).then(
function (args) {
console.log('getAllContacts Complete');
/// Returns args:
/// args.data: Generic cross platform JSON object, null if no contacts were found.
/// args.reponse: "fetch"
},
function (err) {
console.log('Error: ' + err);
}
);
To find a contact with ta specific identifier, use the getContactById()
method. The method returns an iOS-specific
GetFetchResult object.
import { Contacts } from '@nativescript/contacts';
const contactId = '[Contact Identifier]'; // Assumes this is a valid contact identifier (Contact.id)
Contacts.getContactById(contactId).then(
function (args) {
console.log('getContactById Complete');
/// Returns args:
/// args.data: Generic cross platform JSON object, null if no contacts were found.
/// args.reponse: "fetch"
},
function (err) {
console.log('Error: ' + err);
}
);
To get a group or groups of contacts, use the getGroups()
method. To get a group of contacts with a specific name, call the method passing it the name of the group.
import { Contacts } from '@nativescript/contacts';
Contacts
.getGroups('Test Group') //[name] optional. If defined will look for group with the specified name, otherwise will return all groups.
.then(
function (args) {
console.log('getGroups Complete');
/// Returns args:
/// args.data: Generic cross platform JSON object, null if no groups were found.
/// args.reponse: "fetch"
if (args.data === null) {
console.log('No Groups Found!');
} else {
console.log('Group(s) Found!');
}
},
function (err) {
console.log('Error: ' + err);
}
);
To create a new contacts group, create an instance of the Group
class, set group's name and call the save()
method on the instance to save it.
import { Group } from '@nativescript/contacts/models';
const groupModel = new Group();
groupModel.name = 'Test Group';
//Save Argument (boolean)
//iOS: [false=> Use Local Container, true=> Use Default Container]
//Android: will always be true, setting this value will not affect android.
groupModel.save(false);
To delete a contacts group, call the getGroups()
method to first get the group of interest. Then call the delete()
method on that group to delete it.
import { Contacts } from '@nativescript/contacts';
Contacts.getGroups('Test Group').then(
function (args) {
console.log('getGroups Complete');
console.log(JSON.stringify(args));
/// Returns args:
/// args.data: Generic cross platform JSON object, null if no groups were found.
/// args.reponse: "fetch"
if (args.data !== null) {
console.log('Group(s) Found!');
args.data[0].delete(); //Delete the first found group
}
},
function (err) {
console.log('Error: ' + err);
}
);
To add a contact to a group, get the references to the contact and the group of interest. Next, call the addMember()
method on the group passing it the contact reference to add.
import { Contacts } from '@nativescript/contacts';
Contacts.getContact().then(function (args) {
/// args.reponse: "selected" or "cancelled" depending on whether the user selected a contact.
if (args.response === 'selected') {
const contact = args.data; //See data structure below
Contacts.getGroups('Test Group').then(
function (a) {
if (a.data !== null) {
const group = a.data[0];
group.addMember(contact);
}
},
function (err) {
console.log('Error: ' + err);
}
);
}
});
Call the removeMember()
on Group
class instance passing it the contact to remove.
import { Contacts } from '@nativescript/contacts';
Contacts
.getGroups('Test Group')
.then(
function (args) {
if (args.data !== null) {
const group = args.data[0];
Contacts.getContactsInGroup(group).then(
function (a) {
/// args.reponse: "fetch"
console.log('getContactsInGroup complete');
if (a.data !== null) {
a.data.forEach(function (c, idx) {
group.removeMember(c);
});
}
},
function (err) {
console.log('Error: ' + err);
}
);
}
},
function (err) {
console.log('Error: ' + err);
}
);
To get all of a group's contacts, use the Contacts.getContactsInGroup()
method passing it the group instance.
import { Contacts } from '@nativescript/contacts';
Contacts
.getGroups('Test Group') //[name] optional. If defined will look for group with the specified name, otherwise will return all groups.
.then(
function (args) {
if (args.data !== null) {
const group = args.data[0];
Contacts.getContactsInGroup(group).then(
function (a) {
console.log('getContactsInGroup complete');
/// Returns args:
/// args.data: Generic cross platform JSON object, null if no groups were found.
/// args.reponse: "fetch"
},
function (err) {
console.log('Error: ' + err);
}
);
}
},
function (err) {
console.log('Error: ' + err);
}
);
The Contact class has following structure
{
id : "",
name : {
given: "",
middle: "",
family: "",
prefix: "",
suffix: "",
displayname: "",
phonetic : {
given: "",
middle: "",
family: ""
}
},
nickname : "",
organization : {
name: "",
jobTitle: "",
department: "",
// Android Specific properties
symbol: "",
phonetic: "",
location: "",
type: ""
},
notes : "",
photo: null, // {N} ImageSource instance
phoneNumbers : [],
emailAddresses : [],
postalAddresses : [],
urls : []
}
{
id: "",
label: "",
value: ""
}
{
label: "",
value: ""
}
{
id: "",
label: "",
location: {
street: "",
city: "",
state: "",
postalCode: "",
country: "",
countryCode: ""
}
}
The plugin exposes the following labels via the KnownLabel
object to be used for the contact data.
- HOME iOS - phone, email, postal, url Android - phone, email, postal, url
- WORK iOS - phone, email, postal, url Android - phone, email, postal, url
- OTHER iOS - phone, email, postal, url Android - phone, email, postal, url
- FAX_HOME iOS - phone Android - phone
- FAX_WORK iOS - phone Android - phone
- PAGER iOS - phone Android - phone
- MAIN iOS - phone Android - phone
- HOMEPAGE iOS - url Android - url
- CALLBACK Android - phone
- CAR Android - phone
- COMPANY_MAIN Android - phone
- ISDN Android - phone
- OTHER_FAX Android - phone
- RADIO Android - phone
- TELEX Android - phone
- TTY_TDD Android - phone
- WORK_MOBILE Android - phone
- WORK_PAGER Android - phone
- ASSISTANT Android - phone
- MMS Android - phone
- FTP Android - url
- PROFILE Android - url
- BLOG Android - url
Those are the system labels but you can also use any custom label you want.
{
id: string,
name: string,
addMember: (constact: Contact) => void
removeMember: (constact: Contact) => void
}
The object returned by the getContactById()
method of the Contacts
class.
{
data: Contact[];
response: string;
}
See Apple docs on properties available: https://developer.apple.com/library/mac/documentation/Contacts/Reference/CNContact_Class/index.html#//apple_ref/occ/cl/CNContact
NOTE: The plugin uses the Contact framework and it is supported only on iOS 9.0 and above!
All credits to the original author Ryan Lebel for creating nativescript-contacts.
Apache License Version 2.0