omer bar-or · The Plan Askew · My First Deliverable: Address Book Names

My First Deliverable: Address Book Names

Written: June 11th, 2007, 1:08 (UTC) By: omer 3 comments

Another development from over the past few days is my first application that interacts with the Mac OS X Address Book. It is available here. Basically, all it does is tell you how many people are in your Mac OS X address book and lists their names. It currently can only handle ASCII values (just so that it can be easily printed to the terminal), and it's an entirely terminal-based application, but it is a first step for interacting with the Address Book. And, perhaps more importantly, it is a first step using the Address Book Carbon API (Carbon is what OOo uses) rather than the Cocoa API. Meaning: it should be possible to integrate the Address Book using Carbon and C (both supported by OOo) rather than Cocoa and Objective-C (which are not). Enjoy!

File: abnames.tar

Comments

  1. API clarification

    Written: June 12th, 2007, 19:27 (UTC) By: Florian Heckl [e-mail: florian@florian-heckl.de] permalink

    I should clarify here that "The Address Book framework consists of two APIs: one for C, the other for Objective-C." (see http://developer.apple.com/documentation/UserExperience/Conceptual/AddressBook/index.html), rather than Carbon / Cocoa API. You are of course right in that Carbon uses plain C while Cocoa uses Objective-C.

  2. corrected version of abnames

    Written: June 12th, 2007, 20:14 (UTC) By: Florian Heckl [e-mail: florian@florian-heckl.de] permalink

    Well, your code crashed with my address book. So I played around a little and can offer you the following:

    /******

    *

    * Test Carbon Program -- print all first and last names from Address

    * Book (in ASCII).

    *

    ******/

    /* Include */

    #include <stdio.h>

    #include <string.h>

    #include <Carbon/Carbon.h>

    #include <AddressBook/ABAddressBookC.h>

    int main(int argc, char *argv[])

    {

    int i, numPeople;

    CFStringRef firstNameCFString, lastNameCFString;

    char *lastNameString, *firstNameString;

    /* Get the address book and everyone inside of it */

    ABAddressBookRef AB = ABGetSharedAddressBook();

    CFArrayRef all = ABCopyArrayOfAllPeople(AB);

    /* This is used to turn a CFArrayRef into a C array */

    numPeople = (int) CFArrayGetCount(all);

    //CFRange range = {0,numPeople};

    //const ABPersonRef **everyone;

    //CFArrayGetValues(all,range,(const void **) everyone);

    /* Print the number of people... (why not?) */

    printf("Number of people in address book: %dn", numPeople);

    /* Go through the array... */

    for(i = 0; i < numPeople; i++)

    {

    /* First, get the names out of this ABPerson */

    ABRecordRef person = (ABPersonRef) CFArrayGetValueAtIndex(all, i);

    firstNameCFString = (CFStringRef) ABRecordCopyValue((ABRecordRef) person, kABFirstNameProperty);

    lastNameCFString = (CFStringRef) ABRecordCopyValue((ABRecordRef) person, kABLastNameProperty);

    /* The names are extracted as "CFStringRef"s, so this gives us a

    * char * version, for printing. Notice that we have to give an

    * encoding type. I used ASCII for the quick test. I also gave

    * a lot more space than I needed to with malloc. I don't know why

    * yet, but giving the length itself in malloc and then in

    * CFStringGetCString makes firstNameString and lastNameString both

    * blank. So, until I figure out why (if I ever need to), I gave

    * them some padding.

    */

    static char* fallback = "<null>";

    int fbLength = strlen(fallback);

    int firstNameLength = fbLength;

    bool firstNameFallback = true;

    int lastNameLength = fbLength;

    bool lastNameFallback = true;

    if (firstNameCFString != NULL) {

    firstNameLength = (int) CFStringGetLength(firstNameCFString);

    firstNameFallback = false;

    }

    if (lastNameCFString != NULL) {

    lastNameLength = (int) CFStringGetLength(lastNameCFString);

    lastNameFallback = false;

    }

    //fallback again

    if (firstNameLength == 0) {

    firstNameLength = fbLength;

    firstNameFallback = true;

    }

    if (lastNameLength == 0) {

    lastNameLength = fbLength;

    lastNameFallback = true;

    }

    firstNameString = malloc(sizeof(char)*(firstNameLength+1));

    lastNameString = malloc(sizeof(char)*(lastNameLength+1));

    if (firstNameFallback == true) {

    strcpy(firstNameString, fallback);

    } else {

    CFStringGetCString(firstNameCFString, firstNameString, 10*CFStringGetLength(firstNameCFString), kCFStringEncodingASCII);

    }

    if (lastNameFallback == true) {

    strcpy(lastNameString, fallback);

    } else {

    CFStringGetCString(lastNameCFString, lastNameString, 10*CFStringGetLength(lastNameCFString), kCFStringEncodingASCII);

    }

    /* Print them out... */

    printf("%s %sn",firstNameString, lastNameString);

    /* Free our variables */

    if (firstNameCFString != NULL) {

    CFRelease(firstNameCFString);

    }

    if (lastNameCFString != NULL) {

    CFRelease(lastNameCFString);

    }

    free(firstNameString);

    free(lastNameString);

    } // end of for loop

    CFRelease(all);

    return 0;

    } // end of main function

  3. Thanks

    Written: June 14th, 2007, 20:07 (UTC) By: omer [www] [e-mail: omer [dot] baror (at) gmail [dot] com] permalink

    Thanks for the fixes, Florian! I hadn't tested with null/empty names. The error came up for me later when attempting to print properties other than first and last names. I'm posting a new version of the program now, one that prints all properties for all people in the address book. Let me know what you think (and if it crashes too)!

Leave a comment

Color scheme: