Although this site has been focused on iOS development so far, I thought you guys might enjoy learning a bit about Android development as well. So iOS tutorial team member Ali Hafizji has put together this great tutorial on Android development for beginners!
I had never programmed for Android before, but bought myself a device and used this tutorial as my first introduction to the platform. Now that I have a simple app running on my device I’m excited and eager to learn more, and I hope you guys will feel the same way! :]
This is a blog post by iOS Tutorial Team member Ali Hafizji, an iOS and Android developer living in India.
Since I’ve been following this blog, I’ve never read a post related to Android application / game development. So I thought writing something in that area would be helpful to any beginner :]
Android is an amazing and fun platform to work on. Anyone can come up with their own unique idea, create a good product and make it available to thousands and thousands of customers.
In this tutorial, we will create a “Hello World” Android app, get it working on the emulator or a device if you have one, and create a simple master/detail app that shows a list of quotes by our favorite hero, Steve Jobs. I’ll even show you how to build the app for distribution on the Google Market!
And yes, it is a little ironic to make a Steve Jobs quote app on an Android device, but hey this is mainly an iOS blog after all ;]
So keep reading to dive into the wild world of Android!
So Many Devices!
Anyone who wants to buy an android device has a large variety to choose from. There are more than 300 android devices in the market each with their own hardware features. If your primary concern is development, get the best phone that matches the lowest API level that you wish your software to support, so you can test with it. Use the emulator to test other API levels. If your primary concern is having a good phone, get the best phone and use the emulator to test other API levels.
For app development, it doesn’t really matter which phone you get aside from API levels, for game development you might want the slowest phone that you intend to support so you are forced to write efficient code.
Considering all this if you want to buy a phone for software development I recommend buying the Samsung Galaxy Ace, Htc Wildfire S, or Motorola Droid X2. Any should meet your development needs, and you can pick up a fairly inexpensive used one from the links above.
However if you’re looking for the latest and greatest, I recommend Google’s new Galaxy Nexus. This just came out in December and is one of the most powerful devices out there, and is running the latest version of Android (Ice Cream Sandwich).
Note from Ray: I ended up purchasing a used Motorola Droid X2 for about $150. I chose this device because I wanted something cheap for testing purposes, and didn’t want to pay a monthly contract. I hooked up the phone to my local Wi-fi network (bypassing the activation screen by tapping the upper left, upper right, bottom right, and bottom left of the screen where it says to tap the android). I was successfully able to use this device to go through the tutorial.
Setting Things Up
Before we start with the installation process first verify that your computer meets the basic system requirements. If you’re on a mac like me make sure you have Mac OS 10.5.8 or later (x86 only).
Step 1: Verify JDK is installed
The first step is to check if you have the JDK (Java development kit) installed. Mac’s usually come with the JDK preinstalled and ready to use.
To check what version of the JDK you have open up a terminal and type in the command “which java”. Go to the directory that is printed and enter the command “java –version”. Here is what the output looks like:
If for some reason you do not have Java installed, you can download and install it from Oracle.com.
Step 2: Download Eclipse
The next step is to download eclipse (the classic version is recommended). You can download it fromhttp://www.eclipse.org/downloads
Step 3: Download the Android SDK
You can download the Android SDK from http://developer.android.com/sdk/index.html and unpack it. Note you may want to put your Android SDK in a safe spot since you’ll be using it a lot.
Once done, go to the tools folder and double click the android executable. This will open the Android SDK and AVD manager.
Step 4: Download Packages
Click on Available packages this will show a list of all the available Android SDK’s. Download an SDK that you want to build your app for.
To choose an SDK based on your device, go to Settings\About phone\Android version to see the version your phone is running. Then choose an SDK that is the same version as your device or earlier.
Step 5: Install ADT plugin
Next we need to setup the ADT plugin. To do this start eclipse go to Help > Install new software. Click Add on the top right corner
Enter the following URL: https://dl-ssl.google.com/android/eclipse/ Check developer tools, click Next, and walk through the wizard to install the tools.
After you restart Eclipse, it will prompt you for the Android SDK installation directory. Select “Use existing SDKs” and browse to the directory where you downloaded the Android SDK, and finish the wizard.
That’s it! You have successfully setup your development environment.
Note: Some of the above steps may not work if you’re not a Mac user. If that’s the case please find the detailed steps here: http://developer.android.com/sdk/installing.html
Hello Android!!
Assuming you have successfully installed everything, its time to create your first android project.
Step 1: Creating the project
- Start eclipse
- Go to File > New > Other > Android and select Android Project. You should see the following popup screen (yours may be slightly different or split into several steps):
- Enter all the details as I have. Here is a brief explanation of each field:
- Project name is the name of the directory that contains the project files (name it QuoteReader because that’s what we’ll make).
- Build target specifies which version of Android the application is built for. I’ve selected 2.2, which is Froyo.
- The properties elements are self explanatory except for the MIN SDK property. This is used for backward compatibility i.e. if your application requires a minimum api level, or is designed only to support a certain range of Android platform versions. Setting this to a value ensures that your application can only be installed on devices that are running a compatible version of the Android system.
Okay! Now that you have entered all the details press next. Eclipse will now create the project, which you can see in your project navigator.
Step 2: Understanding the project structure
Before we get started with any code lets spend some time going through the project structure.
Here is a brief description of the folders present:
- Source (src): This folder contains all the source files i.e. this is where all the code is.
- Res: This is the area where you keep your images, strings and xml layouts.
- Assets: This is another place where you can keep files. The difference between /res and /assets is that Android does not generate IDs for the assets. What this means is that to access a file in assets the developer has to provide a complete path to that file.
Now that you have a basic understanding of the project structure, lets run the application.
Step 3: Running the application
There are two ways in which we can run the application either on an actual device or on an emulator. I will explain how to do both very briefly.
To run the application on the emulator we first need to create an AVD (Android virtual device). This is an instance of the android emulator. To do this, follow these steps:
- Go to Window > Android SDK & AVD Manager and click New in the top right corner.
- Enter all the required details.
- Click on “Create AVD”, after that you can start the emulator by just selecting it from the AVD manager and clicking on start.
After the emulator starts up you can run the application that you just created. To do this right click on the project, go to Run As and select Android Application. This will launch the app on the emulator.
Running the application on the device is fairly simple and requires very little effort. Here are the steps to launch an app on the device:
- On your device, to to Settings\Application\Development and select the checkbox next to USB debugging.
- Connect the device to your computer with a USB cable.
- Run the project through eclipse. You will see the following popup:
- Select the device and you’re app will be deployed.
Note: Notice that the popup above shows two options; the reason being I already have an emulator running hence I need to choose where to deploy the app i.e. either on the emulator or the device.
Creating a Simple and Easy App
The current state of the application is quite raw and we haven’t yet added anything to the default project. So lets try and build something small but useful.
In this part of the tutorial we will build a tiny application. The idea is to build a quote reader. The quotes will be displayed in a list and when the user clicks on an item the app will navigate to a detailed page containing a picture and the quote.
The first screen contains a list with quotes and thumbnails. Lets start by creating the UI for this.
Step 1: Adding the list view
If you’re coming from the iOS development world, you’re familiar with using Interface Builder to graphically layout an interface. However, because Android supports so many different devices with different screen sizes, creating user interfaces is completely different.
Instead of visually dragging and dropping UI elements to a canvas, you need to define your UI in XML (yes, you read that right!). You’ll add XML tags for the views you want (like buttons, labels, etc.) and add XML attributes for parameters like position, color, etc.
Eclipse does come with a visual editor where you can drag drop UI elements, but I highly recommend editing the XML directly instead as this will give you a stronger grip over your view hierarchy.
In this tutorial, we’ll show you exactly what to input in the XML to set up the UI, but if you want to read about how it all works, check out Android’s XML layout guide here.
Now lets open the main.xml file from the res/layout directory. If the graphical layout view appears, select the main.xml tab to edit raw xml. Then replace the content with the following:
<?xml version="1.0" encoding="utf-8"?> <ListView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/quotes_list" android:layout_width="fill_parent" android:layout_height="fill_parent" > </ListView> |
This will create a list view with a width and height equal to the size of the screen.
Next we need to show this layout to the user, to do this open QuoteReaderActivity.java present in the source directory. You will notice that this class extends a class named Activity. In Android anything that the user interacts with is an activity, the activity is responsible for showing the user content which is present in different views.
Notice that a method called onCreate is overridden and in it a method called setContentView is called. This sets the content of this activity with views present in the xml file passed to it.
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } |
The “R” class present above is used to refer to the resources present in the /res folder. Here’s a screenshot of the contents of this folder of this project:
The “R” class is automatically generated to contain properties for the resources that you put into this folder. For each type of resource, there is an “R” property (for example R.layout for all the layout resources) and for each resource of that type there is a static integer (for example R.layout.main). This integer is the resource ID that you can use to retrive that resource.
This is the xml file in which we just added the list view. Hence when the QuoteReader activity is started it will create our list view.
Go ahead and run your application you should see a blank screen. This is because we haven’t yet added any rows to our list view.
Step 2: Adding rows to the list
In this step we will create rows and add them to our list. We know that the row needs to have a thumbnail and text.
Here is how the row is going to look:
Lets start by creating the layout for the row. Create a new xml file in the res/layout directory and name it “list_item_layout.xml”. Open it in the raw XML view and replace the contents with the following:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="100dip" > <ImageView android:id="@+list/thumb" android:layout_width="60dip" android:layout_height="60dip" android:layout_centerVertical="true" android:layout_alignParentLeft="true" /> <TextView android:id="@+list/text" android:layout_toRightOf="@+list/thumb" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="18dip" android:layout_marginLeft="10dip" android:layout_centerVertical="true" android:singleLine="true" android:ellipsize="end" android:textStyle="bold" /> </RelativeLayout> |
This creates an ImageView for the thumbnail and a TextView for the quote.
Note that we give the ImageView and TextView an ID. An ID is used to uniquely identify a view within a view hierarchy. The syntax is funky here so let’s explain it bit by bit:
- The at-symbol(@): You put this at the beginning, and it indicates that the XML parser should parse and expand the rest of the ID string and identify it as an ID resource.
- The plus-symbol(+): This means that this is a new resource name and that must be created and added to our resources.
- How to use: After the app is compiled you will be able to refer to this view using “R.list.text”.
Notice that the parent view used in this layout is a RelativeLayout. This layout allows you to position its children relative to each other and itself. The ImageView needs to be placed to the left of the layout and it needs to be centered vertically hence those properties are set to true. Also the TextView needs to contain text in a single line and if the length increases it should ellipsize, therefore the single line and ellipsize properties are set.
Now that we have the UI in place, lets add some code so that we can use it for each list item.
Step 3: Understanding adapters and data sources
Okay lets take a brief pause and let me try and explain how a list view is populated with data. Data is present in something known as a data source this is the object that provides the data that will populate the list view. This is usually just a subclass of NSObject – think of it as your app’s model.
An adapter sits between the data source and the list view. It provides the list with data from the data source and refreshes the list items when a scroll occurs.
Android has two standard adapters, ArrayAdapter and CursorAdapter. You can also develop your own adapter by extending these classes or the BaseAdapter class. We will be extending the BaseAdapter class later on in this tutorial, but let’s create the data source first.
Step 4: Creating the data source
First copy all the images that are provided here in your drawable directory. If you don’t have a drawable directory, go ahead and create it. The drawable directory basically should contains items that can be drawn to the screen. The resources that you place here can be referenced through the “R” class. For example “R.drawable.icon” would refer a resource name icon in the drawable folder.
Next, download the quotes we’ll be using for the project and add them into your res/values/strings.xml file. The reason why I added strings to an xml file and not use them directly in code is because I like to keep my resources separate, also this helps a lot when you’re localizing strings. Again you can refer the strings placed here using the same “R” class, for example “R.string.quote_1″ would refer the quote_1 string.
Add the quotes to the file according to the following syntax:
<string name="quote_1">Innovation distinguished between a leader and a follower</string> <string name="quote_2">I want to put a ding in the universe!</string> <string name="quote_3">People don\'t know what they want until you show it to them.</string> <!-- add rest of quotes, up to quote_10 --> |
Notice that you have to precede any single quotes with a backslash.
Now that we have all the data, lets create our data source class. Right click on your src folder goto New and select Class. Name it DataSource, make sure the Package is set to whatever package QuoteReaderActivity.java is part of, and press finish. Add the following lines of code to it:
private ArrayList<Integer> mPhotoPool; private ArrayList<Integer> mQuotePool; private ArrayList<Integer> mPhotoHdPool; public ArrayList<Integer> getmPhotoHdPool() { return mPhotoHdPool; } public ArrayList<Integer> getmPhotoPool() { return mPhotoPool; } public ArrayList<Integer> getmQuotePool() { return mQuotePool; } public DataSource() { mPhotoPool = new ArrayList(); mQuotePool = new ArrayList(); mPhotoHdPool = new ArrayList(); } |
All that we have done here is create 3 variables, generated their getter methods, and initialized the variables in the constructor.
If you get warnings that it can’t find ArrayList, simply go to Source\Organize Imports to have Eclipse automatically add the import you need to the top of the file. You can do this same thing whenever you get warnings on missing imports later on in this tutorial as well.
Next we need to populate the array lists with our data, which are the pictures and the quotes. Notice that we have defined our array list to contain integers. The reason for this is when you drop any resource into the resource directory the build system creates a unique identifier for it which is represented by an integer.
Okay now lets create 3 separate functions to populate our ArrayLists. Add the following functions above the constructor definition.
private void setupPhotoPool() { mPhotoPool.add(R.drawable.steve_1); mPhotoPool.add(R.drawable.steve_2); mPhotoPool.add(R.drawable.steve_3); mPhotoPool.add(R.drawable.steve_4); mPhotoPool.add(R.drawable.steve_5); mPhotoPool.add(R.drawable.steve_6); mPhotoPool.add(R.drawable.steve_7); mPhotoPool.add(R.drawable.steve_8); mPhotoPool.add(R.drawable.steve_9); mPhotoPool.add(R.drawable.steve_10); } private void setupQuotePool() { mQuotePool.add(R.string.quote_1); mQuotePool.add(R.string.quote_2); mQuotePool.add(R.string.quote_3); mQuotePool.add(R.string.quote_4); mQuotePool.add(R.string.quote_5); mQuotePool.add(R.string.quote_6); mQuotePool.add(R.string.quote_7); mQuotePool.add(R.string.quote_8); mQuotePool.add(R.string.quote_9); mQuotePool.add(R.string.quote_10); } private void setupPhotoHDPool() { mPhotoHdPool.add(R.drawable.steve_hd_1); mPhotoHdPool.add(R.drawable.steve_hd_2); mPhotoHdPool.add(R.drawable.steve_hd_3); mPhotoHdPool.add(R.drawable.steve_hd_4); mPhotoHdPool.add(R.drawable.steve_hd_5); mPhotoHdPool.add(R.drawable.steve_hd_6); mPhotoHdPool.add(R.drawable.steve_hd_7); mPhotoHdPool.add(R.drawable.steve_hd_8); mPhotoHdPool.add(R.drawable.steve_hd_9); mPhotoHdPool.add(R.drawable.apple_hd); } |
Each of these functions is filling in data into our ArrayLists. Call these functions in the constructor like so:
setupPhotoPool(); setupQuotePool(); setupPhotoHDPool(); |
We will also add another function for the size of the data source. In our case the size of the data source is 10 i.e. we have 10 images and 10 quotes hence we can simply return the size of any one of our ArrayLists.
Add the following function above the constructor:
public int getDataSourceLength() { return mPhotoPool.size(); } |
That’s all we need. Next we need to use this data source and populate our list.
Step 5: Creating the adapter
Open QuoteReaderActivity.java from the src folder and create a private class, name it QuoteAdapter. This class should inherit from the BaseAdapter class and it should implement all the abstract methods with minimal implementations.
Here’s what the class should look like now:
public class QuoteReaderActivity extends Activity { public class QuoteAdapter extends BaseAdapter { @Override public int getCount() { return 0; } @Override public Object getItem(int arg0) { return null; } @Override public long getItemId(int arg0) { return 0; } @Override public View getView(int arg0, View arg1, ViewGroup arg2) { return null; } } /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } } |
Lets try and understand what each method does.
- getCount(): Returns the number of items present in the data set.
- getItem(int position): Gets the data item associated with the specified position in the data set.
- getItemId(int position): Gets the row id associated with the specified position.
- getView( int position, View convertView, ViewGroup parent): This is used to get a view that displays the data at the specified position in the data set.
Now that we have a basic understanding of all the functions lets add a constructor to our adapter and some private variables. Add the following lines of code to the QuoteAdapter class:
private Context mContext; private LayoutInflater mInflator; private DataSource mDataSource; public QuoteAdapter(Context c) { mContext = c; mInflator = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); mDataSource = new DataSource(); } |
The only new variable here is the mInflator variable this is used to instantiate layout XML file into its corresponding View objects.
Next change all the overridden functions as follows:
@Override public int getCount() { return mDataSource.getDataSourceLength(); } @Override public Object getItem(int position) { return position; } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ImageView thumbnail; TextView quote; if(convertView == null) { convertView = mInflator.inflate(R.layout.list_item_layout, parent, false); } thumbnail = (ImageView) convertView.findViewById(R.list.thumb); thumbnail.setImageResource(mDataSource.getmPhotoPool().get(position)); quote = (TextView) convertView.findViewById(R.list.text); quote.setText(mDataSource.getmQuotePool().get(position)); return convertView; } |
The main function here is the getView function, since it is called for every item in the list view. It is responsible for binding the data source with the list view item.
In it we first check if the convert view is null, the reason we do this is to check if the convertView returned is not a recycled view. The adapter does not create a new view for each and every item instead it creates a set number of views and reuses them as the users scrolls through the list. This is similar to how a UITableView reuses table view cells in iOS.
Once this is done we get a reference to our image view and text view and fill it with data from our data source. The position variable returned is used as an index in the data source.
Step 6: Getting things together
We now have our adapter and data source set we just need to tell our list view to start using our adapter. Add the following private variable to QuoteReaderActivity:
private ListView mListView; |
Then add the following lines in the onCreate method:
mListView = (ListView) findViewById(R.id.quotes_list); mListView.setAdapter(new QuoteAdapter(this)); |
That’s it! Now run the application, and you should see a screen like this:
Congrats! You have made a simple Android app that shows thumbnails of the famous Steve Jobs and his most famous quotes.
Constructing a Detail Page
Next we want to extend our app a bit so you can tap a quote to see it in full detail. It will show a large size picture and the quote written at the bottom.
Step 1: Creating the UI
Lets begin with creating the layout for this screen. Create a new xml file in the res/layout directory and name it “quote_detail.xml”. Add the following lines to the file:
<?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" > <RelativeLayout android:layout_width="fill_parent" android:layout_height="fill_parent"> <ImageView android:id="@+detail/image" android:layout_alignParentTop="true" android:layout_width="fill_parent" android:layout_height="350dip" android:layout_marginLeft="5dip" android:src="@drawable/steve_1" /> <TextView android:id="@+detail/quote" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_below="@detail/image" android:textSize="24dip" /> </RelativeLayout> </ScrollView> |
Here notice that the root view is a scroll view and it has only one child, which is a relative layout. This relative layout contains our image view for the picture and text view for the quote.
The reason why a scroll view is used is since the quote could be long there is a possibility that it might go of the screen. A scroll view is smart enough to understand when its child view is bigger than the screen size and will automatically give you a scroll bar to scroll down.
Step 2: Adding the Quote Detail activity
Lets add the Quote detail activity this is responsible for presenting the quote_detail.xml layout to the user.
First create a new class and name is QuoteDetail, make sure that it extends Activity. Override the onCreate function and set the content of the activity to quote_detail.xml. At this point QuoteDetail.java should look like the following:
public class QuoteDetail extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.quote_detail); } } |
Step 3: Connecting two activities
An activity in android is instantiated with an Intent, the details of an intent are not in the scope of this tutorial. But all you need to know is that an Intent is used to start an activity.
In QuoteReaderActivity.java add the following at the end of your onCreate function.
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView arg0, View arg1, int position, long arg3) { Intent i = new Intent(QuoteReaderActivity.this, QuoteDetail.class); i.putExtra("position", position); startActivity(i); } }); |
What we are doing here is fairly straightforward. We are setting an item click listener and every time an item is clicked we create an Intent.
Notice that we pass the position variable to the intent, this is used to represent the position in the data source for the item clicked.
Next add the following lines in QuoteDetail.java:
private ImageView mImageView; private TextView mQuote; private int mPosition; private DataSource mDataSource; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.quote_detail); Intent i = getIntent(); mPosition = i.getIntExtra("position", 0); mDataSource = new DataSource(); mImageView = (ImageView) findViewById(R.detail.image); mQuote = (TextView) findViewById(R.detail.quote); mImageView.setImageResource(mDataSource.getmPhotoHdPool().get(mPosition)); mQuote.setText(getResources().getString(mDataSource.getmQuotePool().get(mPosition))); } |
As you can see we retrieve the position sent by the QuoteReader activity from the intent and use that to fill in the image view and the text view.
One last thing we need to do before you can run the application is to add an entry for this activity in your manifest. Lets not get into the details of the manifest but take it as a thumb rule to always add any new activity to the manifest.
So add this line to the manifest (AndroidManifest.xml):
<activity android:name=".QuoteDetail" android:screenOrientation="portrait"> </activity> |
Now its time to finally run the application. You should have a complete working app with both a master and detail view!
Uploading to the Android Market
Before I end the tutorial, I wanted to write down the steps to follow to upload an application to the android market. Here is a brief step-by-step guide:
- First you need to get yourself a developer license by signing up here. Its costs an affordable $25 to get one.
- Next you need to obtain a suitable private key. This key will be used to sign your application. To do this use the keytool command, enter the following command in a terminal:
keytool -genkeypair -v -keystore YOUR_KEY_NAME.keystore -alias YOUR_ALIAS_NAME -keyalg RSA -keysize 2048 -validity 10000
- Running the example command as above, Keytool prompts you to provide passwords for the keystore and key, and to provide the Distinguished name fields for your key. It then generates the keystore as a file called YOUR_KEY_NAME.keystore. The keystore and the key are protected by passwords you entered.
- Now you need to compile our application in release mode. In eclipse right click on the project and select Android Tools\Export Signed Application Package. Then specify the keystone and password information you set up previously.
- That’s all; your APK is ready to upload to the android market!
More information on Android
- Here are a few blogs that I think have real solid content:
- Videos: Once you think that you have a basic grasp on android, the Google I/O videos are a great source.
- Books: I personally started off with Professional Android Application Development by Retro Meier and I strongly recommend it for any beginner. Another highly recommended option is the set of books by CommonsWare, such as this one.
Where to go from here
Here is the complete example project with all the code from the above tutorial.
At this point, you should have a very basic understanding of how things work in the Android world. This should give you a good start to explore and create amazing apps.
You’re ready to move on to the next part in this series on Android development, which will take you through some major improvements to the QuoteReader project. Along the way, you’ll learn more key Android concepts.
If you have any questions, comments, or suggestions, please join in the forum discussion below!
0 comments:
Post a Comment