Let me introduce to you: aPod - another Android music player
At the first glance aPod is just another music player for Android. One out of seemingly hundreds of available music players. So what makes it special and why did I have to write a music player at all?
I intially started the project when I had a Motorola Droid running Android 2.1. At that time I was using the phone for music playback a lot. And I was pretty unhappy with the available music players. Some of them had really bad userinterfaces with sometimes non-sense Activity lifetimes. Especially with the stock player I sometimes got nuts trying to open the playback screen or maintain playlists. Only a few players had a clear and classic music player interface with a playback screen and separated playlist. So the first reason for aPod was to handle this usability massacre.
Another problem with early Android versions was the bad/missing genre-support. I listen to many different genres and most of the time I like to play only one or two mixed genres. Most players had functionality to create playlists based on ratings or anything. But it kind of sucks listening to electronic and suddenly having a mario-song or a metal song pop in between. I just wanted a media library allowing me to maintain genres.
Soon the aPod project developed to a playground of what I could do with this new interesting platform called Android. Up to date aPod had a redesign and now has grown to much more than a basic music player.
The typical approach to creation of an user interface should always follow one direction: "problem -> solution". There should be no design patterns which aren't solutions to an existing problem. The more detailed a problem can be described, the better the solution can be designed. Unfortunately many apps suffer from missing care of the designers regarding functionality. While creating aPod the design process followed these questions:
To differentiate between single Activity / task designs and Activity lifecycles additional questions arise from the interaction and integration of different tasks within the App:
Asking this simple questions and sticking to the Android design guides one can create a decent user experience. Let's see how this has influenced the design of aPod:
The very first design pattern stumbled upon in aPod is the dashboard pattern. It features a screen with title-bar, buttons for the main tasks of the app and a live-area which may contain notifications or other runtime data. Since the answer to the last question to design patterns ("Is there a main task which is superior...") obviously is "Yes, playing music!", one could argue that the already controversial dashboard pattern should not be used in this app. Honestly I spent a lot of time thinking about utilizing the pattern. Just because it feels a little like an antipattern in the first place. It's like having a home screen for an App which introduces a different integration of tasks and disturbs the awaited intuitive handling of an App. Additionally it brings some caveats to Activity lifecycles and app states after a subtask has ended.
At the time I implemented the pattern there were two reasons for doing so:
The dashboard pattern allowed me to uncompress the single tasks and avoid cluttered menus, overloaded screens and unintuitive workflows. Also it was heavily used in well known Apps making it easy for a user to understand and use. This and the fact that the notification area was sufficient to display current played song and provide a quick link to the player controls made my decision clear.
Android 4 introduced this awesome new feature to the mobile platform. At first I was sceptic about it because it destroyed the backwards compatibility or at least took very high effort to keep an App compatible. But with the help of ActionBarSherlock the pattern can be used safely for any App. Due to the acceptable effort porting an app to the new Actionbar pattern I decided to do so. Thus many tasks could be optimized for usability. aPod makes use of the Actionbar pattern on every screen as can be seen in the Media section of the project. It allows to put common options in the header to make them quickly accessible and also integrates well with other patterns like tab navigation. While changing the App to use this pattern I also cleaned up the implementation of the Media Library to use the Actionbar tabs instead of the previously used custom solution switching views. To achieve this I also implemented another Pattern which is more of a problem solution approach than a design pattern: Fragments. Read more about Fragments below in the Programming patterns section.
Various patterns have been used to develop aPod. Some of them are android specific patterns and some others are generic to Java or other languages. In some cases I had to develop own patterns to achieve suitable solutions for given situations or problems. Here are some special
A Fragment is a container which unlike an Activity is not bound to a screen. Fragments can pretty easily be implemented to behave different according to the device context. A good example are list-detail-views which provide a list of datasets and a detail view for each of them. On a mobile device the list would be an own Activity calling another Activity when an item is clicked. On a tablet the detail view can be displayed next to the list without switching Activities.
Before using Fragments I implemented an own boilerplate to handle tab switching. Main reason was that the old Android standard for tabs was awkward to handle and for some reason pretty error prone on some devices. Additionally I had to abstract an own layer of Classes for the Media Library tabs with almost identical functionality but different datasources. The new Fragments allowed me to reduce and enhance the code a lot and optimize the used XML-layouts.
A sectionlist is a list contianing headlines for sections of data. This can be starting letters for alphabetic sorting. Fastscroll enables you to use a drawer to scroll through a large list within one screen (it just scrolls through the sections). This pattern is used a lot through the App. It takes action in the Media Library and Playlists. The special thing here is that I created an own implementation of a ListView called AdvencedList. It reduces the problems you have to face when it comes to the decision in which way to implement a list in Android. There are many ways of doing so for different scales and types of datasources. If you don't have much experience this can be a real hassle. After I watched a presentation about ListViews in Android I decided to take the complex way and integrate the fastscroll from the contact App.
The last problem left was the fact that in landscape mode Lists are very unhandy. There is not much space to scroll the lists and not many Items are visible at once. A way to make this better was to implement the GalleryView which scrolls horizontally and gives new possibilities to display the listitems. With a little effort I eventually managed to create a CoverFlow out of the GalleryView.
To make all this a one time effort I decided to implement AdvancedList which is simpler to configure by handing in a datasource and specifying a renderer for the listitems. Additional attributes allow to configure if the list should be displayed in ListView style or GalleryStyle. The result is now a new View which allows fast and easy setup of big lists with multiple ways of presentation.
For performance reasons AdvancedList implements the ListViewHolder pattern which buffers views for list items and their handles in a static context. I won't explain the details of this pattern here since I consider it common law but implementation details may be taken from the presentation mentioned above.
This is the basic story of aPod. There are a lot more features which could be explained here. But these are the most basic ones. By now aPod has evolved to a much more complex and feature rich player.
If you want to read more about these or other topics please feel free to express your wishes in the comments section below. More Information can also be gathered in the project page of aPod.