The Contacts Data API allows client applications to view and update a user's contacts. Contacts are stored in the user's Google Account; most Google services have access to the contact list.
Your client application can use the Contacts Data API to create new contacts, edit or delete existing contacts, and query for contacts that match particular criteria.
In addition to providing some background on the capabilities of the Contacts Data API, this document provides examples of how to interact with contacts using the Java client library. If you're interested in understanding more about the underlying protocol that the library uses, see the Protocol section of this developer's guide.
This document is intended for programmers who want to write Java client applications that can interact with Google's contact lists.
This document assumes that you understand the general ideas behind the Google Data APIs protocol.
For reference information about the classes and methods provided by the client library, see the Java client library API reference. For general Contacts Data API reference information, see the Protocol reference guide.
For help setting up the client library, see the Getting Started Guide.
The Java client library requires Java 1.5. After downloading the client library, you'll find the classes you need to get started in the java/lib/gdataclient-X.Y.jar file.
You may want to sign up for a Google Account for testing purposes. Contacts are associated with Google Accounts, so if you already have a Google Account, you're all set.
Note: To view your contacts without using the Contacts Data API, you can log in to Gmail and click the Contacts link.
A full working sample client, containing all the sample code shown in this document, is available in the Java client library distribution, under the directory gdata/java/sample/contacts/ContactsExample.java. Build and execution instructions are included in the same directory in the README.txt file.
The sample client performs several operations on contacts to demonstrate the use of the Contacts Data API.
To compile the examples in this document into your own code, you'll need the following import statements:
import com.google.gdata.client.*; import com.google.gdata.client.contacts.*; import com.google.gdata.data.*; import com.google.gdata.data.contacts.*; import com.google.gdata.util.*; import java.io.IOException; import java.net.URL;
All Contacts Data API feeds are private. Thus, your client needs to authenticate before accessing a contacts feed. It can authenticate using either of two approaches: ClientLogin username/password authentication or AuthSub proxy authentication.
For more information about authentication with Google Data APIs in general, see the authentication documentation.
AuthSub proxy authentication is used by web applications that need to authenticate their users to Google Accounts. The website operator and the client code don't have access to the username and password for the user; instead, the client obtains special AuthSub tokens that allow the client to act on a particular user's behalf. For more detailed information, see the AuthSub documentation.
When a user first visits your application, they have not yet been authenticated. In this case, you need to display some information and a link directing the user to a Google page to authenticate your request for access to their contacts. The Java client library provides a function to generate the Google page's URL from the AuthSubUtil class. The code below retrieves the URL of the AuthSubRequest page:
String next = "http://www.example.com/welcome.html"; String scope = "http://www.google.com/m8/feeds/"; boolean secure = false; boolean session = true; String authSubLogin = AuthSubUtil.getRequestUrl(next, scope, secure, session);
The getRequestUrl method takes the following parameters (corresponding to the query parameters used by the AuthSubRequest handler):
http://www.google.com/m8/feeds/.The above example shows a call that doesn't request a secure token (the value of secure is false). The resulting request URL might look like this:
https://www.google.com/accounts/AuthSubRequest?scope=http%3A%2F%2Fwww.google.com%2Fm8%2Ffeeds%2F&session=1&secure=0&next=http%3A%2F%2Fwww.example.com%2Fwelcome.html
The user follows the link to Google's site and authenticates to their Google Account.
After the user authenticates, the AuthSub system redirects them to the URL you specified in the next query parameter of the AuthSubRequest URL. The AuthSub system appends an authentication token to that URL, as the value of the token query parameter. For example:
http://www.example.com/welcome.html?token=yourAuthToken
This token value represents a single-use AuthSub token. In this example, since session = true was specified, this token can be exchanged for an AuthSub session token by calling the AuthSubSessionToken service with the single-use token in an Authorization header, as follows, where urlFromAuthSub is the URL that AuthSub appended the token to:
String token = AuthSubUtil.getTokenFromReply(urlFromAuthSub); String sessionToken = AuthSubUtil.exchangeForSessionToken(token, null);
That is, you pass your one-time-use token to the exchangeForSessionToken method, along with either null (if you aren't using enhanced security) or a private key (for more security), and the AuthSub interface returns a session token. For more information about registered applications and private keys, refer to the "Signing requests" section of the AuthSub documentation.
Your application can then use the session token value in subsequent interactions with contacts. The client library automatically sends the token along with requests.
Use ClientLogin authentication if your client is a standalone, single-user "installed" client (such as a desktop application). Just call the setUserCredentials method on your ContactsService object and all subsequent interactions with contacts will be authenticated:
ContactsService myService = new ContactsService("exampleCo-exampleApp-1");
myService.setUserCredentials("liz@gmail.com", "password");
For more information about ClientLogin authentication, including sample requests and responses, see the Account Authentication for Installed Applications documentation.
You can use the Java client library to publish new contact entries.
First, create a ContactEntry object to represent the contact. Then you can set the name, notes and other attributes of the contact. Finally, use the ContactsService object to insert the contact. Here's an example of how to publish a new contact:
public static ContactEntry createContact(ContactsService myService,
String name, String notes)
throws ServiceException, IOException {
// Create the entry to insert
ContactEntry contact = new ContactEntry();
contact.setTitle(new PlainTextConstruct(name));
contact.setContent(new PlainTextConstruct(notes));
Email primaryMail = new Email();
primaryMail.setAddress("liz@gmail.com");
primaryMail.setRel("http://schemas.google.com/g/2005#home");
primaryMail.setPrimary(true);
contact.addEmailAddress(primaryMail);
Email secondaryMail = new Email();
secondaryMail.setAddress("liz@example.com");
secondaryMail.setRel("http://schemas.google.com/g/2005#work");
secondaryMail.setPrimary(false);
contact.addEmailAddress(secondaryMail);
ExtendedProperty favouriteFlower = new ExtendedProperty();
favouriteFlower.setName("favourite flower");
favouriteFlower.setValue("daisy");
contact.addExtendedProperty(favouriteFlower);
ExtendedProperty sportsProperty = new ExtendedProperty();
sportsProperty.setName("sports");
XmlBlob sportKinds = new XmlBlob();
sportKinds.setBlob(new String("<dance><salsa/><ballroom dancing/><dance/>"));
spsportsPropertyorts.setXmlBlob(sportKinds);
contact.addExtendedProperty(sportsProperty);
// Ask the service to insert the new entry
URL postUrl = new URL("http://www.google.com/m8/feeds/contacts/liz@gmail.com/full");
return myService.insert(postUrl, contact);
}
The insert method takes the service's POST URL as a parameter. Then the method returns the entry as it was stored by the server. The entry returned is the same one you sent, but it also contains various elements added by the server, such as a contact ID.
If your request fails for some reason, Google may return a different status code. For information about the status codes, see the Google Data API protocol reference document.
Note: 409 error can be returned when there is a different contact with the same email address. As for now, google contacts API does not allow two different contacts to share an email address.
Note: A photo cannot be added to a contact while creating the contact.
When adding a photo, setting a proper ContentType is important.
Example of adding a photo in a jpg format:
public static void addContactPhoto(ContactEntry entry, ContactsService service, byte[] photoData)
throws ServiceException, IOException {
Link editPhotoLink = entry.getContactEditPhotoLink();
URL editUrl = new URL(editPhotoLink.getHref());
GDataRequest request = service.createRequest(GDataRequest.RequestType.UPDATE,
editUrl, new ContentType("image/jpg"));
OutputStream requestStream = request.getRequestStream();
requestStream.write(photoData);
request.execute();
}
}
To retrieve the user's contacts, call the getFeed
method with the contact feed URL:
public static void printAllContacts(ContactsService myService)
throws ServiceException, IOException {
// Request the feed
URL feedUrl = new URL("http://www.google.com/m8/feeds/contacts/liz@gmail.com/full");
ContactFeed resultFeed = myService.getFeed(feedUrl, ContactFeed.class);
// Print the results
System.out.println(resultFeed.getTitle().getPlainText());
for (int i = 0; i < resultFeed.getEntries().size(); i++) {
ContactEntry entry = resultFeed.getEntries().get(i);
System.out.println("\t" + entry.getTitle().getPlainText());
System.out.println("Email addresses:");
for (Email email : entry.getEmailAddresses()) {
System.out.print(" " + email.getAddress());
if (email.getRel() != null) {
System.out.print(" rel:" + email.getRel());
}
if (email.getLabel() != null) {
System.out.print(" label:" + email.getLabel());
}
if (email.getPrimary()) {
System.out.print(" (primary) ");
}
System.out.print("\n");
}
System.out.println("IM addresses:");
for (Im im : entry.getImAddresses()) {
System.out.print(" " + im.getAddress());
if (im.getLabel() != null) {
System.out.print(" label:" + im.getLabel());
}
if (im.getRel() != null) {
System.out.print(" rel:" + im.getRel());
}
if (im.getProtocol() != null) {
System.out.print(" protocol:" + im.getProtocol());
}
if (im.getPrimary()) {
System.out.print(" (primary) ");
}
System.out.print("\n");
}
System.out.println("Groups:");
for (GroupMembershipInfo group : entry.getGroupMembershipInfos()) {
String groupHref = group.getHref();
System.out.println(" Id: " + groupHref);
}
System.out.println("Extended Properties:");
for (ExtendedProperty property : entry.getExtendedProperties()) {
if (property.getValue() != null) {
System.out.println(" " + property.getName() + "(value) = " +
property.getValue());
} else if (property.getXmlBlob() != null) {
System.out.println(" " + property.getName() + "(xmlBlob)= " +
property.getXmlBlob().getBlob());
}
}
String editPhotoLink = contact.getContactEditPhotoLink().getHref();
System.out.println("Edit-photo Link:" + editPhotoLink);
if (contact.getContactPhotoLink() != null) {
String photoLink = contact.getContactPhotoLink().getHref();
System.out.println("Photo Link:" + photoLink);
}
}
}
Note: The feed may not contain all of the user's contacts, because there's a default limit on the number of results returned. For more information, see the setMaxResults method in Retrieving contacts using query parameters.
The Contacts Data API lets you request a set of contacts that match specified criteria, such as requesting contacts created or updated in a given date range, or published by a particular author. To do this, you create a Query object and pass it to the ContactsService.getQuery() method.
For example, to send a date-range query, use the setUpdatedMin method of the Query object. The following code snippet prints the title of each contact updated after the given start time:
public static void printDateMinQueryResults(
ContactsService myService, DateTime startTime) throws ServiceException,
IOException {
// Create query and submit a request
URL feedUrl = new URL("http://www.google.com/m8/feeds/contacts/liz@gmail.com/full");
Query myQuery = new Query(feedUrl);
myQuery.setUpdatedMin(startTime);
ContactFeed resultFeed = myService.query(myQuery, ContactFeed.class);
// Print the results
System.out.println(resultFeed.getTitle().getPlainText() +
" contacts updated on or after "
+ startTime);
for (int i = 0; i < resultFeed.getEntries().size(); i++) {
ContactEntry entry = resultFeed.getEntries().get(i);
System.out.println("\t" + entry.getTitle().getPlainText());
System.out.println("\t" + entry.getUpdated().toStringRfc822());
}
}
Notice that the Query object is constructed using the same contact feed URL used to retrieve contacts.
The Contacts Data API supports the following Query methods:
<atom:id> element and a <gd:deleted> element. (Google retains placeholders for deleted contacts for 30 days after deletion; during that time, you can request the placeholders using the showdeleted query parameter.)direction can be either "ascending" or "descending".Note: To track incremental changes to a contact list, do the following: When you send a request for a feed, keep track of the value of the feed's <updated> element. Then you can later retrieve only the contacts that have changed since the previous request by setting updated-min to that <updated> value, and setting showdeleted to true.
For more information about query parameters, see the Contacts Data API Reference Guide and the Google Data APIs Reference Guide.
Note: By default, the entries in a feed are not ordered.
Sample code downloading a photo:
public static void downloadPhoto(ContactEntry entry, ContactsService service)
throws ServiceException, IOException {
Link photoLink = entry.getContactPhotoLink();
if (photoLink != null) {
InputStream in = service.getStreamFromLink(photoLink);
ByteArrayOutputStream out = new ByteArrayOutputStream();
RandomAccessFile file = new RandomAccessFile(
"/tmp/" + entry.getSelfLink().getHref().substring(
entry.getSelfLink().getHref().lastIndexOf('/') + 1), "rw");
byte[] buffer = new byte[4096];
for (int read = 0; (read = in.read(buffer)) != -1;
out.write(buffer, 0, read));
file.write(out.toByteArray());
file.close();
}
}
To update an existing contact, first you retrieve the entry you want to update, then you modify it, and then you send it to the server using the update method. The following code snippet modifies a contact's name, assuming that you've already retrieved the contact from the server.
Note: In the underlying XML, the contact's name is stored in the <atom:title> element. Thus, the Java client library uses the setTitle method to set the contact's name.
public static ContactEntry updateContactName(
ContactsService myService, ContactEntry entryToUpdate, String newName)
throws ServiceException, IOException {
entryToUpdate.setTitle(new PlainTextConstruct(newName));
URL editUrl = new URL(entryToUpdate.getEditLink().getHref());
return myService.update(editUrl, entryToUpdate);
}
The above code returns a newly-updated ContactEntry. To update any other properties, simply set them in the ContactGroupEntry object before calling update.
Note: 409 error code can be returned if:
- You are trying to update a contact and are using an old edit URI - the contact was updated after the edit URI was saved.
- You want to add a new email address that is used by another contact. Currently google contacts API does not allow two different contacts to share an email address.
Updating a photo is the same as adding a photo.
To delete a photo for a contact, you can execute a code snippet like this one:
public static void deleteContactPhoto(ContactEntry entry, ContactsService service)
throws ServiceException, IOException {
Link editPhotoLink = entry.getContactEditPhotoLink();
URL editUrl = new URL(editPhotoLink.getHref());
service.delete(editUrl);
}
To delete a contact, pass the contact's edit URL to the delete method on your ContactsService object, like this:
public static void deleteContact(ContactsService myService,
ContactEntry entryToDelete)
throws ServiceException, IOException {
URL deleteUrl = new URL(entryToDelete.getEditLink().getHref());
myService.delete(deleteUrl);
}
Note: To update existing contacts, see Updating contacts; don't update by deleting contacts and then re-adding them.
You can use the Java client library to publish new contact group entries.
Here's an example of how to publish a new contact group:
public static ContactGroupEntry createContactGroup(ContactsService service,
String name, String notes, ExtendedProperty additionalInfo)
throws ServiceException, IOException {
// Create the entry to insert
ContactGroupEntry group = new ContactGroupEntry();
group.setTitle(new PlainTextConstruct(name));
group.addExtendedProperty(additionalInfo);
// Ask the service to insert the new entry
URL postUrl = new URL("http://www.google.com/m8/feeds/groups/liz@gmail.com/full");
return service.insert(postUrl, group);
}
First, create a ContactGroupEntry object and set a name and other attributes for the contact group. Then use the ContactsService object to insert the contact group. The insert method takes the service's POST URL as a parameter. The method returns the entry as it was stored by the server. The entry returned is the entry you sent extended with elements added by the server, such as a contact group ID.
If your request fails for some reason, Google may return a different status code. For information about the status codes, see the Google Data API protocol reference document.
Sample code to retrieve the user's contact groups:
public static void printAllGroups(ContactsService myService)
throws ServiceException, IOException {
// Request the feed
URL feedUrl = new URL("http://www.google.com/m8/feeds/groups/liz@gmail.com/full");
ContactGroupFeed resultFeed = myService.getFeed(feedUrl, ContactGroupFeed.class);
// Print the results
System.out.println(resultFeed.getTitle().getPlainText());
for (int i = 0; i < resultFeed.getEntries().size(); i++) {
ContactGroupEntry groupEntry = resultFeed.getEntries().get(i);
System.out.println("Id: " + groupEntry.getId());
System.out.println("Group Name: " + groupEntry.getTitle().getPlainText());
System.out.println("Last Updated: " + groupEntry.getUpdated());
System.out.println("Extended Properties:");
for (ExtendedProperty property : groupEntry.getExtendedProperties()) {
if (property.getValue() != null) {
System.out.println(" " + property.getName() + "(value) = " +
property.getValue());
} else if (property.getXmlBlob() != null) {
System.out.println(" " + property.getName() + "(xmlBlob) = " +
property.getXmlBlob().getBlob());
}
}
System.out.println("Self Link: " + groupEntry.getSelfLink().getHref());
System.out.println("Edit Link: " + groupEntry.getEditLink().getHref());
}
}
The Contacts Data API supports for contact groups the same Query methods as allowed for contacts, except for the setCustomParameter("group", groupID).
Sample code for contact groups restricted with set-updated-min method:
public static void printDateMinQueryResults(
ContactsService myService, DateTime startTime) throws ServiceException,
IOException {
// Create query and submit a request
URL feedUrl = new URL("http://www.google.com/m8/feeds/groups/liz@gmail.com/full");
Query myQuery = new Query(feedUrl);
myQuery.setUpdatedMin(startTime);
ContactGroupFeed resultFeed = myService.query(myQuery, ContactGroupFeed.class);
// Print the results
System.out.println(resultFeed.getTitle().getPlainText() +
" contact groups updated on or after "
+ startTime);
for (int i = 0; i < resultFeed.getEntries().size(); i++) {
ContactGroupEntry entry = resultFeed.getEntries().get(i);
System.out.println("\t" + entry.getTitle().getPlainText());
System.out.println("\t" + entry.getUpdated().toStringRfc822());
}
}
To update an existing contact group, first you retrieve the entry you want to update, then you modify it, and then you send it to the server using the update method. The following code snippet modifies a contact group's name, assuming that you've already retrieved the group from the server.
public static ContactGroupEntry updateContactGrpupName(
ContactsService myService, ContactGroupEntry entryToUpdate, String newName)
throws ServiceException, IOException {
entryToUpdate.setTitle(new PlainTextConstruct(newName));
URL editUrl = new URL(entryToUpdate.getEditLink().getHref());
return myService.update(editUrl, entryToUpdate);
}
The above code returns a ContactGroupEntry containing the entire newly-updated post. To update any other properties, simply set them in the ContactGroupEntry object before calling update.
Note: 409 error code can be returned if you are trying to update a contact group and are using an old edit URI - the contact group was updated after the edit URI was saved.
Deleting a contact group can look like this:
public static void deleteContactGroup(ContactsService myService,
ContactGroupEntry groupToDelete)
throws ServiceException, IOException {
URL deleteUrl = new URL(groupToDelete.getEditLink().getHref());
myService.delete(deleteUrl);
}
Note: To update existing contact groups, see Updating contact groups; don't update by deleting contact groups and then re-adding them.