Thursday, 5 March 2009

Automatic synchronisation of OS X Addressbook without enabling Yahoo!

Update: Snow Leopard (10.6) has this built-in so there's no need for these instructions unless you're running Leopard (10.5) or lower. The following command will ensure this runs periodically:
$ /System/Library/PrivateFrameworks/GoogleContactSync.framework/Versions/A/Resources/gconsync --sync com.google.ContactSync --periodic

I am using Google Sync Services exclusively to synchronise between two MacBook Pros and an iPhone.

The one caveat is that to enable Addressbook synchronisation you have to enable, say, Yahoo! synchronising before the iSync client will allow synchronisations to occur.

Oh, and it's a manual process to launch iSync client.

This is an ugly hack to an otherwise elegant solution.  I don't like it.

So I went trawling the Internet to see if I could solve it.

I found an extremely informative post that outlines a lot of the work required.  Then, a sprinkle of launchd to make it all work.

Here's how it's done:

  1. Add a new "google" device in your devices list:
    $ defaults write ~/Library/Preferences/com.apple.iPod Devices -dict-add google '{ "Device Class" = iPod; "Family ID" = 10001; }'
  2. Launch Address Book and open the Preference pane. The Google contact sync option should appear.
  3. Register the sync client. Open a terminal and type the following:
    $ /System/Library/PrivateFrameworks/GoogleContactSync.framework/Versions/Current/Resources/gconsync --register 1
  4. Create the file, ~/Library/Preferences/com.google.GoogleContactSync.plist:
    {user = "username@gmail.com";}
  5. Add a password item to your keychain with the following values:
    Keychain Item Name:GoogleContactSyncService
    Account Name: username@gmail.com
    Password: password
  6. Create a Launch Agent. I have set the interval time to 300 seconds (5 mins). Obviously, it can be changed to something different. eg: ~/Library/LaunchAgents/com.example.gsync.plist:
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
      <dict>
        <key>Label</key>
        <string>com.example.gsync</string>
        <key>ProgramArguments</key>
        <array>
          <string>/System/Library/PrivateFrameworks/GoogleContactSync.framework/Versions/A/Resources/gconsync</string>
          <string>--sync</string>
          <string>com.google.ContactSync</string>
          <string>--report</string>
          <string>1</string>
          <string>--entitynames</string>
          <string>"com.apple.contacts.Contact,com.apple.contacts.Email Address,com.apple.contacts.IM,com.apple.contacts.Phone Number,com.apple.contacts.Street Address"</string>
        </array>
        <key>StandardErrorPath</key>
        <string>/tmp/gsync.error</string>
        <key>StandardOutPath</key>
        <string>/tmp/gsync.log</string>
        <key>LowPriorityIO</key>
        <true/>
        <key>Nice</key>
        <integer>1</integer>
        <key>StartInterval</key>
        <integer>300</integer>
      </dict>
    </plist>
  7. Add the agent:
    $ launchctl load ~/Library/LaunchAgents/com.example.gsync.plist
  8. Reboot. (Yes, it's required. The program, when launched from launchd, won't find the password until you've rebooted. I'm sure there's a way to do it without, but I don't know what that is.)
  9. You can kick off a sync run manually by running:
    $ launchctl start com.example.gsync
    ... or you can wait the interval period for the next run.