Cordova Demo - Viewing all Contacts

This post is more than 2 years old.

A quick demo of something I've wanted to see myself for a while now - a user on Stackoverflow asked if it was possible to view all the contacts on a device using PhoneGap/Cordova. It is rather trivial to do so. Simply perform a search and skip providing an actual filter. Here is an example.

document.addEventListener("deviceready", init, false);
function init() {

	navigator.contacts.find(
		[navigator.contacts.fieldType.displayName],
		gotContacts,
		errorHandler);

}

function errorHandler(e) {
	console.log("errorHandler: "+e);
}

function gotContacts(c) {
	console.log("gotContacts, number of results "+c.length);
	for(var i=0, len=c.length; i<len; i++) {
		console.dir(c[i]);
	}
}

All I've done here is run the find method of the Contacts plugin. You must provide the first argument, which specifies which fields you will search against, but you do not have to actually provide a search value. Running this code as is will return the entire contact object, but obviously you could, and should, ask for a subset of the contacts if you only care about particular values.

I tested it on my Android phone and it worked really darn fast, despite having 400+ contacts. Here is the result being viewed via GapDebug:

GapDebug

Not really rocket science, but maybe useful. If you want to copy this code into your own project, you can find it here: https://github.com/cfjedimaster/Cordova-Examples/tree/master/stealcontacts.

Ok, I was about to post this as is, but then I thought, let me add something fun. I modified the code slightly to see if a contact photo exists - and if so - append it to the DOM:

function gotContacts(c) {
	console.log("gotContacts, number of results "+c.length);
	picDiv = document.querySelector("#pictures");
	for(var i=0, len=c.length; i<len; i++) {
		console.dir(c[i]);
		if(c[i].photos && c[i].photos.length > 0) {
			picDiv.innerHTML += "<img src='"+c[i].photos[0].value+"'>";
		}
	}
}

A simple little tweak, but with a fun result: device-2014-12-23-074946

Enjoy!

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by Filipe Silva posted on 1/5/2015 at 1:28 PM

One tip that I'd like to add is that if you're getting app crashes on search, try adding the contactFindOptions.desiredFields option to retrieve only the fields you really need.

I had some trouble with a client on iOS crashing, and after quite a bit of work ended up figuring out that the OS silently kills apps using too much RAM, and that somehow his contacts had something really odd there (the app functioned just fine with over 5k contacts on other devices).

