Yesterday I released my first Android application into the Android Market. The application is a sliding puzzle game, and comes into two flavors, a free (lite) version (called "Sliding Puzzle Lite"), and a full version ("Sliding Puzzle Full") at $0.99. The lite version has only the basic features, such as 9 pre-loaded images and the ability to view the full (final) image during game play. The full version has the following features:
- pre-loaded with 9 images
- 4 difficulty levels (3x3, 4x4, 5x5, 6x6)
- shuffle puzzle image
- view final image
- load image from SD Card
- take a picture using the Camera and load it as a puzzle
- displays a timer during game play
- displays how much percentage of the puzzle is done
- displays the number of moves made
Below are some screen shots of the application:
I want to make some observations about the entire process.
First, the design was far from optimum in the first iteration; it was too complex for a one-screen game (one main screen, namely the puzzle screen). I started refactoring when I had to add some features and I noticed how hard it was to do just that. I ended up getting rid of some classes, methods, and instance variables all together, simplifying the design. Efficiency is crucial when developing for mobile devices. My background is in Java ME, where the restrictions are even bigger than on Android-based smartphones. For example, because I had to work with key-value pairs, instinctively I first went with a HashMap. I notice that the key-value pairs where actually pairs of integers, so I switched to using a SparseIntArray, which is more efficient that a HashMap. An even better approach would have been to use to parallel arrays of ints, but that's exactly how the SparseIntArray class is implemented, thank you for that! Overall, I tried to follow the guidelines form Designing for Performance document. Hence, the entire process was an iterative/incremental one, based on add feature <=> test feature <=> fix bugs <=> refactor (I hope the model does not look like a waterfall one because it wasn't :)). I noticed that testing and fixing bugs took the most time (and I am sure I still have bugs left unnoticed by me). I have been testing for the past month (and I've been doing all this in my spare time, being that I am working on my PhD also). Testing was still done manually (I hate that I do not use some kind of unit testing in Android). My biggest problem was that I was getting out of memory exceptions when loading bitmaps (especially when loading from SD card). I ended up using Bitmap.createScaledBitmap method to scale the bitmaps down. Furthermore, having the bitmaps displayed on the screen was initially done in a 'bulk' manner, where the screen would freeze until the first couple of images could be displayed. That's not user friendly at all; reading some blogs from smarter people, I ended up using a AsyncTask, where each image I would load, I would display on the screen, one at a time. With that, you would images being loaded on the display, similar to how the Gallery application (that comes pre-loaded on the phone) works.
Second, nothing beats testing on a real device. Emulators do come close, but having a device made quite a difference. For example, on some G1 phones, the camera software has a known bug, namely that the camera preview does not work in portrait mode. This issue is of course non-existent in the emulator.
I keep telling fellow students that I work with (or teach to), that nothing beats writing applications. Sure, you can read books (which of course you have to do), run examples, but if you do not start coding, you will never get to the next level as a programmer.
There are other lessons I have learned, and maybe I will post them in a later post.
Overall, I am looking forward to adding new features to the full version of the game (such as speech recognition, integration with Facebook, and many more), and also developing the next game from the list of ideas that I have.
I hope you enjoy the sliding puzzle, at least as much as I enjoyed developing it!