The package declaration needs to be the same as the one you used when creating the project. And, like in any other Java project, you need to import any classes you reference. Most of the Android-specific classes are in the android
package:
package com.commonsware.android.skeleton;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import java.util.Date;
It’s worth noting that not every Java SE class is available to Android programs. Visit the Android class reference[7] to see what is and is not available.
Activities are public classes, inheriting from the android.app.Activity
base class. In this case, the activity holds a button (btn
):
public class Now extends Activity implements View.OnClickListener {
Button btn;
A button, as you can see from the package name, is an Android widget, and widgets are the UI elements that you use in your application.
Since, for simplicity, we want to trap all button clicks just within the activity itself, we also have the activity class implement OnClickListener
.
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
btn = new Button(this);
btn.setOnClickListener(this);
updateTime();
setContentView(btn);
}
The onCreate()
method is invoked when the activity is started. The first thing you should do is chain upward to the superclass, so the stock Android activity initialization can be done.
In our implementation, we then create the button instance (new Button(this)
), tell it to send all button clicks to the activity instance itself (via setOnClickListener()
), call a private updateTime()
method (discussed in a moment), and then set the activity’s content view to be the button itself (via setContentView()
).
All widgets extend the View base class. We usually build the UI out of a hierarchy of views, but in this example we are using a single view.
I discuss that magical Bundle icicle
in Chapter 16. For the moment, consider it an opaque handle that all activities receive upon creation.
public void onClick(View view) {
updateTime();
}
In Swing, a JButton
click raises an ActionEvent
, which is passed to the ActionListener
configured for the button. In Android, a button click causes onClick()
to be invoked in the OnClickListener
instance configured for the button. The listener is provided the view that triggered the click (in this case, the button). All we do here is call that private updateTime()
method:
private void updateTime() {
btn.setText(new Date().toString());
}
When we open the activity (onCreate()
) or when the button is clicked (onClick()
), we update the button’s label to be the current time via setText(), which functions much the same in Android as JButton
does in Swing.
Building and Running the Activity
To build the activity, either use your IDE’s built-in Android packaging tool, or run ant in the base directory of your project. Then, to run the activity do the following:
1. Launch the emulator (e.g., run tools/emulator
from your Android SDK installation), as shown in Figure 4-1.
Figure 4-1. The Android home screen
2. Install the package (e.g., run tools/adb install /path/to/this/example/bin/Now.apk
from your Android SDK installation).
3. View the list of installed applications in the emulator and find the Now application (see Figure 4-2).
Figure 4-2. The Android application “launcher”
4. Open that application.
You should see an activity screen like the one shown in Figure 4-3.
Figure 4-3. The Now demonstration activity
Clicking the button — in other words, clicking pretty much anywhere on the phone’s screen — will update the time shown in the button’s label.
Note that the label is centered horizontally and vertically, as those are the default styles applied to button captions. We can control that formatting, which Chapter 6 covers.
After you are done gazing at the awesomeness of Advanced Push-Button Technology, you can click the back button on the emulator to return to the launcher.
CHAPTER 5
Using XML-Based Layouts
While it is technically possible to create and attach widgets to our activity purely through Java code, the way we did in Chapter 4, the more common approach is to use an XML-based layout file. Dynamic instantiation of widgets is reserved for more complicated scenarios, where the widgets are not known at compile-time (e.g., populating a column of radio buttons based on data retrieved off the Internet).
With that in mind, it’s time to break out the XML and learn how to lay out Android activities that way.
What Is an XML-Based Layout?
As the name suggests, an XML-based layout is a specification of widgets’ relationships to each other — and to their containers (more on this in Chapter 7) — encoded in XML format. Specifically, Android considers XML-based layouts to be resources, and as such layout files are stored in the res/layout
directory inside your Android project.
Each XML file contains a tree of elements specifying a layout of widgets and their containers that make up one view hierarchy. The attributes of the XML elements are properties, describing how a widget should look or how a container should behave. For example, if a Button
element has an attribute value of android:textStyle = "bold"
, that means that the text appearing on the face of the button should be rendered in a boldface font style.
Android’s SDK ships with a tool (aapt
) which uses the layouts. This tool should be automatically invoked by your Android tool chain (e.g., Eclipse, Ant’s build.xml
). Of particular importance to you as a developer is that aapt
generates the R.java
source file within your project, allowing you to access layouts and widgets within those layouts directly from your Java code.
Why Use XML-Based Layouts?
Most everything you do using XML layout files can be achieved through Java code. For example, you could use setTypeface()
to have a button render its text in bold, instead of using a property in an XML layout. Since XML layouts are yet another file for you to keep track of, we need good reasons for using such files.
Perhaps the biggest reason is to assist in the creation of tools for view definition, such as a GUI builder in an IDE like Eclipse or a dedicated Android GUI designer like DroidDraw[8]. Such GUI builders could, in principle, generate Java code instead of XML. The challenge is re-reading the UI definition to support edits—that is far simpler if the data is in a structured format like XML than in a programming language. Moreover, keeping generated XML definitions separated from hand-written Java code makes it less likely that somebody’s custom-crafted source will get clobbered by accident when the generated bits get re-generated. XML forms a nice middle ground between something that is easy for tool-writers to use and easy for programmers to work with by hand as needed.