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:

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:
Enjoy!
Archived Comments
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).
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. :)
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.
I'm not aware of any offhand - but did you search plugins.cordova.io?
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?
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.
Found this plugin. Trying to do this today evening. https://github.com/dbaq/cor...
I keep getting an error that navigator.contacts is undefined. What have I missed? Thanks.
Your code is running before deviceready has fired, or you forgot to include the contacts plugin.
It is after the device ready. How do I include the plugin? THanks.
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
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.
If you make a new project, add the plugin, then just copy the www assets from the Git repo.
It shows [Object Object] when I run it on iOS
Add JSON.stringify() around the output.
Hi Raymond, thanks for this post, is there anyway to sort the contacts based on name ??
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.
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
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.
hi ,can i add contact automatic with a name and no in variable on button click?
Please see the docs. It demonstrates how to add contacts.
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
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.
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
how to remove the contact the code is not working ?????
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.
How can i get the Contact Events like Anniversary?
Is there a way to find just one contact???
Look in the Contact object. It should return everything that exists.
Use the find API - see the plugin docs for more information.
I have added a contact with Anniversary and Birth date .it returns only the Birth date. i have tried iphone 4s and 5s. Thanks
Remember you have to *ask* for the fields you want returned. Please see the Contact docs.
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
If that didn't work - then I'd file a bug report.
Thanks Raymond, I have reported this issue in jira
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.
Yes - if the data is there, you would just do it. Iterate over the array I mean and display it as you see fit.
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
That smells like a bug in the plugin then. Can you try reporting that?
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...
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
});
}
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.
Thank you, very useful!
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"="">
Your error message was messed up in disqus. Can you post it to a Gist and then share the URL here?
Very helpful!!! Tried this and it worked for me
Do you know if we can get the fovourites contacts with this ?
Check the docs for the plugin - you may be able to search by a category.
Looking at the docs, I see a categories field. It may be in there.
Nice article.