I’ve been working my arse off the past few weeks on various projects for clients, and feel the need to write. I’m not sure what I want to write about so I just opened up WordPress and decided to experiment. This post is that experiment.
This morning (a Sunday morning – internationally recognised as me time), I’m taking time away from that for a couple of hours to do what I used to do before “playing on the computer” turned into “making a living”. I’m going to write this as I go, so it’ll probably be terrible. But meh, that’s not a good enough reason not to do it.
Prep coding fuel (actually from a few weeks ago, but representative of liquid requirements):
Oh..kay? So what are you actually doing then?
I’m going to make something with OS OpenSpace; Ordnance Survey’s Google Maps-alike API for using OS map imagery in a manner familiar to developers. You can read about it here.
It’s been on my list of rainy day play-around projects for ages, and whilst I keep getting emails about cool new stuff they’ve done with it, I never seem to have that spare time to actually try it out. This morning that changes. It sounds cool, I want to make something, so I am.
The first part of using any new API is getting something working. I normally do this by setting up an empty project in Android Studio, importing any required libraries and setting up the API keys, secrets tokens or whatever the API uses for authentication.
As I’ve signed up for an API key already, I went to the Manage My Sites page (which is for apps too, despite the “sites” title) on the OpenSpace site to see what my API key is, and to find out which package name I originally used when I signed up – I’ll need to use the same one for this mini-project. I called it com.mattfenlon.osmap, so that’ll be my package name.
Integrating the SDK
Next bit is to integrate the Android SDK if they have one, which they do. Cool.
But bloody hell…not the most straightforward quick start guide I’ve ever seen! To save you skimming time if you want to just get the jar file, it’s here. Import it into Android Studio (or Eclipse if you’re a masochist and haven’t switched yet). Not covering that step here. GIYF.
Getting something to happen…
By this point I’ve got the jar file set up as needed in my AS project, and it’s syncing fine. I’ve loaded up a Genymotion emulator (because the Android SDK emulators suck…); a Nexus 6 configuration, running Lollipop. Because shiny. The app builds and loads the bog “Hello World” with no errors, we’re in business.
Incidentally I’m using Fragments not Activities, because they’re efficient, super-flexible and best practice. Anyone who tells you otherwise is either too lazy to learn the new way, or is recycling old projects from the days that they used to use Activities and cba to update their base projects. Sorry, it’s my opinion of course, but there’s no downside to using Fragments for even simple projects like this if you’re a half-decent developer. /rant
Setting up permissions
From the example app, it looks like it needs Internet, External Write and Access Network State. Also Open GL ES 2, presumably for some map rendering shenanigans.
Adding a MapFragment
This is done in XML. Nothing fancy, just a <fragment> of name:
It has a label too, not sure if that’s needed yet.
Setting up the MapFragment in Java
Similar but not the same as a Google Maps setup. I’m using the demo app they provide in GitHub to get the map object instantiated. The only difference being that I’m doing this within a Fragment rather than an activity, so getFragmentManager() becomes getActivity.getFragmentManager() etc. No biggie.
Now I’ll try running it to see if it’s all good so far…
Cock… Right, to LogCat. What have I done wrong?
Right. I don’t think I’m jumping to conclusions to guess that it’s something to do with that OpenGL ES 2.0 reference from earlier…
How do I find out what went wrong then?…
Best bet is usually check out the documentation/comments within the library that you’re using. I just did and found this from here.
There’s talk of emulator issues with hardware acceleration. I’ll try on actual hardware to see if that’s the issue.
Sure enough. Works fine on hardware! Rather than implement a workaround as suggested, I’ll just crack on with my physical Nexus 5. Life’s too short, and this is just a hobby session.
Adding a marker
This looks very familiar, very Google Maps like, which is what I’m sure they were going for in order to reduce boundaries for adoption to existing developers – don’t make us work too hard, always a good idea.
Rather than read docs or do trial-and-error to see what the format is of such a grid point. I’ll just punt it out from a touch input in that OnMapClick listener method, straight into LogCat.
Then I’ll run the app on my phone and tap it a couple of times to see what I’ve got.
Interesting. So it’s a six-figure reference with no decimal accuracy as far as I can see. Every tap yields a .0 on the end. Reckon that’s just an OS grid reference stored as a Double? I’ll have a look here.
Confirmed! Progress then. It should be trivial then to add markers. I’ll find somewhere interesting, get the grid ref and try it out.
It needs a string for a label, and a BitmapDescriptor for an icon. I’ve borrowed an icon from here for that. Free for personal use (I’m not selling this little app, so I think that counts). What’s that look like then.
Ah…that’s a bit big. I pulled it straight from a Drawable. I’ll make it a Bitmap and resize it. I also need to make it zoom and centre on the marker that I just made, as I have to scroll to it at the moment.
Adding more stuff…
At this point, I got lazy with the typing and just ploughed on with a little demo app… So this last bit is brief. (you can skip to the GitHub repo at this point and read the comments)
I thought the helmet and Silverstone was a good start, so I went on Wikipedia and found the locations of all of the permanent UK racing circuits, converted the listed Lat/Lon to OS Grid references using this handy site again, and manually added them to an ArrayList.
The array list is then parsed and adds the markers to the map. I set a 3000m per pixel value for the zoom, so it sort of pops out when you open up the app.
That’s it. Check it out on the GitHub repo if you want to see the super-simple implementation.