Moving Contacts into My New Droid Phone
I’ve been waiting on a phone like the Droid for years – an Internet connected miniature computer I can put in my pocket. I skipped Windows Mobile because it was lame: Poor resolution, poor open source application support, poor UI experience (poor Microsoft). I skipped Blackberry because the phones are ugly with small screens and the software is just awful. I skipped the iPhone because I’m not into platforms you can’t tinker with… app stores are fine, but, as a developer, I don’t want to be forced to use one. And Objective C should be something programmers either choose (or not) on its own merits – not due to Apple strong arming.
The G1 was almost good enough, but I heard it was slow and slow computers drive me crazy. Finally, my Droid has arrived. I’m not thrilled that Java is the recommended programming language, but at least you don’t have to program in Objective C. I’m on day 2 with my Droid and I’m really just getting started. The first challenge I ran into was moving my contacts from Thunderbird and my old Casio “Boulder” phone. With my old Casio phone, I used Verizon’s free Backup Assistant to keep my contacts backed up. This application is actually a nice touch by Verizon and they should publicize it better. After your first backup, you can login to their site and see your contacts. Last time I switched phones, I just installed Backup Assistant on my new phone and downloaded my contacts from my online backup. Unfortunately, Verizon has not yet ported Backup Assistant to the Android platform. They do, however, allow you to login to their web site and download all contacts as a CSV files. I though for sure there would be an easy way to get contacts in a CSV file onto my Droid, but that did not turn out to be the case.
My first task was to export another CSV from Thunderbird and consolidate my cell phone and email contacts. Luckily, this wasn’t too bad because I had done it last time I switched phones. I used OpenOffice’s Calc program to open both CSV file, manually consolidate them, then export the resulting consolidated contact list as a CSV file.
To get my consolidated CSV onto the Droid, first, I tried copying the CSV file onto the Droid and using the phone’s import contact function. With a USB cable, getting the CSV file onto the phone was easy enough, but the Droid import function only understands vCards, so the CSV file was useless for the Droid import function.
The Droid will automatically sync with Gmail Contacts and I knew Gamail had a CSV import function, so I tried uploading my CSV file into Gmail Contacts. I could get some of the CSV uploaded, but, after many tries, I could not get Email addresses and mobile phone numbers properly imported. These are the most important data items, so IMO, Gmail’s CSV import is almost useless.
Next I tried to use an online service to convert my CSV to vCard, then import the resulting vCard file via the Droid contact import function. This sort of worked, but contacts with multiple phone numbers had all phone numbers set to be “home” and all email addresses were set as “other” (rather than “work” or “home”). I got the bright idea to import the vCard file into Gmail contacts, but this produced the same problems as trying to import directly on the Droid.
Thinking that getting contacts into Gmail must be a common problem, I ran a bunch more Google searches looking for something that would do the conversion I needed, but I found nothing.
So, I decided to do what only a programmer can do… write a program to get my contacts from the CSV onto my Droid. Actually, I did this indirectly. I used Google’s .Net data API to upload my CSV into Gmail Contacts, then the Droid’s built-in Gmail sync function automatically puts the contacts onto my Droid. I did it this way because a) I’ve worked the Google .Net data API before and found it easy to use and b) I have a good CSV library I’ve found and used on other projects.
For those interested, I have copied the full source code below:
using System; using System.Collections.Generic; using System.IO; using System.Text; using Google.GData.Contacts; using Google.GData.Client; using Google.GData.Extensions; using Google.Contacts; using LumenWorks.Framework.IO.Csv; namespace GoogleContactsUpload { class Program { static void Main(string[] args) { string username = "user1@gmail.com"; string password = "password1"; Uri feedUri = new Uri(ContactsQuery.CreateContactsUri(username)); RequestSettings rs = new RequestSettings("teztech-GoogleContactsUpload-1", username, password); ContactsRequest cr = new ContactsRequest(rs); using (StreamReader contactsReader = new StreamReader(@"C:\Users\pj\Documents\Databases\ContactsMerged.csv")) { using (CsvReader contactsCsv = new LumenWorks.Framework.IO.Csv.CsvReader(contactsReader, true, ',', '"', '"', '\0', true)) { while (contactsCsv.ReadNextRecord()) { Contact contact = new Contact(); contact.Title = string.Format("{0} {1}", contactsCsv["First Name"], contactsCsv["Last Name"]); if (contactsCsv["Email Address"] != "") { EMail workEmail = new EMail(contactsCsv["Email Address"]); workEmail.Primary = true; workEmail.Rel = ContactsRelationships.IsWork; contact.Emails.Add(workEmail); } if (contactsCsv["Home Email"] != "") { EMail homeEMail = new EMail(contactsCsv["Home Email"]); homeEMail.Rel = ContactsRelationships.IsHome; contact.Emails.Add(homeEMail); } if (contactsCsv["Work Phone"] != "") { PhoneNumber workPhone = new PhoneNumber(contactsCsv["Work Phone"]); workPhone.Rel = ContactsRelationships.IsWork; contact.Phonenumbers.Add(workPhone); } if (contactsCsv["Home Phone"] != "") { PhoneNumber homePhone = new PhoneNumber(contactsCsv["Home Phone"]); homePhone.Rel = ContactsRelationships.IsHome; contact.Phonenumbers.Add(homePhone); } if (contactsCsv["Mobile Phone"] != "") { PhoneNumber mobilePhone = new PhoneNumber(contactsCsv["Mobile Phone"]); mobilePhone.Primary = true; mobilePhone.Rel = ContactsRelationships.IsMobile; contact.Phonenumbers.Add(mobilePhone); } if (contactsCsv["Work Fax"] != "") { PhoneNumber faxPhone = new PhoneNumber(contactsCsv["Work Fax"]); faxPhone.Rel = ContactsRelationships.IsFax; contact.Phonenumbers.Add(faxPhone); } if (contactsCsv["Home Address"] != "") { PostalAddress homeAddress = new PostalAddress(); homeAddress.Value = FormatAddress(false, contactsCsv["Home Address"], contactsCsv["Home Address 2"], contactsCsv["Home City"], contactsCsv["Home State"], contactsCsv["Home ZipCode"], contactsCsv["Home Country"]); homeAddress.Rel = ContactsRelationships.IsHome; contact.PostalAddresses.Add(homeAddress); } if (contactsCsv["Work Address"] != "") { PostalAddress workAddress = new PostalAddress(); workAddress.Value = FormatAddress(false, contactsCsv["Work Address"], contactsCsv["Work Address 2"], contactsCsv["Work City"], contactsCsv["Work State"], contactsCsv["Work ZipCode"], contactsCsv["Work Country"]); workAddress.Rel = ContactsRelationships.IsWork; contact.PostalAddresses.Add(workAddress); } if (contactsCsv["Organization"] != "") { Organization organization = new Organization(); organization.Label = contactsCsv["Organization"]; organization.Title = contactsCsv["Job Title"]; contact.Organizations.Add(organization); } StringBuilder notes = new StringBuilder(); if (contactsCsv["Web Page 1"] != "") notes.AppendFormat("Website: {0}", contactsCsv["Web Page 1"]); notes.AppendFormat("{0}{1}", notes.Length > 0 ? "\r\n" : "", contactsCsv["Notes"]); contact.Content = notes.ToString(); Contact createdContact = cr.Insert(feedUri, contact); } } } } static public string FormatAddress(bool useBR, string address1, string address2, string city, string state, string zip, string country) { StringBuilder address = new StringBuilder(); string newLine = useBR ? "<br />" : "\r\n"; if(address1 != "") address.AppendFormat("{0}{1}", address.Length > 0 ? newLine : "", address1); if(address2 != "") address.AppendFormat("{0}{1}", address.Length > 0 ? newLine : "", address2); StringBuilder cityStateZip = new StringBuilder(); cityStateZip.Append(city); if(state != "") cityStateZip.AppendFormat("{0}{1}", cityStateZip.Length > 0 ? ", " : "", state); if(zip != "") cityStateZip.AppendFormat("{0}{1}", cityStateZip.Length > 0 ? " " : "", zip); if(cityStateZip.Length > 0) address.AppendFormat("{0}{1}", address.Length > 0 ? newLine : "", cityStateZip.ToString()); if(country != "") address.AppendFormat("{0}{1}", address.Length > 0 ? newLine : "", country); return address.ToString(); } } }
I just got a Droid for Father’s Day and I thought getting my phone book which was on the backup assistant from Verizon would be easy, but as you found it is nearly impossible to get it into the Droid. I do appreciate you finding a way to do this, but I am very far from working with source code, so can you suggest something/somebody who might be able to help out this +1 tech guy. I thank you for your time and knowledge………..Mike