I have code to read contact details and to read birthdays. But how do I get a list of contacts in order of their upcoming birthday?
For a single contact identified by id, I get details and birthday like this:
Cursor c = null;
  try {
   Uri uri = ContentUris.withAppendedId(
     ContactsContract.Contacts.CONTENT_URI, id);
   c = ctx.getContentResolver().query(uri, null, null, null, null);
   if (c != null) {
    if (c.moveToFirst()) {
     DatabaseUtils.cursorRowToContentValues(c, data);
    }
   }
   c.close();
   // read birthday
   c = ctx.getContentResolver()
     .query(
       Data.CONTENT_URI,
       new String[] { Event.DATA },
       Data.CONTACT_ID + "=" + id + " AND "
         + Data.MIMETYPE + "= '"
         + Event.CONTENT_ITEM_TYPE + "' AND "
         + Event.TYPE + "=" + Event.TYPE_BIRTHDAY,
       null, Data.DISPLAY_NAME);
   if (c != null) {
    try {
     if (c.moveToFirst()) {
      this.setBirthday(c.getString(0));
     }
    } finally {
     c.close();
    }
   }
   return super.load(id);
  } catch (Exception e) {
   Log.v(TAG(), e.getMessage(), e);
   e.printStackTrace();
   return false;
  } finally {
   if (c != null)
    c.close();
  }
and the code to read all contacts is:
public Cursor getList() {
        // Get the base URI for the People table in the Contacts content
        // provider.
        Uri contacts = ContactsContract.Contacts.CONTENT_URI;
        // Make the query.
        ContentResolver cr = ctx.getContentResolver();
        // Form an array specifying which columns to return.
        String[] projection = new String[] { ContactsContract.Contacts._ID,
                ContactsContract.Contacts.DISPLAY_NAME };
        Cursor managedCursor = cr.query(contacts, projection, null, null,
                ContactsContract.Contacts.DISPLAY_NAME
                        + " COLLATE LOCALIZED ASC");
        return managedCursor;
    }