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.

7 comments:

  1. Very nicely done. I haven't tested after a reboot but manually running:/System/Library/PrivateFrameworks/GoogleContactSync.framework/Versions/A/Resources/gconsync --sync com.google.ContactSync --report 1 --entitynames "com.apple.contacts.Contact,com.apple.contacts.Email Address,com.apple.contacts.IM,com.apple.contacts.Phone Number,com.apple.contacts.Street Address"worked beautifully. Thanks for figuring this out.

    ReplyDelete
  2. This works beautifully!!! Great job. One caveat though. . .In step 7, you have to say . It won't work without the full path.

    ReplyDelete
  3. Thanks, steadfast_i_&_i... ammended. ;)

    ReplyDelete
  4. Cool (and overdue) for 10.6 to do this automatically. I note it now also syncs pictures properly too.I did an upgrade to 10.6 and notice my old launch agent is still running. It duplicates the built-in functionality, right? Should be safe to delete it and the keychain entry?

    ReplyDelete
  5. Yep, you can go ahead and remove all the things in this post. ie: launch agent, keychain entry, etc.

    ReplyDelete
  6. Would it be possible to adapt this to two gmail accounts?

    ReplyDelete
  7. @peterI'm not sure what you mean exactly but I'll try to answer the question.Maybe.You might be able to use the com.google.GoogleContactSync service to sync to account A and use the built-in stuff for account B. This would mean that account A, account B and the stuff in your addressbook would all by synchronised to each other.I hope this answered your question and good luck!

    ReplyDelete