This nativescript-contacts-lite plugin provides pretty fast (but hey it's all relative) read-only access to the iOS and Android contact directory. By limiting the scope of the result set through the desiredFields
, it is possible to obtain a JSON object containing the relevant data of the contact directory within a couple of hundred milliseconds.
This repository contains a demo application in the demo-angular
folder that uses this plugin to display a contact picker. The demo app can be a good starting point for your app and may be used for narrowing down issues whilst debugging. Just clone this repo and run tns run <platform>
in the demo-angular
folder.
Run tns plugin add nativescript-contacts-lite
To use the contacts module you must first require()
it.
var Contacts = require("nativescript-contacts-lite");
Both methods retrieve contacts and share the same interface. The difference is that the former runs in the main thread and the latter within a web worker.
Argument 1: desiredFields An array containing the desired fields to fetch from phone's storage backend. Possible values are:
[
'address',
'display_name',
'email',
'name_details',
'nickname',
'note',
'organization',
'phone',
'photo',
'thumbnail',
'website'
]
Argument 2: searchTerm (optional)
A string with a search term to limit the result set to only contacts whose display_name
contain the term. Defaults to fetching all relevant contacts if an empty search term is provided or none at all.
Argument 3: debug (optional) Boolean (true/false) determining whether to pass debug messages to the console. Defaults to false.
Example using getContacts
let desiredFields = ['display_name','phone'];
let searchTerm = 'Jon';
console.log('Loading contacts...');
let timer = new Date().getTime();
Contacts.getContacts(desiredFields,searchTerm).then((result) => {
console.log(`Loading contacts completed in ${(new Date().getTime() - timer)} ms.`);
console.log(`Found ${result.length} contacts.`);
console.dir(result);
}, (e) => { console.dir(e); });
Example using getContactsWorker
let desiredFields = ['display_name','phone','thumbnail','email','organization'];
console.log('Loading contacts...');
let timer = new Date().getTime();
Contacts.getContactsWorker(desiredFields).then((result) => {
console.log(`Loading contacts completed in ${(new Date().getTime() - timer)} ms.`);
console.log(`Found ${result.length} contacts.`);
console.dir(result);
}, (e) => { console.dir(e); });
Get contact details for a specific contact.
Argument 1: contactId The identifier of the contact you wish to obtain details of (obtained through the getContacts(Worker) methods).
Argument 2: desiredFields
An array containing the desired fields to fetch from phone's storage backend. See getContacts
method for possible values.
Argument 3: debug (optional) Boolean (true/false) determining whether to pass debug messages to the console. Defaults to false.
Example
let contact_id = contact.contact_id // get id from result of getContacts method
let desiredFields = [
'address',
'display_name',
'email',
'name_details',
'nickname',
'note',
'organization',
'phone',
'photo',
'thumbnail',
'website'
]
Contacts.getContactById(contact_id,desiredFields).then((result) => {
console.dir(result);
}, (e) => { console.dir(e); });
The plugin provides both methods that run in either the main/UI thread or within a web worker. Although offloading the processing to a separate thread adds web worker initialization time, it guarantees that the main UI thread will continue to work smoothly.
If you are implementing an autocomplete where on each key you are querying a smaller subset of the contacts, you will probably want to go with the non-worker variant to avoid web worker initialization time while the user is waiting. On the other hand, if you are reading the entire contact directory while initializing your app, you probably want this to happen in the background to avoid the UI getting stuck while processing. In the latter case you probably would want to use the web worker variant.
Another way to speed up performance is possible in certain cases like when you are building a contact picker. In this case it is probably good enough to first provide a narrow array of desiredFields like ['display_name','thumbnail']
to getContacts
to display the list. Only when the user selects a specific contact, you can obtain all details for a specific contact by supplying a wider array of desiredFields to getContactById
. This example has been implemented in the demo app located in this repository.
On a relatively old Samsung Galaxy S4 a list of ~600 contacts is returned somewhere between ~300ms up to ~2s depending on the desired fields and whether you run in the main thread or in a web worker.
Tests on an iPhone 7 plus with ~600 contacts returned in ~105ms when running getContacts(['display_name', 'phone'])
(so non worker). This could use some more real iOS device data in different modes (e.g. more fields & web worker mode) if anyone has some.
This plugin is compatible with webpack bundling through the nativescript-dev-webpack plugin as of NativeScript 3.2. However, if you are using the web worker functions, we need to ensure that the web worker resources are included in the package. For this purpose, you should add the nativescript-worker-loader to your project: npm i -D nativescript-worker-loader
.
The plugin returns photo
& thumbnail
images as a base64 encoded string ready to be used as the source attribute of an image, e.g. <Image *ngIf="item.thumbnail" [src]="item.thumbnail"></Image>
This plugin uses the nativescript-permissions plugin by Nathanael Anderson for obtaining read-only permissions to the phone's contacts on Android 6 and above.
Since the plugin uses the Contact framework it is supported only on iOS 9.0 and above!
As of iOS 10 it has become mandatory to add the NSContactsUsageDescription
key to your application's Info.plist
(see Apple's developer documentation).
Therefore you should add something like this to your ~/app/App_Resources/iOS/Info.plist
:
<key>NSContactsUsageDescription</key>
<string>This application requires access to your contacts to function properly.</string>
The iOS part of this plugin is based on code from the nativescript-contacts plugin.