Thursday, July 25, 2013

PhoneGap Day US 2013 Recap

Why, weren't you there? Seriously, what's stopped you? This conference is so great and so cheap that if you are anywhere near Portland, Oregon you need to go. Even if you aren't near Portland you need to convince your boss to send you to the conference.

What's the number one reason to attend PhoneGap Day? Timing, no wait the community. The community really comes out for this conference. I can't think of another conference I've attended where you can meet so many committers. If you were there you could have met all those people you see fixing bugs on JIRA and checking code into GIT.

Beyond the committers there were lots of folks who are building real applications with PhoneGap and they are there for you to talk with, network and generally pick their brains.

There were a lot of great presentations this year but if I was going to single out three they'd be Andy Trice's PhoneGap+Hardware, Michael Brooks super slick PhoneGap Command Line demo/presentation (I only wish I was that smooth) and finally Lyza Danger Gardner's deck on PhoneGap Self-Defense for Web Devs. That one was jam packed with things web devs should know before diving into PhoneGap.

I was sweating my talk a bit before heading up on stage. I was about to give a speech recognition demo on a stage in front of 250 people. There were so many things that could have gone wrong like the (network, crowd volume) and one thing did. For some reason my MBP would not mirror the displays so either I could see the presentation or the audience could. Luckily, as a former boy scout, I was prepared. I was hosting my presentation on Dropbox so I was able to slide over to Tommy-Carlos Williams laptop to do my demo without holding up the show. Thanks again Tommy!

Sacrificing my laptop to the demo gods seemed to appease them and the rest of my presentation went off pretty well with only one unintentionally funny moment. People seemed to have liked it which I was happy about. You can download a PDF version of the presentation but it plays much better as a live demo.

All of these presentation videos will be available soon. In fact when mine is up I'll be posting it here. As well I'm lagging behind posting my source code but I'm kinda busy with some other commitments I'll talk about on a later date.

Beyond catching up with all of the other PhoneGap committers it was a great conference for meeting folks I internet knew, In Real Life. Besides the afore mentioned Tommy-Carlos Williams who shocked me by not having an Australian accent, he is USA born, I got to meet my co-worker Marcel Kinard for the first time. Both Marcel and I work at IBM where he is managing IBM's contributions to the PhoneGap/Cordova code base. Finally I got to know Jim Cowart of Icenium pretty well over the conference. Jim's done a great write up of the conference himself.

Honestly, I will carry to my grave the memory of the taste of Griddled Bacon Wrapped Date with warm honey from Tora Bravo. Jim, Marcel, Burin and I went there after the first day of the conference and we were all blown away with how good the food was. I guess it is not a secret but Portland is a great city for foodies.

Finally I will leave you with this over the shoulder video of me playing Galaga at Ground Kontrol the amazing barcade (bar + arcade) courtesy of Jim.

Wednesday, July 3, 2013

Backup, Remove and Restore your Contacts using PhoneGap

A couple of people have had questions on how to do this recently so I thought I would do a write up on it. As well, it illustrates how you avoid using loops with asynchronous code. Although for an even better explanation of that topic you'll want to read Item 64: Use Recursion for Asynchronous Loops from David Herman's book, Effective JavaScript. Chapter 7 on Concurrency is worth the purchase price of the book but I digress...

First a warning. Try all the code out on an emulator first. The methods below will completely wipe the contacts from your device so you'll want to make sure the backup step works first before continuing. You've been warned!

Anyway, if you want to backup the contacts on your device to a file you'd use the following process:
  1. Find all the contacts
  2. Request a file system object
  3. Create a FileEntry object
  4. Create a FileWriter
  5. Write the JSON data to file
The code in which to accomplish those tasks is as follows: Once you see the "backup complete" message in the console you'll have a file called "contacts.bak" in the root directory of your file system. For Android users that will probably be /sdcard and for iOS, etc. it would be in the applications sandbox. If you take a look at the file you will see something like this: If you are seeing what looks like your complete contact database in text format then you are ready to proceed.

Next we will delete all the contacts on the device. The steps are:
  1. Find all the contacts
  2. Recurse through the contacts deleting one at a time.
The code looks like:

This might look a little bit weird at first glance but trust me it'll make sense. You'll notice in deleteAllTheContacts the first thing we do is to create a local function called deleteContacts. This is the method that will actually remove the contacts from the device. Then after the definition of deleteContacts we call navigator.contacts.find(). This call will get an array of all the contacts on the device and call it's success function which is deleteContacts.

Now in deleteContacts we do a check to see if the length of the contacts array is zero. If it is zero then we are done, there are no more contacts left to be deleted. If the contact array length is greater than zero we have more work to do. We'll pop the next Contact object off of the contacts array, which reduces the size of the array by one and we'll call the remove method of the Contact object. The success call back for remove method is the deleteContacts method. Keep reading this paragraph until all of your contacts have been deleted. Boom recursion.

But wait, you are wondering how could this possibly work. Your thinking I've got 7 quintillion contacts and there is no way the call stack can support that many recursive calls. Ah, but you are forgetting that asynchronous calls return immediately so they never eat up the call stack. If you tried doing this with a for loop you would blow up the call stack causing your program to crash if you had enough contacts and even if you didn't kill your app how would you know when all of those async calls to remove were complete without doing a lot of JavaScript gymnastics. Just use the recursion approach.

Finally you'll want to be able to restore the contacts you've previously saved to file. I've broken it down into two separate methods to make it easier to read:
  1. Request local file system
  2. Get the FileEntry
  3. Request the File object
  4. Read the data and parse it to JSON
  5. Recurse through all the contacts and save them to the device

This is pretty much just unrolling the two previous steps of backing up and deleting the contacts. If you've gotten this far you should be able to understand what is going on. Although there are two lines I want to draw your attention to:
contactData.id = null;
contactData.rawId = null;
What I'm doing here is removing the unique ID's from the contact. If you skip this step you will signal the API that you are attempting to modify an existing contact and the save will most probably fail. Hopefully this helps a bunch of folks.