No need to send flowers.
I’ve opted to write an Android “Hello World” tutorial in reverse – rather than start from scratch and progress along to a final product, this tutorial is a teardown of a finished application (albeit a simple one). The goal is to cover a range of fundamental concepts with practical examples.
Installing the app
Firstly, let’s take a look at the app. I’ve made the app publicly available: HelloWorld.apk – download and copy to your phone. You can copy via USB cable, email it to your phone, drop it in via Dropbox / Google Drive… etc.
You’ll need to enable application installs from non-market sources. On your phone, go to Settings -> Security -> Device Administration and click on “Allow installation of apps from sources other than the Play Store”.
Next, navigation to where you’ve saved the file on your phone. Click to install. Done.
Hello World! – We knew him so well
This is a very simple app consisting of 2 screens. The first screen has an editable textbox and two buttons.
Clicking the button “Open Dialog” will launch an alert dialog with the inputted text:
Clicking the button “Open Activity” will open a new screen displaying the inputted text:
What can we learn from this?
In tearing down this app, there are a number of concepts we can cover, such as:
- Designing a front end and the controls available
- Designing a back end that references UI controls
- Simple Navigation
- Multi language support
- Multi resolution support
Better get started then.
I’ve made my source available on github – Android Hello World
Download the file and unzip. Launch Eclipse (see previous blog post), create a new Android application (package com.example.helloworld), and drop the source code in.
MainActivity.java – Summary
This class inherits from the Activity class. An Activity class is the back end code for a front end screen. That is, all screens have an Activity class associated with them.
The method onCreate sets the layout of the screen with a call to setContentView, input parameter R.layout.activity_main.
This input value is easily explained – in the project hierarchy, there is a res/layout folder. In that folder, there is a file: activity_main.xml.
This xml file defines the screen layout. Any xml file dropped into this directory can be referenced in code using the R.layout. prefix.
Before moving on to activity_main.xml, we can see that MainActivity instantiates two buttons and assigns onClick events to them.
To instantiate the buttons, we grab them from the front end using the findViewById method. In the first case, we use the parameter value R.id.btnDialog – this is a unique ID assigned to a control in the XML layout – more on that next.
Screen design can be done by dragging and dropping controls onto a canvas. If you look at the raw XML, you can see that this screen has:
- A TextView (label) with the id “tvQuestion”
- An EditText (editable textbox) with the id “etAnswer”
- A Button with the id “btnActivity”
- A Button with the id “btnDialog”
When you need to reference a control at the back end code, do so via its ID.
There are several styling attributes – these can be set in the raw XML, or in the canvas editor.
Worth noting is the attribute “android:text”. This can be a text value, but in each case, I’ve done something like android:text=”@string/lblOpenActivity”.
This again is an external reference – it says that the text value we want to use is in res/values/strings.xml under the heading lblOpenActivity. Let’s take a look.
This file holds all string variables we wish to use. For the example above, we have the following key-value pair:
<string name=”lblOpenActivity”>Open Activity</string>
If I wanted to provide localisation into Polish, it’s quite straightforward – I just need to create the folder res/values-pl, and a strings.xml file in that folder with the necessary translations:
<string name=”lblOpenActivity”>Otwórz aktywny</string>
Android knows which file to load based on the locale of the device. If an appropriate locale file or key/value pair does not exist, the system will default to the value in the vales/strings.xml file.
In addition to responding to user locale, the application will automatically respond to device resolutions.
The source tree has a number of drawables folders, each one suffixed with a device resolution.
The concept here is each folder contains icons for the appropriate device resolution.
For example, the folder drawable-mdpi has an icon ic_launcher.png. The folder drawable-hdpi has an icon with the same name, but higher resolution.
In code, we merely refer to drawable.ic_launcher – the system will know which resolution to load based on the device.
This file is important in that it defines:
- All Activities in the application (here we have MainActivity and ChildActivity).
- Which Activity is the starting activity (the launcher).
- What is the minimum version of the operating system supported by the app
- The app icon and label
- The version number and name
Note that the app icon id defined as per the drawables section above.
Version number and name – these will be used if you submit to the Play store. The number is an integer and has to increment with each new version you release, and the name is merely a label.
MainActivity.java – Opening Dialogs
Back to MainActivity.java. Have a look at the launchDialog() method. You can see we are extracting the value of the editable textbox and displaying it in a dialog. Nothing complex at all here. We could add additional functionality to the onClick method of the “OK” button if we really wanted to.
MainActivity.java – Opening Activities
Have a look at the launchActivity() method. Here we are getting the value of the editable textbox and passing that as an input parameter to a new screen.
As an analogy, think of a hyperlink with a querystring – not only do we define where to go to, but also the state of the screen.
To launch a new screen, we do so using the Intent class. In the code, we launch an intent for the ChildActivity screen.
We add a key-value pair to the intent using the “putExtra” method, before starting the activity.
In the onCreate method of this Activity, we grab the key-value pairs from launching intent (akin to reading the querystring).
We do so using the getExtras() method:
Bundle extras = getIntent().getExtras();
Then we do a lookup in the bundle:
String input = extras.getString(“input”).
Where “input” was the name of the key used in the previous screen.
This Activity also has a button – clicking it calls the finish() method, which dismisses the activity and returns the user to the previous screen.
Thank you all for coming. Tea and sandwiches will be served back at the family home.