Having talked about wanting to write a phone app, I now need to work out what to write: this is important because you’ll never forget your first app.
One of my simple pleasures in life is getting to the top of a hill to discover a view indicator. You know the sort of thing, a lovely brass plaque with lines radiating out showing the bearing and distance to various landmarks. I’m engrossed and spend a happy time following the lines to the various landmarks, much to the chagrin of the Canine Companion who regards a summit as a food stop and is demanding better service from the kitchen. Sadly, one of the many disappointments in this life is that such delights don’t appear on every summit. So wouldn’t it be cool to have an app that provides this public service wherever you are? That’s one of the better articulated requirements specs I’ve read in a while and so that is what my first phone app will be: View Indicator 1.
The idea is that wherever you are you get a nice indicator showing the bearing and distance to various landmarks. And it would be nice to point the phone at some distant landmark and say to anyone in earshot (yes, I’m looking at you Jazz): “Wow! That’s Schiehallion and it’s 85km away.” Hours of endless tedium awaits my walking companion – what could be better? It’s also much more convenient to have this app in a nice phone that fits in your pocket than have to carry a large brass plaque around in your rucksack.
So it’s a simple matter of bringing three things together:
- A database of landmarks (name, latitude and longitude)
- Our current location (hello GPS)
- Which way are we looking? (Yes, the phone has a digital compass – let’s talk)
Now those of you reading the above spec closely will be saying “But, Kev, you’re going to need two separate views here: one for the radial indicator and another for the “what’s that over there?” part”. Award yourself an extra glass for your attention to detail. You are right, we are going to have two views and allow the user to switch between them with a cool flick of the finger gesture. This is just a way of playing with more of the Android platform.
A central concept in Android is the Activity. This is where users get to do things and the platform has to manage them. My little phone has roughly 107 the computing capacity that John Young 2 had on Apollo 16 but the difference is that I have a tiny little Li-on battery to keep the phone slim so it doesn’t spoil the line of my suit 3 whereas John had three big fuel cells to power his computer 4. The Apollo computer has very limited memory and CPU cycles but heaps of power; I’ve got the opposite, and so Android has to do a juggling act keeping those two cores humming while drawing the power you get from a lethargic ant.
So I’m splitting the app into two activities: get my location, and then show what I can see from this location. There’s a good reason for this split: they are logically separate things, and only one of them needs to use that battery-gobbling GPS service. Once we’ve got the location we can shut it down and save the battery for a rainy day. Once we have the location we can pass on to the second activity which is showing what we can see from this point.
So the first activity (after the obligatory splash screen) is to get the current location. We check if the GPS service is running and if not give the option of going off to the settings to enable it. A great time-saver was to also include the option of just using a fixed point (my house) instead. This has the great advantage of not needing a view of the GPS constellation when debugging indoors! If we go for the GPS fix then we wait until we get an accuracy of 100m or less, at which point we enable a big Proceed button to let us to move into the next activity.
A World of Two Views
In the second activity I want two separate views with a flip (Android term for the side-ways swipe gesture) to switch between them. This activity is the one that listens to the compass sensor and updates the visible view. We’ll call the first view “List” and the second “Rose”. Both of these make use of a database of landmarks (places with known position). This database is held in a SQL Lite database (one of the libraries provided by Android) . Although I spend my days up to the elbow in SQL databases, I prefer to wrap all that plumbing in a nice object-oriented entity framework. Over the decades I’ve played with most paradigms (imperative, declarative, functional, relational, object-oriented and probably a few others) and the one that fits my mind best is object-oriented. They each give something interesting and we’re now getting a lot of cross-over, e.g. the arrival of lambda expressions from functional languages into object-oriented languages like C#. Cool, succinct and useful.
So it is natural to add a little wrapper using Android’s content provider framework to give me landmarks as nice objects with methods and properties as Darwin intended. With the plumbing done we can start on the views so we can finally see something.
This takes the current compass heading and displays a list of landmarks in that direction arranged closest first. The list will show the distance to each landmark. To give a bit of leeway, we’ll include landmarks that are ±10° of the heading. A small needle (a custom view showing an arrow-head) will show whether the landmark is left or right of the current heading. In this example screendump you can see that our bearing is 8° (roughly north) and that Ben Lomond is slightly to the left, and Ben Ledi slightly to the right. When the needle is pointing straight up then you are looking directly at that landmark.
This is my attempt to show the relative bearing and distance to all landmarks within a certain distance of the current location, i.e. an analogue of the brass plates. We’ll use a slider to control how far we want to look. The display will show the name and distance with a line whose length is the fraction of the selected range. Clearly a view like this isn’t shipped as standard in Android so I need to start from scratch with a custom view. Luckily Android has an excellent set of graphics libraries that make this stuff a cinch so long as you remember all that graphics transformation stuff you last used 30 years ago…
What’s That Flipper…?
On a smartphone you have limited screen space and so we can’t show both views at the same time. So we arrange the UI to use a ViewFlipper to hold the different views and wire up a touch listener to see if the user is flipping the display. When you combine this with Android’s built-in UI animation mechanism the control is very simple and effective: a sideways flick of the finger and the views fade in and out. Way cool.
But What About My Tablet 5?
Now it so happens that the Missus 6 has a Galaxy 10.1 Tablet (i.e. gorgeous piece of kit) that could easily show both views side-by-side and I just happen to have borrowed it for the day. Any chance? Pah, child’s play!
One interesting approach in Android is that the user interface (UI) is typically defined in an XML layout document rather than assembled using (typically verbose) code, and it allows you to specify different UIs for different classes of device. So my phone gets the “show one view at a time” layout, while the tablet gets the “show both views together” layout. The only change to the code was in selectively adding listeners for the flip gesture if we are only showing one view at a time: the rest was just XML definition fun. I haven’t done a great deal to optimise the UI but it shows the potential: same app running on very different devices with minimal code change.
So What Did I Learn?
Android comes with a lot of surprisingly good documentation including tutorials and sample code. Read it. And again. Try out the examples. Google anything you don’t understand because (literally) millions of other people have been down the road before you and have been generous with their comments and suggestions.
It’s Running on a PHONE!
It’s still amazing that I’m writing high-level code using things like threads, 2D graphics, advanced UI controls etc and running on a PHONE! And the performance is better than some desktop machines I was using only a few years ago.
Declarative User Interfaces
The XML layout mechanism tries for that nice separation between UI and functionality, but doesn’t quite get there. Your code still needs to extract the various views you need to display your data and this introduces fragility in needing to cast properly. If there is any problem in the layout definition then things go bad quietly with only an unhelpful stack trace from somewhere deep in the activity manager to indicate a problem.
For things like colours and strings you can define them in XML and refer to them in the code. This is fine for “Hello World” but as your app grows you’ll find them sprouting like mushrooms in a student flat. So I strongly recommend you invent some naming scheme that indicates where they are used, e.g. “global-background”, or “splash-credits”.
My best bit of advice in developing on Android is to “hurry slowly”: start with something very small (Hello World) and move in very small steps trying out the result at each point. Keep a restore point at every step (a bright guy like you is obviously using a source control system) so that when things go pear-shaped (and they will!), you can at least revert to the last-known-good state.
Give Stuff Back
This is the crux of the open-source philosophy. That’s why I’ve scribbled down this rant – it just might help someone. Should anyone be interested in the actual app itself please get in touch via the contact form and I’ll ship you what I have.
- July 2012: I’ve recently discovered that these things are called Toposcopes ↩
- My favourite astronaut: the epitome of cool. ↩
- If you didn’t go “What!? The next time Kev will be in a suit is when the undertaker is laying him out.” at that point, then you clearly don’t know me. The more sentimental among you might think “He’ll be in a suit when he takes his daughter down the aisle.” – fools. I’ll obviously be in Craghopper trousers – the only question is whether they are shorts and that depends on time of year (April to October = YES, otherwise NO). ↩
- No it’s not fuel cell envy: over 30 years ago I built a Methanol fuel cell for a 6th year school chemistry project. You did know that they were a British invention don’t you? ↩
- Although I prefer The Register‘s term Fondleslab ↩
- A major gadget-freak ↩