Windows 8 apps for the PhoneGap developer-Contacts
This is part 4 in my series on Windows 8 apps for the PhoneGap developer.
It’s time to make contact with a user’s contacts! Since a user’s device is very personal to them, it often has their list of contacts. And it’s very common to build functionality into phone apps for interacting with a user’s contacts. PhoneGap certainly lets you do that!
The PhoneGap api provides a way for your app to get a single contact by searching for it, or get a list of contacts. The general pattern is to retrieve the contacts and display them in a UI so the user can pick one or more. Be warned, however – don’t try this if your phone has a lot of contacts, it will likely crash the app due to memory constraints. Below is the typical example you’ll see on how to get a list of contacts from the user’s phone. Note that it’s an asynchronous operation and as such has callback specified – one for success and one for failure - as well as some parameters to filter the returned results (which can be used to get around the memory limitations I mentioned above).
function getContacts() {
obj = new ContactFindOptions();
obj.filter = ""; //Brooks";
obj.multiple = true;
navigator.contacts.find(["displayName", "name", "phoneNumbers", "emails", "urls", "note"],
function(contacts)
{
console.log("received contacts :: " + contacts.length);
console.log("contacts[0] = " + contacts[0]);
var s = "";
if (contacts.length == 0)
{
s = "No contacts found";
}
else
{
s = "Number of contacts: "+contacts.length+"<br/><table width='100%'><tr><th>Name</th><td>Phone</td><td>Email</td></tr>";
for (var i=0; i < contacts.length; i++)
{
try
{
var contact = JSON.parse(contacts[i]);
}
catch(e)
{
console.log(e.message + " " + contacts[i]);
continue;
}
s = s + "<tr><td>" + contact.displayName + "</td><td>";
if (contact.phoneNumbers && contact.phoneNumbers.length > 0)
{
s = s + contact.phoneNumbers[0];
}
s = s + "</td><td>"
if (contact.emails && contact.emails.length > 0)
{
s = s + contact.emails[0];
}
s = s + "</td></tr>";
}
s = s + "</table>";
}
document.getElementById('contacts_results').innerHTML = s;
},
function(e)
{
document.getElementById('contacts_results').innerHTML = "Error: "+e.code;
},
obj);
};
Windows 8 employs a different mechanism for selecting contacts. You write code that lets your app invoke what’s known as the contact picker . This displays an interactive selection box that allows the user to select one or more contacts (your choice) to be returned to the app.
Here is code that invokes the Contact picker and processes the returned results.
function pickContact() {
// Verify that we are unsnapped or can unsnap to open the picker
var viewState = Windows.UI.ViewManagement.ApplicationView.value;
if (viewState === Windows.UI.ViewManagement.ApplicationViewState.snapped &&
!Windows.UI.ViewManagement.ApplicationView.tryUnsnap()) {
// Fail silently if we can't unsnap
return;
};
// Create the picker
var picker = new Windows.ApplicationModel.Contacts.ContactPicker();
picker.commitButtonText = "Select";
// Open the picker for the user to select a contact
picker.pickSingleContactAsync().done(function (contact) {
if (contact !== null) {
// Create UI to display the contact information for the selected contact
var contactElement = document.createElement("div");
contactElement.className = "contact";
// Display the name
contactElement.appendChild(createTextElement("h3", contact.name));
// Add the different types of contact data
appendFields("Emails:", contact.emails, contactElement);
appendFields("Phone Numbers:", contact.phoneNumbers, contactElement);
appendFields("Addresses:", contact.locations, contactElement);
// Add the contact element to the page
document.getElementById("output").appendChild(contactElement);
} else {
// The picker was dismissed without selecting a contact
}
});
}
In this code, we make sure the Windows 8 JavaScript app is not in a snapped state, which is the view where the app takes up a narrow column on the screen. Picker dialog boxes won’t display properly if their host is in a snapped view. Fill or full screen view is acceptable though. The user will probably be picking a contact from their People app. Keep in mind that contacts in the People app come from a variety of sources that the user has set up on their machine – Windows Live, Facebook, Outlook, LinkedIn, etc. So not all of them have all the contact data that you might be looking for in your code. But the nice thing about the Contacts system is they will all have the same fields, identified in this documentation.
After the user chooses a contact and clicks the Submit button (the title is controlled by the commitButtonText property of the contactPicker), the contact data is returned to the app, which we then parse and display on the screen. There’s a helper method in this example called appendFields that formats things nicely for us.
function appendFields(title, fields, container) {
// Creates UI for a list of contact fields of the same type, e.g. emails or phones
fields.forEach(function (field) {
if (field.value) {
// Append the title once we have a non-empty contact field
if (title) {
container.appendChild(createTextElement("h4", title));
title = "";
}
// Display the category next to the field value
switch (field.category) {
case Windows.ApplicationModel.Contacts.ContactFieldCategory.home:
container.appendChild(createTextElement("div", field.value + " (home)"));
break;
case Windows.ApplicationModel.Contacts.ContactFieldCategory.work:
container.appendChild(createTextElement("div", field.value + " (work)"));
break;
case Windows.ApplicationModel.Contacts.ContactFieldCategory.mobile:
container.appendChild(createTextElement("div", field.value + " (mobile)"));
break;
case Windows.ApplicationModel.Contacts.ContactFieldCategory.other:
container.appendChild(createTextElement("div", field.value + " (other)"));
break;
case Windows.ApplicationModel.Contacts.ContactFieldCategory.none:
default:
container.appendChild(createTextElement("div", field.value));
break;
}
}
});
}
Now that you know the different technique for accessing contacts from a Windows 8 JavaScript app, you’ll simply need to rewrite the contact selecting portion of your PhoneGap app. Fortunately, if you planned it well, your contact picker is a separate screen, invoked via a button or link on the screen that needs the contacts. So instead of showing that screen, simply put in calls to the Contact Picker API.
A side effect of the design of the Windows 8 Contact picker is that you can’t programmatically add contacts to the People app. Now, you might be saying “Hey I have a lot of contacts my app needs to manage. How can I get those contacts added to the user’s contact list so they can work with them?”
Well, an interesting thing about Windows 8 is that when the user goes to pick things like contacts (or files or pictures for that matter), they have the option to select different applications as the source of contacts. This means if your application manages or retrieves information that provides “contact” like data (your company’s personnel database, some online list like the user’s Pinterest friends, or perhaps collaborators in a github project) you can have your application be a source of contacts for any other application on the user’s machine from which they could pick contacts. That means if they’re in the mail app and want to email someone from a contact list you application provides, when they go to pick a contact in their email app, your app’s “contact picker page” that you have defined in your manifest file.
The quickstart for managing contacts has the full sample, but the main things you do is create a contact picker page that other apps (or even your app) will use, then register your app as a contact extension. Here’s what the custom Contact Picker screen from that sample app provides. Keep in mind that now, any other app that wants to pick contacts can use this sample app as its source.
Certainly you’d pretty it up a bit, but being able to show this type of cool selection box and return one or more contacts is pretty powerful.
In the above screenshot, the blue bars at the top and bottom are system provided. The user can switch between contact providers by clicking at the top where it now says ContactPicker JS sample. The Select and Cancel buttons at the bottom live in the collection area. The way this code is written, as the user clicks the checkbox next to each name, it is added to the collection of contacts to be returned, and displayed in the collection area.
In the project’s manifest file (below), you can see that we’ve declared our app a Contact Picker itself, and when it’s invoked in that way, the start page will be the contactPicker.html page.
That’s it! Integrating contacts with a Windows 8 app is slightly different from how you do it in a PhoneGap app, but it’s still programmable with JavaScript and designable with HTML so it’s pretty easy to adopt it into your overall application.