Having seen the
XML resources that Android uses to launch the application, we can turn to
some Java code that initializes the application. Use Eclipse to open
MicroJobs.java
in the Java editor.
After the package declaration and the import statements, the
MicroJobs class is defined. Most Activities (and the
other activities in this application) extend the Activity class. Because we want to display a map in this application, and
we want to take advantage of the powerful mapping features built into
Android, we declare that MicroJobs will extend MapActivity, as shown in
the following code segment. If you look in the Android documentation for
MapActivity, you will see that it is a subclass of Activity, and so
inherits all the Activity methods and variables:
/**
* MicroJobs
*/
public class MicroJobs extends MapActivity {
Skip over the first few variables and the definition of the
MJOverlay class for the moment, to get to the
definition of the onCreate method, as
shown in the code block that follows. This is the method called by Android
when it first launches an application, so that’s where we’ll put our
initialization code. Let’s take a look at it, section by section:
MapView mvMap;
MicroJobsDatabase db;
MyLocationOverlay mMyLocationOverlay;
double latitude, longitude;
/**
* Called when the activity is first created.
*
* @see com.google.android.maps.MapActivity#onCreate(android.os.Bundle)
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
The first thing to note is that onCreate receives
an argument when it runs: a Bundle that will be referred to as savedInstanceStte. Note also that the first
thing onCreate does is call the
onCreate method of its superclass. That
makes sense because we want the chain of superclasses to initialize
themselves appropriately. But what is this Bundle thing?
A Bundle is one of the mechanisms used by Android to pass structured
data between Activities. It’s just a parcel of key/object pairs,
and you’ll see later when we start another Activity that we have the
option of passing that Activity a Bundle. In the case of MicroJobs, we aren’t going to make use of
any of the resources in the savedInstanceState Bundle, but we
faithfully pass it on to the onCreate
method of our superclass.
The very last line in this section of code sets our Content View. The setContentView call tells
Android that we want to use the layout information in R.layout.main.java to lay out the screen for
the Activity. The
parameters come from our res/layout/main.xml file. Android “inflates”
these parameters when layouts are created, using them to determine how the
layout looks.
So let’s digress for a minute and take a look at the first part of
the XML version of that file:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ffc5d1d4"
>
<com.google.android.maps.MapView
android:id="@+id/mapmain"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true"
android:apiKey="0P18K0TAE0dO2GifdtbuScgEGLWe3p4CYUQngMg"
/>
<TextView
android:id="@+id/lblMicroJobsToday"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="MicroJobs for You Today Near:"
android:textSize="20dp"
android:textColor="#FF000000"
android:layout_centerHorizontal="true"
android:gravity="top"
/>
<Spinner
android:id="@+id/spnLocations"
android:layout_width="250dp"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="2dp"
android:layout_below="@+id/lblMicroJobsToday"
/>
<Button
android:id="@+id/btnShowList"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:text="List Jobs"
android:textSize="20sp"
android:gravity="center_vertical"
android:layout_centerInParent="true"
android:layout_alignParentBottom="true"
/>
</RelativeLayout>
First, we say that we are going to use a Relative Layout for this
screen. Android offers a variety of Layout types, you can even define your own Layout types. A
Relative Layout says that we are going to define the positions of the
different user interface elements by relating their positions to each
other and to the overall screen. That may sound a little vague right now,
but it will be clear when we go into some of the attributes in detail.
The first few lines of code define overall attributes for the screen
layout:
android:orientation
This tells Android which way we want “gravity” to work in
determining the screen layout.
android:layout_width and
android:layout_height
These tell Android that we want to make use of the whole screen;
we aren’t trying to leave room for other Activities to be partially
visible.
android:background
This defines the color of the background for the
application (which isn’t really visible in our case, since the map
covers the whole screen).
This is a good time to talk briefly about defining colors in Android . The color
specification will be familiar to you if you’ve worked with web pages
(although on a web page, the Alpha value is the last item instead of the
first). Colors in Android are defined by a pound sign (#)
followed by four 8-bit integers in hexadecimal:
Alpha The transparency of the resulting color, FF being completely
opaque and 0 being completely transparent.
Red Red’s contribution to the resulting color, FF being fully on
and 0 meaning no red.
Green Green’s contribution to the resulting color, FF being fully
on and 0 meaning no green.
Blue Blue’s contribution to the resulting color, FF being fully
on and 0 meaning no blue.
Common colors are also defined as global constants for use in
Java. |
The rest of the file defines each of the visual elements of the
screen, and tells Android where we’d like it placed.
The following elements of the application are defined in the
file:
Section starting
<com.google.android.maps.MapView
This is the main View for this Activity:a Map that consumes most of the screen and shows the
locations of jobs that might be of interest to the user. You’ll see
that most Views can be described in a layout file by just writing
the name of the View, but this holds only for Views that are part of
Android’s default libraries. MapViews are not included, so we create
an XML element for it. The MapView View is defined in the maps
library, so the full pathname is com.google.android.maps.MapView. We assign
it the following attributes:
android:id
This defines an identifier that we can use to refer to
this View, either from other places in this XML file
or from our Java code. You’ll see later in the Java
initialization code that we connect the Java source code with
this XML source through these IDs.
android:layout_width
and android:layout_height
These are the same attributes defined earlier for the
application, but here they apply to the MapView alone, not the
whole application. The fill_parent value, as its name
suggests, asks for permission to fill all the space
within the parent. In this case the parent happens to be the
whole screen, but it is important to keep in mind that
this attribute affects only the relationship between the
MapView and its parent.
android:clickable
This tells Android that we want an interactive MapView that the
user can click on using the touchscreen on the Android phone
(simulated by mouse clicks on the emulated Android
phone).
android:apiKey
This is an attribute unique to MapViews. You need an API Key from
Google to use a Map View, just as you do when you add a Google
map to your web page.
Section starting <TextView
This will display a Label telling the user what he’s looking
at. The attributes defined here are typical of what needs to be
defined for a TextView. In addition to attributes we already saw
under MapView, this element has:
android:text
This contains the text we’d like to display in the
TextView.
android:textSize
This says how big Android should display the text—in
this case, 20 scaled pixels high (see the upcoming sidebar for
a description of Android dimensions).
android:textColor
This defines the color of the text.
android:layout_centerHorizontal
This tells Android that we want it to center the displayed
text horizontally.
android:gravity
This tells the Android layout manager where to
position the element vertically relative to its container,
when the element is smaller. Gravity can be defined as
top, center_vertical, or bottom. Note that gravity and
attributes like layout_centerHorizontal
are layout hints that the layout manager uses to lay
out the children of a container. There is no guarantee that
the hints will be followed, but the layout manager attempts to
satisfy the combined requests from the container, the children
it contains, and any global layout hints from the user
interface.
There are many other attributes we could define for our
TextView, and they are all described in the Android documentation
that accompanies the SDK.
Section starting <Spinner
This is a standard Android control that allows the user to
select from the current location or any of several “favorite”
locations that are recorded in the user’s profile. In addition to
the attributes we’ve seen already, the android:layout_below attribute controls
the placement of the Spinner. This is the first attribute we’ve seen
that applies specifically to the Relative Layout we chose at the top
of the file. It tells Android that it should position this Spinner
just below the interface element whose id is
lblMicroJobsToday.
Section starting <Button
The final
segment of main.xml defines a
Button widget, which is just what it sounds like—a button that the
user can press to initiate some action. In this case, we want a
button that takes us to the listing of jobs.
android:layout_width
and android:layout_height
These are the same attributes used for the other views,
but we don’t want the Button to take up the whole width of the
screen, so we give it a defined width. Vertically, we just
tell it to wrap the text that it is displaying.
android:text
This places a label on the Button.
android:textSize
This tells Android how large we’d like that text drawn—in this case,
20 scaled pixels.
android:layout_centerInParent
Since the button is not as wide as the parent (the
screen), we need to tell the layout manager where to put the
Button horizontally. This says “put it in the middle.”
android:layout_alignParentBottom
The Button is only tall enough to wrap the label
that it displays, so we also need to tell the layout manager
where to place it vertically on the screen. This says “put it
at the bottom.” Note that we could also have said android:gravity=bottom.
Android provides multiple ways of expressing our layout
requests.
Often you will need to specify a dimension for some element of the user interface. In the example
here we generally used scaled pixels (abbreviated “sp”), but Android
actually offers a rich set of dimensions to choose from:
px (pixels)
If a dimension is set at 10px, it will be exactly 10 pixels long,
no matter what the physical size (and physical density) of the
pixels on the display. 10px will therefore be different sizes on
handset displays with different pixel densities. On a QVGA
display, for example (320×240 pixels), it will be 1/24th of the
height of the display. The same 10px running on a VGA display
(640×480 pixels) will be 1/64th of the height of the
display.
dip or dp (device-independent pixels)
In an effort to make it easier to adapt applications
to different pixel densities, dimensions can be expressed in
device-independent pixels (sometimes also called
“density-independent pixels”). When you specify a dimension of
10dpi, Android will scale the resulting object so it appears the
same size it would appear on a 160dpi screen. For example, if a
640×480 display is 4"×3", its pixel density is 160 dots per inch
(640/4, or 480/3). On that screen, dp’s are the same as px’s. But
if we run the same application on a tablet-size VGA screen—say,
8"×6"—the pixel density is 80dpi, and a dimension given as 10dp
will be twice as large as a dimension given as 10px. The scaling
factor for dp’s is approximate—Android doesn’t try to make dp’s
come out exactly right.
sp (scaled pixels)
Scaled pixels are a lot like dp’s, but they are intended
for elements that need finer control over the density scaling
factor, such as text.
pts (points)
This is used to express text size in points, just as you would
in any text editor. Points are a fixed dimension (roughly 1/72nd
of an inch), so the text will appear the same size on any
display.
in (inches)
This is just what it says: the dimension in
inches.
mm (millimeters)
This is also just what it says, only metric this
time.