If you’re a regular reader of my blog, you will have noticed that I recently went on a Raspberry-Pi-fueled, hardware hacking binge, first using it as an infrared remote control and then applying the same principles to make it into a RF remote control, thus mostly controlling my entire house in this fashion.
This is the IR setup in action:
You may have noticed two things (well, one and a half): Firstly, there is a bit of latency between clicking the button and the browser making the HTTP call to the server, which adds a bit of latency to the whole thing. Secondly, and less markedly, you need to launch the browser (which always takes a while to start up), navigate to the webpage, maybe authenticate and start pressing the laggy buttons, which you have to also create yourself.
Since I’ve wanted to get started with Android development for a while, I figured this would be the perfect opportunity to create something interesting. Enter Tungsten, now available for free on the Play store. This is the story of how I built it and my general experiences with Android development, as a complete Android and Java novice.
This is what I envisioned making in the beginning: An Android app (provisionally called Tungsten), which allows you to easily create your own remotes by entering labels and URLs for the button in a YAML-based layout file and putting it up on the same server you’re using for your HTTP API. Point Tungsten to the URL where your layout file lives, and it will download and install it, creating the buttons. Press a button, and Tungsten will make a POST API call immediately, in effect controlling your Raspberry Pi (or any other server you specify).
Of course, your layout file can specify multiple devices (or you can download multiple layout files), and Tungsten will happily add them all, allowing you to swipe between panes to get to the different devices. That way, you won’t have to navigate from one page to the next, you can just swipe right to control your TV and swipe left to control your garage door.
The advantages to this are manifold: Much shorter startup time (usually instant). Much less latency (usually within a few MS, looks like). Less hassle in creating the interfaces. Can control multiple devices from the same app.
More generally, Tungsten can issue HTTP POST requests to any server you specify, so it could also be used for controlling purely software-based servers (maybe for starting various tasks/reports).
I looked for some good resources for Android development on the web, and came across the Busy Coder’s Guide to Android Development. While I only read a few pages before using it mostly as a reference, it struck me as a very well-written book, and it solved many questions I had when referring to it. I would definitely recommend it if you’re just starting out, as it explains everything very clearly and concisely.
I downloaded and set up Eclipse, like the book very clearly details, and was quickly up and running (hell, I even managed to get the “hello world” running on my phone, which was magical for me, in a few minutes). After reading a few pages on the Android basics and creating a simple app with a few buttons, I got a bit itchy and started looking for samples that would allow me to implement a swiping layout. I found the official Android sample for tabs/panes, and quickly had it running on my phone, and even managed to create a few buttons on each pane (they’re called “fragments” in Android parlance).
I also found examples on StackOverflow (where basically 50% of my development happened) on how to store data on an SQLite database, how to add buttons to a view, how to add or delete fragments, etc, which guided me through development all the way to the final product.
One thing that frustrated me to no end was a bug that prevented panes from being removed. I wanted to give the user the ability to delete a pane, but Android screwed up when deleting the fragment and didn’t remove it, resulting in a crash later on. This took me around three days to track down, as nothing I tried seemed to work. In the end (and for posterity), what worked was to use a
FragmentStatePagerAdapter while overriding
getItemPosition to always return
POSITION_NONE, for no reason whatsoever. Nothing indicates that this should be done, or even indicate that a normal
FragmentPagerAdapter is unsuitable for this. Dark magic, but I found the solution somewhere on StackOverflow.
Another annoying thing is the need to access
View objects everywhere. It really cramps my style having to pass them, and I don’t know if I’m introducing memory leaks by storing references to them, but there’s no other way I can see to, for example, split off the code that performs the HTTP request without it. The HTTP request code only needs the context to generate a notification (a
Toast), but, nonetheless, I need to pass it everywhere, which is quite annoying.
Publishing on the Play Store
Publishing on the Play Store couldn’t have been easier. There’s the Preparing for Release document that clearly details what you should do, and I had my APK created and uploaded in a few minutes. Creating all the icons, screenshots and descriptions took longer, but the icon was literally two seconds of Inkscape with the calligraphy brush, so the whole process was really quick.
What I like about the Play Store, apart from the statistics, is that you can have alpha, beta and production stages for your app, and control access to them via a Google Group or Google+ Community. That was very nice, since it allowed me to distribute my application to friends for the alpha stage easily and without everyone else getting a buggy app.
Making the app run on more devices
Initially, my app only worked on Android 4+. With the excellent support libraries and the brilliant emulator, it took me an hour to support Android 2.3, and another one to support 2.1, pretty much getting 99% of the devices out there supported. Sure, my app is a toy and really small, but it wasn’t significant effort anyway. I fixed a few bugs relating to the HTTP libraries in the emulator as well, and I was off to the races with the second version of my app!
In general, I found Android development pretty straightforward. For Java, the only knowledge you need is a vague familiarity with OOP, and that was pretty much all the language you need to know, as Java is both pretty straightfoward to pick up and has excellent tooling, so Eclipse helps you with things you don’t know by almost always suggesting the correct syntax.
That said, Java is pretty annoyingly verbose. I found myself writing 2-3 lines of code for every line of code I would have written in Python, and got pretty frustrated in the process, but it was only frustration at the verbosity, not actual difficulty. Fortunately, StackOverflow can get you a significant amount of the way there, as pretty much every question you’ll have has been answered by now.
The Android APIs are a bit complicated and hard to follow if you don’t know what all the
Contexts and everything are and what they’re used for, but I’m slowly learning. I’m really not confident that I’m not passing the wrong thing most of the time and creating awful memory leaks, but that’s something you learn with time and by reading, so hopefully I’ll get there.
In the end, writing some code and seeing it run natively on my phone was an utterly exhilarating experience, probably because I am a huge nerd and find these things supremely interesting. I did enjoy the whole process, frequently staying up until 7 am to code the thing, and loving every moment of it.
I can definitely see myself continuing with Android and improving Tungsten, and I already know what I want to work on next: Better layout support, in the form of a CSS-grid-like column layout (I’ll see how I can best implement this). The app runs very well so far, without any problems, and I’m using it daily (I have to say, controlling the desk fan from the couch with the mobile phone is magical). I’ve had no crashes or any other problems with it, and I’m very proud of what I achieved in roughly three days of development in total.
You can find Tungsten on the Google Play Store, and it’s free to download and use. I’d appreciate if you would use it for your project, or if you’d give me any pointers, as I’m still very new to Android. Thanks!