My iPhone development article was based on a 14 day start-to-finish concept. But one thing I learned from that experience was that 14 days was really too short for me to do any sort of complex app. There's just too much to do.
The original app was a bit of a 3D interactive slide-show based on photos from your iPod or iPhone. For the Android app, I decided to expand the concept by dynamically bringing in additional content from the Internet. This was going to complicate things greatly, so I would just let it take as long as I needed. This turned out to be several months of on-and-off, night and weekend development.
As I started porting my app, it quickly became clear that there would be little reuse other than general architectural flow and concepts. The original code was Objective C, the new would be Java, and never the twain shall meet.
The OpenGL calls were somewhat of an exception. I'm far from an OpenGL expert, so it was good to use the original as reference, even though there were differences due to the language bindings and the general level of support from the different platforms.
Once I got rolling, It didn't take too long (about a week or so of part-time tinkering) to get the basic functionality of my original iOS app running under Android (Figure 4).
Figure 4: Basic functionality working.
This emulator screen-capture shows the running app with the same basic level of functionality as the iPhone version. I could fetch, re-size, display and scroll my images in a three-dimensional space with basic user-interaction. And this time, there wasn't anybody around to slap my hand with a ruler when I scanned the file-system for images.
Once I had the basic app running, I moved on to fetching additional content online. Since I was dealing with images, I started with a few online photo sharing services - Flickr, Panorama, and Pic Plz.
Most online services these days have opened up an external application programming interface (API) for folks like me who want to do a bit of mash-up with their content. Each API is a bit different, so part of your task will be to abstract these differences away so the bulk of your code won't know where the content came from.
For me, the initial cut at fetching online images came pretty quickly, since I was familiar the the basic Java operations. But when you're writing an app that deals with external content, there are a lot of "corner-cases" and architectural decisions that need to be made with respect to external communications to really make it bullet-proof.
For example, if your app starts up and you can't get online, what action do you take? Continue and hope the connection comes in later? Give up? Have some level of reduced level of functionality? These are all questions that you'll have to address and they are specific to the app.
If you have a good Internet connection, there's no problem. And if you have no connection it's fairly easy to deal with. But what if you have a "bad" or intermittent link? This is where it gets tricky and you have to think about what this means for your application.
When the app starts up, you can check the online state. But there's no guarantee that it won't be different a second later. You have to be prepared to deal with changes. In my case, I had problems that would show up when I had a spotty connection. My checks would indicate that I was online, but when I went to fetch content, I wouldn't get anything. This would manifest itself as a mostly back screen as I had nothing to show.
The eventual solution was to dig deeper into the Java APIs, adding a timeout to the low-level socket being used to fetch content. If it was taking too long, I would give up. This can still be a bit tricky, as you don't want to get into a state where you "thrash" a bit as you try to make a connection give up, and then try again forever.
For my app, I had to add a number of checks inside the code to query for online state and then fall back to a set of built-in photos if I couldn't get any from the Internet. I'm still not totally satisfied with this solution, as I suspect my users will get tired of seeing the same images frequently. But the alternative is to show a black screen until I can get the "real" images.
I toyed with the idea of using a cache for those times when I couldn't get online or when I wanted to conserve bandwidth. But the problem for me was the type of data I was using. Caching is useful when you are using the same data over and over. But for my app, this isn't the case.
I'm fetching new data fairly often, so a long-term cache isn't all that useful. In addition, there isn't a lot of storage space on these devices, so I didn't want to fill it up with transient data. In the end, I decided to just cache small images such as Facebook icon photos or RSS icons because these tended to show up over and over.
Another issue you'll have to deal with when fetching anything from the Internet is unknown content. It isn't uncommon to try and fetch data only to find out it's missing, corrupt or too large. For handling missing or corrupt content, you just have to be paranoid and make sure you check whatever you can and wrap critical code in the proper exception handlers.
For large images, the problem is that too big of an image could cause the app to run out of memory. There's no guarantee that today's hottest image on Flickr isn't a 500 MB candid shot of Justin Bieber eating a hot dog at the mall.
So I just had to decide on a maximum image size that I would even try to handle. Anything too large would just get discarded before I even tried to read it all in. This maximum was adjusted based on the capabilities of the device I was running on. Available memory can be queried when your app starts up to give you some idea of what you're dealing with.
This brings up yet another facet of Android development: Dealing with potentially hundreds of device variations. When you're targeting only iOS devices, you're just dealing with the few variations of the iPod, iPhone and the iPad, which are likely up to date with the latest OS.
But with Android you have to consider numerous screen resolutions, CPU speed, physical capabilities and wide variations in OS version. For me, this meant extra time in the emulator and lots of time rounding up friends and family to test the app on their phones.