Wednesday, November 28, 2012

Reminiscing the Kindle (E-Ink) days

Way back in November of 2010, I put together a native app for the folks over at Naiku for the TIES 2010 Conference. At the time, the three major e-reader devices were the iPad (1st generation), Android tablets (v2.2/Froyo - if you were lucky), or the 3rd generation E-Ink Amazon Kindle. 

Since Android and Kindle both use Java, I was eager to see what kind of native app I could put together in an "extremely short" amount of time. I wrote up the Android version first, and then turned my effort towards the Kindle.

The limitations
Developing a native app for the Kindle (E-Ink) is a very different experience than Android (obviously).
  • The first hurdle was gaining access to the Kindle Developer Kit (KDK). Amazon restricts  access to this program, which means the developer tools and API aren't freely accessible. Even the official KDK forums are "invitation only".
  • At the time, the KDK only supported Java 1.4, which was severely limiting, because some of my favorite Apache libraries required Java 5 (annotations!)
  • Another limitation was that raw Sockets were not allowed, which negated my ability to use the Apache HttpClient, which used a Socket, not a URLConnection. In the end, I had to code up my own cookie-handling HTTP Client from scratch using the KDK Connection. This was needed to communicate with the central server and receive the JSON data.  
  • I had to get the signing keys so that I could deploy my app to a real Kindle.
  • The widget library is very basic - there wasn't a checkbox widget, nor radio buttons, so I had to write my own widgets.
  • The 3rd gen Kindle decided to omit the row of keys for numbers (which was present on the 2nd gen), which made it really hard to answer numeric math problems. Fortunately, you could use "Alt" plus the top row of keys - but the Kindle didn't have that screen-printed on the device. Instead, Amazon recommended that your app display "soft-keys" at the bottom of the scree.

In the end, I managed to get something "highly usable" in time for the conference.
Here's the login screen:

And here's a sample question, which demonstrates the "custom checkbox" widget for the multiple-choice selection. Some questions were single selection, so it had to act like a Radio Group, and other questions were multi-select, so it would have to act like a bunch of check-boxes:

Not surprisingly, the "finished app" was ridiculously small and took no time to transfer over the wireless connection. 

In the end, it was yet another great geeky experience!

Monday, November 19, 2012

How old are these songs?

I'm constantly looking for new music - the upbeat kind that gets the energy flowing for coding. I used to listen to the station "93X", but I've noticed that their song catalog is becoming increasingly antiquated.  Since that's just a guess, it seemed prudent to verify the hypothesis using a little "cloud magic".

Gathering the current song data

On the station's website, they have a "ticker" that lists the currently playing song. Using Firebug "Net" panel, it looks like the Javascript code has a timer that polls the site every 15 seconds for the current song's artist and title.  The URL request looks like this:

The response is something like this:

Cached Data

<div id="nowPlayingArtist">SOUNDGARDEN</div></hr>
<div id="nowPlayingSong">BLACK HOLE SUN</div>

Yeah, that's right, it's 2012, and they're still playing "Black Hole Sun" (hey, I like the song too - but a bit less than when it was released in the early/mid 90's).

Now that we have a "easy" way of obtaining the current artist/song information, the next step is to find out the release date. Fortunately, Apple's dominance of the recorded music business comes in handy here. iTunes makes it easy to search for something - they even have a convenient API guide: 

Thus, the search URI looks something like this:

The result is a JSON array (very nice!) containing 43 matches. The hard part here is going to be finding the "correct" entry among all of the values. It seems that the "ideal" way to accomplish this is to find the object(s) which match (case insensitive!) these property values:
"trackName":"Black Hole Sun", 

In this case, there's a few "correct" matches, and each has a different release date:

In this case, the "solution" is to simply pick the oldest release date.

Saving it for later

The next part is accumulating that information and storing (persisting) it so that an continual analysis can be performed. Otherwise, it's possible that a particular DJ may prefer the "classic" songs over the newer ones, and thus would skew the overall results.  The big question here is "what's the average age of the songs played on this station?"

Since this is being stored "in the cloud", a few options are available.

  • Google App Engine Datastore, which is effectively a key/object store. 
  • MongoDB, a document store 
  • Something relational, like AWS RDS, Microsoft SQL, or Google Cloud SQL 

For this trivial app (small amount of persistence), any of them will suffice. More on that, and the eventual code/implementation coming later.