FlightPredictor: a postmortem

Postmortem
Two weeks ago I noticed that FlightCaster, the backend service that FlightPredictor uses for all its data, had disappeared. The API wasn’t responding and the website was down. FlightCaster had been acquired by NextJump in January 2011, so the writing had been on the wall for a while.

I started working on the first version of FlightPredictor for webOS in March 2010. I like traveling and planes, and the fact that FlightCaster used machine learning to predict when flights would be late sounded both cool and useful. When I saw their API was free to use that cinched the deal. I’m still not sure what the business plan was for a free API (this is why I’m bad at business!), but many thanks to Jason Freedman for making that possible. Jonathan Chase was also very helpful in answering my API questions and helping me with problems.

I sold a decent number of copies, but that aside, FlightPredictor opened a lot of doors for me. It was featured on the Palm homepage (well, its icon was 🙂 ), it won in the Palm Hot Apps competition (which came with $1000), Palm gave away 5000 copies for the TouchPad (and paid me for them!), and it was featured in the short-lived webOS Pivot magazine. I also got to travel to Palm HQ in 2010, where webOS 2.0 was introduced (day 1, day 2, day 3) and 2011, to get engineering assistance for my TouchPad apps. (recap) And you can draw a pretty straight line to my involvement in the webOS community to my Nokia Developer Ambassador position after webOS was killed.

Back in 2011 I wrote about what I want to get out of app development, and that still rings true.

Stats
Unfortunately some of the webOS numbers are lost to the Palm reporting system change in 2012, but:

FlightPredictor for webOS Phones:
4.29 stars (24 ratings)
released May 2010 (started March 2010)
total copies sold: not sure, but probably in the 1000-2000 range
101 sold in 2011
28 sold in 2012
9 sold in 2013
1 sold in 2014

FlightPredictor HD (for the HP TouchPad):
3.22 stars (59 ratings)
– this had a lot of 0 star ratings – I wonder if this was from people who got the app for free and then didn’t like it or something?
released July 2011 (started April 2011)
total copies sold: probably around 1000? plus 5000 that Palm gave away. See here and here for some raw numbers
16 sold in 2012
13 sold in 2013
0 sold in 2014

FlightPredictor for Android:
4.92 stars (13 ratings)
released November 2011 (started September 2011)
total copies sold: 466

FlightPredictor for Windows Phone:
4.0 stars (38 ratings)
released March 2012 (started December 2011)
total copies sold: 139
84 sold in 2012
44 sold in 2013
11 sold in 2014

FlightPredictor for Windows 8:
4.5 stars (4 ratings)
released August 2012 (started April 2012)
total copies sold: 201
24 sold in 2014 (can’t get data for other years 😦 )

What’s Next
Well, I have this nice shell of a flight tracking app, and I would love to integrate it with Cortana on Windows Phone. It will be a fair amount of work, though, and I’m somewhat actively working on two other apps right now, and it looks like it’s going to be a busy rest of 2014. So: we’ll see!

taking joy in fixing a badly broken LJ app

After the latest LJ release, I got a few emails saying LJ for WebOS was badly broken, and lo and behold they were right.

I was not excited about fixing the app, since I knew the code for parsing posts, which is most of what broke, was pretty brittle and terrible. (c.f. “don’t parse HTML pages with hand-written state machines”) And I don’t even use the app much anymore, and it’s certainly not going to sell many more copies since it only works on webOS phones, which are not exactly flying off the shelves, and new ones might not exist. So I toyed with the idea of dropping support entirely, but that just felt wrong, even though I’d rather be working on new shiny apps for Windows Phone 7.

Last night I took the first serious stab at fixing things, and it turned out to be much more fun than I had hoped. The app was so nonfunctional it felt like writing a whole new one, and it turns out the new page format is a bit nicer to parse to boot. So I’ve fixed maybe 60% of the issues already, and hopefully I can fix the rest by next week sometime (pending New Year’s festivities) and get back to WP7.

Setting values on a view: webOS vs. Android vs. Windows Phone 7

Now that I’m working on porting FlightPredictor to a third platform (Windows Phone), I have a better idea of the differences between the platforms. This post is about one of the more common things to do: taking values in code and making them show up in a view.

For reference, here’s a screenshot of the flight info page of FlightPredictor for Android:

