Mobile development is something that I have always wanted to try, but I never owned a smart phone and so really had no deep drive to develop mobile applications. This all changed recently when I purchased a Motorola Droid and immediately began playing with the Android OS and developing applications for various purposes; mainly for conference management. I have always hated how I would go to a conference and I would receive a piece of paper of have to check a website to know what sessions happened when. I set out to create an Android app to help me manage the sessions available for the Codemash conference that I attend annually.
Setting up the Environment
The first step for me is always to set up an IDE and as is the case with most non-Microsoft products and technologies, the IDE in use will be Eclipse. I am not an overly big fan of Eclipse, mostly because I have been spoiled by Visual Studio, but it is a very useful tool for developing. Aside from Eclipse you will also need the Android 2.0 SDK which will provide you with the emulator necessary for testing your app. I found this links helpful in walking me through the process of setting things up: http://developer.android.com/guide/developing/eclipse-adt.html
Understanding Android Applications
The first thing to understand about Android apps is they are centered around an Activity. An application can have many activities of differing types. In general you will use a vanilla Activity, but other activity types, such as ListActivity, are also available. The primary functions of the Activity class is the onCreate functions which you will override to perform tasks associated with the app startup. Creating an Android Project in Eclipse you will see your onCreate method defined as such:
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); }
The value being passed into setContentView is actually an integer which maps to a special class called “R” which contains mapped elements from the layout, I will elaborate more on this in the next section.
Understanding the layout
The layouts in Android can be defined in the program if desired but Android also supports defining the layout in XML. By default, Eclipse will create a layout file called main in a directory called “layout” in a special folder called “res”. Now look above at what is being passed to setContentView. A special class called R is maintained by Android which contains references to elements in the view. This makes it easier to references the items in the layout.
The next thing to understand is that everything that can be shown to the user or used to control the structure of the UI is a “view”. TextView for example is used to show text, Button is a view which is used to represent a button, ListView which is a list of items. Views can have IDs which can be added to R and allow them to be easily referenced in the code. LinearLayout is also a view. The important thing to remember when defining your layout in XML is all elements must define a layout_width and a layout_height. If you fail to do this, your application will crash on startup when the content view is loaded.
Understanding Population of ListView
I want to talk about this as it caused a significant amount of pain for me when I was learning it, though looking back I am confused as to why it did, but that is normal I suppose :). So the first thing to understand is if you are from the .NET world, throw what you know away since Android prefers to make the population of a List as complicated as possible.
First you need to have a ListView on the page, as you might expect. Next if your activity does not derive from ListActivity you will need to create an Adapter class. The following is my definition for the adapter I use in my CodeMash app:
public class CustomListAdapter extends BaseAdapter { @Override public int getCount() { return _data.size(); } @Override public T getItem(int position) { return _data.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int index, View renderer, ViewGroup parent) { TextView view = new TextView(this); return view; } }
This example uses generics for the internal list that will be applied to the ListView, but it is not required. Here are some additional things that must be added to the class to make it work.
- Create a constructor that takes as parameters a reference to the Activity that is called it, a parameter to hold the list you are going to bind to the ListView, and finally a reference to the ListView that we are going to bind to.
- The most important thing to do is store references to the Activity and the data internal within the class, as they will be referenced and needed throughout. You must also call the setAdapter method of the ListView reference and pass as a parameter “this”.
You will notice that inheriting from the abstract class BaseAdapter will require the implementation of several abstract methods: getCount, getItem, getItemId, getView. Here is an explanation of these functions:
- getCount()
- This function is responsible for returning the size of the underlying data set
- getItem(int position)
- This function is responsible for returning an object from the underlying data set at a given position
- getItemId(int position)
- This function is responsible for returning an identifier for the selected object at a given position. In most of my examples I just return the position that was passed, depends on if I have a key to pass out.
- getView(int index, View renderer, ViewGroup parent)
- This is the most important function in the adapter, it allows you to define the ItemRow, that is how each item in the dataset is represented in the ListView. Most often you will do this programmatically, though I have been working with XML inflation and that shows promise of removing UI building code from the code, which I think helps forge good separation.
So the basic idea with the adapter is to pass in the data, the activity, and the ListView that you intend to reference and use. You then make a simple call to setAdapter and read your data from within the object creating a view to represent the object for each row in the ListView using the getView method required by the BaseAdapter abstract class.
Conclusion:
My general feelings toward developing on Android are a mixture of annoyance and sheer fun. On the one hand it is nifty to develop applications for a mobile platform and Android has a wide assortment of features to help you. On the other hand, I have never been a fan of Java as it feels like a hack next to C# and the absence of the many native syntax features in Java makes some development difficult. Some of the common things seem more difficult then they should be, but that could be that coming from Silverlight and Xaml, I have a higher expectation for describing layouts through markup.
Overall, I like developing in Java because of how close it is to C# and .NET, and once you get used to the way it does things like events and generics it becomes less about the language and more about the platform, which is the idea.
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }