Wednesday, September 28, 2016
The Gmail Public Labels API
The Gmail Public Labels API
[This post is by Nadav Aharony, a product manager on the Android team — Tim Bray]
Were rolling out new developer features for the Gmail Android app: It now includes a public ContentProvider that you can use to retrieve label data. You can use this to access up-to-date unread counts for specific accounts inboxes and labels.
To use the API, the Gmail app needs to be at version 2.3.6 or higher on Froyo or Gingerbread; 4.0.5 or higher on Honeycomb and ICS. Before using it, be sure you first check the Gmail app version; weve provided a handy GmailContract.canReadLabels(Context)
method to help with this. Your app will need the com.google.android.gm.permission.READ_CONTENT_PROVIDER
permission.
Finding the Gmail accounts set up on the device
The Labels API needs a valid Gmail account to build a query for per-label information. Assuming the GET_ACCOUNTS permission, the AccountManager can be used to fetch this information:
// Get the account list, and pick the first one
final String ACCOUNT_TYPE_GOOGLE = "com.google";
final String[] FEATURES_MAIL = {
"service_mail"
};
AccountManager.get(this).getAccountsByTypeAndFeatures(ACCOUNT_TYPE_GOOGLE, FEATURES_MAIL,
new AccountManagerCallback() {
@Override
public void run(AccountManagerFuture future) {
Account[] accounts = null;
try {
accounts = future.getResult();
if (accounts != null && accounts.length > 0) {
String selectedAccount = accounts[0].name;
queryLabels(selectedAccount);
}
} catch (OperationCanceledException oce) {
// TODO: handle exception
} catch (IOException ioe) {
// TODO: handle exception
} catch (AuthenticatorException ae) {
// TODO: handle exception
}
}
}, null /* handler */);
Getting and accessing existing labels
Once youve got the email account, you can get a ContentProvider URI to query against. Weve provided a simple support class called GmailContract.java for constructing the URI and defining the columns and relevant constants.
You can access any label, predefined or user-defined. The predefined labels include (you have to use symbolic constants rather than these strings, see below):
Priority Inbox
Starred
Chats
Sent
Drafts
All mail
Spam
Trash
To obtain a Cursor with information for all labels in an account, your app can either query this URI directly or use a CursorLoader. Heres an example:
Cursor c =
getContentResolver().query(GmailContract.Labels.getLabelsUri(selectedAccount),
null, null, null, null);
You can query and watch for changes on a single label by storing the URI value in the GmailContract.Labels.URI
column from the cursor data.
The NAME
value for pre-defined labels can vary by locale, so dont use GmailContract.Labels.NAME
. Instead, identify pre-defined labels like Inbox, Sent or Drafts using the String value in the GmailContract.Labels.CANONICAL_NAME
column. Heres an example:
// loop through the cursor and find the Inbox
if (c != null) {
final String inboxCanonicalName = GmailContract.Labels.LabelCanonicalName.CANONICAL_NAME_INBOX;
final int canonicalNameIndex = c.getColumnIndexOrThrow(GmailContract.Labels.CANONICAL_NAME);
while (c.moveToNext()) {
if (inboxCanonicalName.equals(c.getString(canonicalNameIndex))) {
// this row corresponds to the Inbox
}
}
}
If you choose to use a CursorLoader, it will keep the label counts up to date as they change over time.
Sample App
You can find a sample app that makes use of the new API here. The app provides a basic readout of label and message-count information.
People care about their incoming mail; were looking forward to seeing what you do with access to this information. Were also open to suggestions as to how to improve and extend this new API.
Available link for download