This view is one of the most important ones in the app, and there’s a ton of information on it. Let’s focus on just one part: how to make the flight times (the “4:35 PM – 5:50 PM” in the upper-right corner) show up on screen.

webOS:
For a blast to the past, let’s look at Mojo first. This is the old application framework that is only used for older phones today.

In Mojo, each view is an HTML page, so in our HTML page for the flightInfo view, we include the following:

#{-publishedDepartureTimeStr} - #{-publishedArrivalTimeStr}

(I’m deliberately omitting the layout stuff…maybe I’ll cover that in a future post!)
The #{} syntax means to use the property from the templateModel of the scene. (the - means don’t escape any HTML in the property). So, my Flight object has these properties, and when pushing the scene I call

this.controller.stageController.pushScene({name: 'flightInfo', templateModel: event.item}, event.item);

The event.item is the Flight object, and since I’m passing it as the templateModel, that’s it! All in all, this is pretty simple – as long as the property’s already defined in the Flight object, I only have to change one thing (the HTML source of the view) to get it to show up.

Now, let’s look at Enyo, the new application framework that is used on the TouchPad (and some newer phones). In Enyo, views are defined by JavaScript that generates HTML. (for a real introduction, see Enyo Basics – From the Bottom Up) Here, the FlightInfo kind includes this for the view:

{name: 'currentFlightTimes', allowHtml: true, content: ''}

and then in the create code for the scene, we have:

this.$.currentFlightTimes.setContent( flight.publishedDepartureTimeStr + ' - ' + flight.publishedArrivalTimeStr);

Here we have two things to do, but it’s still fairly straightforward to make new properties show up.

Android:

Things are considerably less happy here. First, we have to define the TextView in the layout’s .xml file:

<TextView android:id="@+id/flightInfoCurrentFlightTimes">

Then we have to create a variable for this TextView in the Activity class:

private TextView currentFlightTimesView;

Then, in the constructor for the Activity class, we have to get the view:

currentFlightTimesView = (TextView) findViewById(R.id.flightInfoCurrentFlightTimes);

And finally, when we set a flight, we have to set the text on that view:

currentFlightTimesView.setText( flight.getOriginalDepartureTime().getTimeStr() + " - " + flight.getOriginalArrivalTime().getTimeStr());

So that’s a total of 4 changes to make, in two different files. This is significantly more irritating than either webOS version, and it really shows up when you have ~20-30 of these to add to the view.

Windows Phone 7:
Back to a world of happiness: with data binding, we can go back to a Mojo-like model and just add this to the XAML:

<TextBlock Text="{Binding PublishedFlightTimes}">

Admittedly, in this case we’d have to add an extra property for this (or make two separate TextBlocks), but there are plenty of cases where I just want a property that already exists. In any event, it’s much simpler than Android. Hooray!

So, the final count:

OS Changes
webOS – Mojo 1
webOS – Enyo 2
Android 4
Windows Phone 1 (maybe 2)

I would be very curious to see what the corresponding number is for iOS – is there a way to do simple templating?

On a revenue basis, webOS >> Android

I worked for around 3 months on FlightPredictor for Android. It’s not a particularly pretty app, but it is very functional, and I am proud of it.

Since I released it 3.5 weeks ago, I have sold a grand total of 20 copies. At $1.99 each, minus Google’s cut and taxes, that amounts to around $20. (and I had to pay $25 to register in the Android Market, so I haven’t even broken even) There’s even FlightPredictor Lite, a free trial version with ads (that have made me 3 cents so far).

On webOS, a platform whose future has been very uncertain since August, and despite the fact that I haven’t released any new apps in a while, and have only made minor updates to FlightPredictor HD (mostly adding airport maps at users’ requests), and there’s no free trial version, I’m still making $10 a day. Obviously there are a lot of factors helping me out there (TouchPad firesale, the fact that FlightPredictor HD is still a featured app and is in Pivot), but maaan. If I wanted to optimize for revenue, I should have doubled-down (ahem) on webOS.

I guess that makes FlightPredictor for Android somewhat of a labor of love, which is odd since I don’t plan on getting an Android phone. It was fun to learn how to make an Android app, though, even if it was frustrating at times.

The Windows Phone version is coming along slowly (busy time of year), and I’m hoping playing around with a developer phone will give me more ideas of how apps generally work on WP7.