programming: checking that downloaded maps are up-to-date
Posted on 2012-03-27 15:18:00
Tags: projects programming
I came across an interesting problem when working on FlightPredictor for Windows Phone: ensuring that downloaded airport maps are up-to-date.
This is the first time I've had to deal with this problem when porting FlightPredictor:
- The original FlightPredictor for webOS phones doesn't include airport maps. Simple! :-)
- In FlightPredictor HD (for the HP TouchPad), I just included the airport maps in the app itself. This made it a big download, but it was dead simple. When I wanted to update the airport maps, I would just upload a new version of the app, which was a little annoying but the maps don't get updated that often.
- For FlightPredictor for Android, I used Android's neat Content Provider functionality to provide the maps in a separate package, so it could be downloaded separately. This means that people that just wanted the app without maps could get that, and when I updated the maps I could just update that package and not the main one.
But neither of these options were viable for WP7 - there are limits on app sizes (if I included all the maps, it could only be downloaded over WiFi), and there's no Content Provider-type mechanism. So I decided to let the app download the maps from inside the app itself, if the user chooses to do so.
This created a new problem: how could I tell when new maps were available? Here were my criteria:
- As little data transfer as possible: One option was just to check every week or so if there are new versions. I wanted to avoid this because I'm hosting the maps on Amazon S3, so I pay for bandwidth.
- Doesn't have to scale up to many updates: As I mentioned, these maps don't get updated too often.
- Can't falsely claim there are new maps: A corollary of #1 - the full maps download is ~20MB, and I don't want people redownloading them for no reason.
- Can't assume maps update at the same time as the app: There is a variable delay between when I submit a new version and when it appears in the Marketplace and when people actually start updating.
So, here's what I came up with:
- When we download the index file (a JSON file listing all the airport map file names/titles), we calculate the SHA256 hash of the index file and save it.
- On startup, we check to see if the saved hash is the latest version. Here's the tricky bit: the app has a list of all known "old" hashes, as well as the current one. We only report that there are updated maps if the saved hash is one of the old ones - if it's one we don't recognize, assume it's a newer version that we don't know about yet.
And my process for updating maps is to publish them to S3 first, then submit a new version of the app with a new maps index hash. If old users manage to get the new version of the maps, no problem - they won't report as out of date (since the hash won't match anything), and when they get the new version of the app they won't report as out of date either.
This backup was done by LJBackup.