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.
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.
NSContactsUsageDescription
key to the App_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>
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.
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