Wednesday, December 5, 2012

Exercising my inner geek


Overview: The Y Mobile App is something that I wrote (and continue to maintain) for free in my spare time.  My previous "smartphone" was underpowered and incapable of displaying the "official" on-line exercise schedules, plus I wanted a quick way to check and see what was happening at the locations around me. 

I initially shared the app with friends and other members that I knew. Those people liked the app for its convenience and usefulness, and shared the link via Facebook and E-mail. Some people find that this app helps them discover new Group Exercise classes to try - there's a wide variety of classes, and the Group Ex instructors are great (I'm always amazed - and very thankful - at the amount of work they put into running those classes)!

If you have any comments or suggestions on improvements for the app, please leave a comment below!


The long story (with lots of geeky details):

A few years ago, I joined the local YMCA in attempt to counterbalance the hours that my butt spends in my office chair. One of the "member benefits" are the various Group Exercise classes (most of which still intimidate me - because I'm a geek, which means I'm accustomed to not fitting in). Since I bounce around between a few of their locations, it's handy to have on-line access to the schedule information. The problem is that their web site wasn't very compatible with my stinkin' old first generation LG Optimus cell phone. 



The phone has a decent web browser - the usual WebKit enabled thing that came with Android 2.2 (FroYo) - it just didn't like all of the lovely Flash widgets used by the YMCA site, and the response time was longer than my attention span (I hate waiting on computers - which is a driving factor in the software I write - if I can't stand it, nobody else should either). One day, when I was using a "real" computer to view the Group Exercise (Group Ex) information on the YMCA's website, I noticed the queries were landing at a website called GroupExPro.com, with a bunch of "human readable" parameters on the query string.

My inner geek couldn't resist the temptation, and I hit F12 to bring up Firebug and check out the  interaction between the browser and their site. I fiddled around with the options to see if a JSON response was possible (rather than the pre-formatted HTML stream), but couldn't find it. I decided to send an e-mail to the site's support/contact address to see if they already had a JSON option available. I was surprised to receive a response (on a weekend night!) from one of their developers who gave me the magic parameter needed to receive a JSON response. After a little testing with 'wget' (relax, I've started using 'curl' more often these days, due to development with RESTEasy), I was able to tweak my query strings to assemble the information I needed.

Since it was winter 2012 when I gleaned this information, I was ready for a fresh "geek project", and this seemed like a perfect fit. I was working on learning more about Google's AppEngine (GAE) and their App Engine Datastore (yeah, yet another NoSQL implementation). After a few nights of work, I had the "alpha release" ready for use. My app pulled the JSON data from the GroupExPro website every few hours, and stuffed it in the Memcache since it's "expendable information" that can be re-obtained if/when the Memcache fails or gets flushed.

The whole thing is coded up in GWT, which worked great for this project - On the Client Side, GWT provides simple RPC with the server, UI event handling, Browser History management, and compacts all of the UI's files into an obscenely tiny download. The hosting on GAE is free because the amount of CPU and bandwidth used by my app falls below Google's minimum thresholds, which means free hosting!

Here's the link to the live application (still running in Google App Engine):
http://ytwincities.appspot.com

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:

http://www.93x.com/jsfiles/NowPlaying.aspx?lid=5163&source=http%3A%2F%2Forigin%2Emedia%2Eradcity%2Enet%2Fkxxr%2Fnowplaying%2Fnowplaying93%2Exml&refresh=15&5927.663631614869

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: http://www.apple.com/itunes/affiliates/resources/documentation/itunes-store-web-service-search-api.html 

Thus, the search URI looks something like this:  https://itunes.apple.com/search?media=music&term=SOUNDGARDEN+BLACK+HOLE+SUN

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", 
"artistName":"Soundgarden", 

In this case, there's a few "correct" matches, and each has a different release date:
"releaseDate":"2010-09-28T07:00:00Z", 
"releaseDate":"1994-02-28T08:00:00Z", 

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.