Comment 2 (In reply to #1) by Raymond Camden posted on 1/5/2015 at 2:59 PM

I did mention this, but only in regards of "return what you need", I didn't go into detail about why, so thank you, Filipe. :)

Comment 3 (In reply to #2) by Rajesh K G posted on 6/20/2015 at 11:50 AM

hi Raymond, I am quite happy to connect with you. I am seeing you on many Cordova mails threads. I have a similar problem that Cordova Contacts plugin is not able get me quick results, though i just give very limited 1 or 2 desiredFields and Fetch fields (say 1 or 2). I have close to 700 contacts in my 2 Year old Android phone. It takes close to 4 mins for fetching. Sometimes, it doesn't even return succ / fail. Would there be any other quick Contact Cordova plugin ? i see many posts talk about this slowness.

Comment 4 (In reply to #3) by Raymond Camden posted on 6/21/2015 at 2:19 AM

I'm not aware of any offhand - but did you search plugins.cordova.io?

Comment 5 (In reply to #4) by Rajesh K G posted on 6/21/2015 at 9:21 AM

Thanks Raymond. Searched a lot but all point back to same plugin. If we just want fetch even just two fields do we need that much json transformations?

Comment 6 (In reply to #5) by Raymond Camden posted on 6/21/2015 at 12:10 PM

I can't really comment on *how* the plugin works as I've never looked at the source code for it. Best I can suggest is filing a bug, or perhaps trying to fix it yourself and submitting a PR.

Comment 7 (In reply to #6) by Rajesh K G posted on 6/22/2015 at 7:07 AM

Found this plugin. Trying to do this today evening. https://github.com/dbaq/cor...

Comment 8 by Pete Olsen posted on 1/6/2016 at 3:02 PM

I keep getting an error that navigator.contacts is undefined. What have I missed? Thanks.

Comment 9 (In reply to #8) by Raymond Camden posted on 1/6/2016 at 3:09 PM

Your code is running before deviceready has fired, or you forgot to include the contacts plugin.

Comment 10 (In reply to #9) by Pete Olsen posted on 1/6/2016 at 3:11 PM

It is after the device ready. How do I include the plugin? THanks.

Comment 11 (In reply to #10) by Raymond Camden posted on 1/6/2016 at 3:21 PM

This is covered in the docs (and my book ;) but the basic concept is:

cordova plugin add X

where X is the name of the plugin. In your case, cordova-plugin-contacts

Comment 12 (In reply to #11) by Pete Olsen posted on 1/6/2016 at 3:23 PM

Ahh, well I installed the plugin as shown. It's just not being picked up I guess. Which directory do you run the command in? The www dir or the home directory? Thanks.

Comment 13 (In reply to #12) by Raymond Camden posted on 1/6/2016 at 3:26 PM

If you make a new project, add the plugin, then just copy the www assets from the Git repo.

Comment 14 by Amila Jayasinghe posted on 3/4/2016 at 4:27 AM

It shows [Object Object] when I run it on iOS

Comment 15 (In reply to #14) by Raymond Camden posted on 3/4/2016 at 12:46 PM

Add JSON.stringify() around the output.

Comment 16 by Dinesh Raja posted on 3/13/2016 at 4:59 AM

Hi Raymond, thanks for this post, is there anyway to sort the contacts based on name ??

Comment 17 (In reply to #16) by Raymond Camden posted on 3/14/2016 at 1:39 PM

Via the plugin, no, but once you have the array back, just use sort() on it and pass an inline function that sorts on the name value.

Comment 18 by Shash posted on 3/16/2016 at 4:48 AM

Hai Raymond sorry..this is related to google oauth...after adding google plus plugin while building i.c ionic build android I'am getting

ERROR building one of the platforms: Error code 1 for command: /home/shashank/ionic-starter-oauth-master/platforms/android/gradlew with args: cdvBuildDebug,-b,/home/shashank/ionic-starter-oauth-master/platforms/android/build.gradle,-Dorg.gradle.daemon=true,-Pandroid.useDeprecatedNdk=true

You may not have the required environment or OS to build this project

Error: Error code 1 for command: /home/shashank/ionic-starter-oauth-master/platforms/android/gradlew with args: cdvBuildDebug,-b,/home/shashank/ionic-starter-oauth-master/platforms/android/build.gradle,-Dorg.gradle.daemon=true,-Pandroid.useDeprecatedNdk=true

Comment 19 (In reply to #18) by Raymond Camden posted on 3/16/2016 at 1:25 PM

Your comment has nothing at all to do with this blog post. For general questions, you can use my contact form, or post to Stack Overflow.

Comment 20 by Subin Babu posted on 4/26/2016 at 10:59 AM

hi ,can i add contact automatic with a name and no in variable on button click?

Comment 21 (In reply to #20) by Raymond Camden posted on 4/26/2016 at 1:01 PM

Please see the docs. It demonstrates how to add contacts.

Comment 22 by Amila Jayasinghe posted on 5/6/2016 at 5:02 AM

Hi.. How can I get contact list using ionic ng-Cordova? It looks these codes are not work for ionic ng-Cordova. Can you please help me?
Thanks

Comment 23 (In reply to #22) by Raymond Camden posted on 5/6/2016 at 12:57 PM

The code I used was for the Contacts plugin and will work just fine in any Cordova app, including any Ionic app. Using Ionic does not mean you *have* to use ngCordova. If you want to use the Contact support in ngCordova, I'd suggest checking their docs. If it still doesn't work for you, tell us what you tried and how it failed, although it will be a bit OT for this blog post.

Comment 24 (In reply to #23) by Amila Jayasinghe posted on 5/7/2016 at 7:09 AM

This is noted. In fact, I was trying to run my app in ionic view. I'll try to run it on real devise and get back to you with the status. Thanks

Comment 25 by Love Panchal posted on 9/27/2016 at 6:17 AM

how to remove the contact the code is not working ?????

Comment 26 (In reply to #25) by Raymond Camden posted on 9/27/2016 at 3:24 PM

Well my demo doesn't talk about removing contacts, right? So if you are talking about how to use the Contact API in general, then your question is off topic and should be posted to Stack Overflow instead.

Comment 27 by TOJO PAUL posted on 12/8/2016 at 7:53 AM

How can i get the Contact Events like Anniversary?

Comment 28 by Karan Rao posted on 12/8/2016 at 11:39 AM

Is there a way to find just one contact???

Comment 29 (In reply to #27) by Raymond Camden posted on 12/8/2016 at 12:20 PM

Look in the Contact object. It should return everything that exists.

Comment 30 (In reply to #28) by Raymond Camden posted on 12/8/2016 at 12:20 PM

Use the find API - see the plugin docs for more information.

Comment 31 (In reply to #29) by TOJO PAUL posted on 12/8/2016 at 3:17 PM

I have added a contact with Anniversary and Birth date .it returns only the Birth date. i have tried iphone 4s and 5s. Thanks

Comment 32 (In reply to #31) by Raymond Camden posted on 12/8/2016 at 4:31 PM

Remember you have to *ask* for the fields you want returned. Please see the Contact docs.

Comment 33 (In reply to #32) by TOJO PAUL posted on 12/9/2016 at 4:49 AM

var options = new ContactFindOptions();
options.filter = "";
options.multiple = true;
var fields = ["*"];
navigator.contacts.find(fields, onSuccessContact, onErrorContact, options);

I have used above Code and tried '*' to get all contact fields.

Thanks

Comment 34 (In reply to #33) by Raymond Camden posted on 12/9/2016 at 2:25 PM

If that didn't work - then I'd file a bug report.

Comment 35 (In reply to #34) by TOJO PAUL posted on 12/12/2016 at 5:13 AM

Thanks Raymond, I have reported this issue in jira

Comment 36 by Joshua Rowe posted on 1/3/2017 at 6:50 PM

Is there a way to show multiple photos per contact? Seems you can save multiple photos but the returned array shows the same URL for each photo in the array.

Comment 37 (In reply to #36) by Raymond Camden posted on 1/3/2017 at 6:53 PM

Yes - if the data is there, you would just do it. Iterate over the array I mean and display it as you see fit.

Comment 38 (In reply to #37) by Joshua Rowe posted on 1/3/2017 at 6:59 PM

I guess what I mean is the data is there, but the URL is the same across all photos. For example, if contact ID 1000 has three photos, the URL for each of the three photos is the same instead of each having a unique URL: content://com.android.contacts/contacts/1000/photo

Comment 39 (In reply to #38) by Raymond Camden posted on 1/3/2017 at 7:00 PM

That smells like a bug in the plugin then. Can you try reporting that?

Comment 40 (In reply to #39) by Joshua Rowe posted on 2/3/2017 at 4:02 PM

Have an issue reported on this with some details. Looks like it may be a device limitation per the Android documentation and some findings in the code, but want to make sure: https://issues.apache.org/j...

Comment 41 by Puja posted on 3/16/2017 at 8:54 AM

Hello Raymond,

I have an requirement where I have to show the iphone/ipad contacts which is only having email address in shorting order by dispaly name.
With the below code i am getting all the conatacts which is not having the email id also.COuld you please help me on this

function onDeviceReady() {
var options = new ContactFindOptions();
options.filter = "";
options.multiple = true;
var fields = [name,navigator.contacts.fieldType.emails];
navigator.contacts.find(fields, onSuccessGetContacts, onErrorGetContacts);
}

function onSuccessGetContacts(contacts) {

//create the Model
var oModelContacts = new sap.ui.model.json.JSONModel();
oModelContacts.setSizeLimit(2500);

//define the structure of the Model / Entity
var oData = {
"Contacts": []
};

//set the entity to the model
oModelContacts.setData(oData);

//set the model to core
sap.ui.getCore().setModel(oModelContacts);

//fill the model with the contacts of the device formatted name and first email address
var oModelData = sap.ui.getCore().getModel().getData();

for (var i = 0; i < contacts.length; i++) {

var email = "";
if(contacts[i].emails && contacts[i].emails.length > 0) {
email = contacts[i].emails[0].value;
}
oModelData.Contacts.push({
displayName: contacts[i].name.formatted,
email: email
});
}

Comment 42 (In reply to #41) by Raymond Camden posted on 3/16/2017 at 2:35 PM

I honestly can't understand what you are saying. It sounds like you want contacts that have email addresses. If you can't filter by that using the contacts API, then you can use the code I've shown to get *all* contacts and then filter it yourself afterwards.

Comment 43 by Jin Ping posted on 4/14/2017 at 7:27 AM

Thank you, very useful!

Comment 44 by valentine ofili posted on 8/16/2017 at 9:04 AM

Thank you for this , however it is not working.

When i try running your example with the snippet below

onDeviceReady: function() {
this.receivedEvent('deviceready');
console.log("Device ready event ");

//get contacts on user's device
navigator.contacts.find(
[navigator.contacts.fieldType.displayName],
gotContacts,
errorHandler);

function gotContacts(c) {
console.log("gotContacts, number of results "+c.length);

for(var i=0, len=c.length; i<len; i++)="" {="" console.dir(c[i]);="" }="" }="" function="" errorhandler(e)="" {="" console.log("error="" "="" +="" e);="" }="" i="" get="" an="" error="" in="" my="" logcat="" whic="" i="" view="" when="" emulating="" the="" app="" on="" a="" real="" device="" with="" contacts.="" failed="" to="" get="" birthday="" for="" contact="" from="" cursor="" java.lang.illegalargumentexception="" at="" java.sql.date.valueof(date.java:219)="" at="" org.apache.cordova.contacts.contactaccessorsdk5.getbirthday(contactaccessorsdk5.java:1977)="" at="" org.apache.cordova.contacts.contactaccessorsdk5.populatecontactarray(contactaccessorsdk5.java:466)="" at="" org.apache.cordova.contacts...(contactaccessorsdk5.java:295)="" at="" org.apache.cordova.contacts.contactmanager$3.run(contactmanager.java:209)="" at="" java.util.concurrent.threadpoolexecutor.runworker(threadpoolexecutor.java:1112)="" at="" java.util.concurrent.threadpoolexecutor$worker.run(threadpoolexecutor.java:587)="" at="" java.lang.thread.run(thread.java:818)="" im="" using="" cordova="" contacts="" plugin="" cordova-plugin-contacts="" 2.3.1="" "contacts"="">

Comment 45 (In reply to #44) by Raymond Camden posted on 8/16/2017 at 11:18 AM

Your error message was messed up in disqus. Can you post it to a Gist and then share the URL here?

Comment 46 by Steve Nosse posted on 9/8/2017 at 6:13 PM

Very helpful!!! Tried this and it worked for me

Comment 47 by Petronel Malutan posted on 11/27/2017 at 8:00 AM

Do you know if we can get the fovourites contacts with this ?

Comment 48 (In reply to #47) by Raymond Camden posted on 11/27/2017 at 3:30 PM

Check the docs for the plugin - you may be able to search by a category.

Comment 49 (In reply to #48) by Raymond Camden posted on 11/27/2017 at 3:35 PM

Looking at the docs, I see a categories field. It may be in there.

Comment 50 by newguy posted on 1/9/2019 at 10:19 AM

Nice article.