Android Application Basics: Activities and Intents
- Android Application Overview
- Activity Lifecycle
- Multiple Activities
Each Android application is represented by a single Android project. An overview of the project structure, including a brief introduction to the basic building blocks of an application, is provided as useful background information for the recipes in this book. Then the focus of this chapter turns to activities and the intents that launch them.
Android Application Overview
An Android application consists of various functionalities. Some examples are editing a note, playing a music file, ringing an alarm, or opening a phone contact. These functionalities can be classified into four different Android components, shown in Table 2.1, each of which is specified by a Java base class.
Table 2.1. The Four Possible Components of an Android Application
Functionality |
Java Base Class |
Examples |
Focused thing a user can do |
Activity |
Edit a note, play a game |
Background process |
Service |
Play music, update weather icon |
Receive messages |
BroadcastReceiver |
Trigger alarm upon event |
Store and retrieve data |
ContentProvider |
Open a phone contact |
Every application is made up of one or more of these components. They are instantiated by the Android operating system (OS) as needed. Other applications are allowed to use them, too, within the specified permissions.
As multiple functionalities play out in the OS (some not even related to the intended application, such as an incoming phone call), each component goes through a lifecycle of getting created, focused, defocused, and destroyed. The default behavior can be overridden for a graceful operation, such as saving variables or restoring user interface (UI) elements.
With the exception of ContentProvider, each component is activated by an asynchronous message called an Intent. The Intent can contain a Bundle of supporting information describing the component. This provides a method of passing information between components.
The rest of this chapter demonstrates the previous concepts using the most common component: the Activity. Because activities almost always specify an interaction with a user, a window is automatically created with each activity. Therefore, a short introduction to the UI is also included. Of the other components, Service and BroadcastReceiver are covered in Chapter 3, "Threads, Services, Receivers, and Alerts," and ContentProvider is covered in Chapter 9, "Data Storage Methods."
Recipe: Creating a Project and an Activity
A straightforward way to create an Android project or any of its components is to use the Eclipse Integrated Development Environment (IDE). This method ensures proper setup of the supporting files. The steps to create a new Android project are
- In Eclipse, choose File New Android Project. This displays a New Android Project creation screen.
- Fill in the Project name, such as SimpleActivityExample.
- Select a Build Target from the choices provided. These choices are based on the Software Development Kit (SDK) versions that are installed on the development computer.
- Fill in the Application name, such as Example of Basic Activity.
- Fill in the Package name, such as com.cookbook.simple_activity.
- To create the main activity in the same step, be sure Create Activity is checked and fill in an Activity name, such as SimpleActivity.
All activities extend the abstract class Activity or one of its subclasses. The entry point to each activity is the onCreate() method. It is almost always overridden to initialize the activity, such as setting up the UI, creating button listeners, initializing parameters, and starting threads.
If the main activity is not created with the project or another activity needs to be added, the steps to create an activity are
- Create a class to extend Activity. (In Eclipse, this can be done by right-clicking on the project, choosing New Class, and then specifying android.app.Activity as the super class.)
- Override the onCreate() function. (In Eclipse, this can be done by right-clicking on the class file, choosing Source Override/Implement Methods..., and then checking the onCreate() method.)
- As with most overridden functions, it must invoke the super class method, too; otherwise, an exception may be thrown at run-time. Here, the super.onCreate() should be called first to properly initialize the activity, as shown in Listing 2.1.
Listing 2.1. src/com/cookbook/simple_activity/SimpleActivity.java
package com.cookbook.simple_activity; import android.app.Activity; import android.os.Bundle; public class SimpleActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } }
- If a UI is used, specify the layout in an XML file in the res/layout/ directory. Here it is called main.xml, as shown in Listing 2.2.
- Set the layout of the activity using the setContentView() function and passing it the resource ID for the XML layout file. Here, it is R.layout.main, as shown in Listing 2.1.
Listing 2.2. res/layout/main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> </LinearLayout>
- Declare the properties of the activity in the AndroidManifest XML file. This is covered in more detail in Listing 2.5.
Note that the string resources are defined in the strings.xml file in the res/values/ folder, as shown in Listing 2.3. This provides a central place for all strings in case text needs to be changed or reused.
Listing 2.3. res/values/strings.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="hello">Hello World, SimpleActivity!</string> <string name="app_name">SimpleActivity</string> </resources>
Now a more detailed look at the directory structure of this project and the additional auto-generated content is explored.
Directory Structure of Project and Autogenerated Content
Figure 2.1 shows an example project structure, as seen from the Eclipse Package Explorer.
Figure 2.1 Android project directory structure, as seen in the Eclipse IDE.
With the exception of the Android 2.0 library, the project structure is a mix of user-generated and auto-generated files.
User-generated files include
- src/ contains the Java packages the developer writes or imports for the application. Each package can have multiple .java files representing different classes.
- res/layout/ contains the XML files that specify the layout of each screen.
- res/values/ contains the XML files used as references by other files.
- res/drawable-hdpi/, res/drawable-mdpi/, and res/drawable-ldpi/ are directories that contain pictures the application uses. They have high, medium, and low dots-per-inch resolution, respectively.
- assets/ contains additional nonmedia files the application uses.
- AndroidManifest.xml specifies the project to the Android OS.
Autogenerated files include
- gen/ contains autogenerated code, including the generated class R.java.
- default.properties contains project settings. Although autogenerated, it should be kept under revision control.
An application's resources include XML files describing the layout, XML files describing values such as strings, labels of UI elements, and additional supporting files such as pictures and sounds. At compile time, references to the resources are gathered into an autogenerated wrapper class called R.java. The Android Asset Packaging Tool (aapt) autogenerates this file. Listing 2.4 shows what it looks like for the "Creating a Project and an Activity" recipe.
Listing 2.4. gen/com/cookbook/simple_activity/R.java
/* AUTO-GENERATED FILE. DO NOT MODIFY. * * This class was automatically generated by the * aapt tool from the resource data it found. It * should not be modified by hand. */ package com.cookbook.simple_activity; public final class R { public static final class attr { } public static final class drawable { public static final int icon=0x7f020000; } public static final class layout { public static final int main=0x7f030000; } public static final class string { public static final int app_name=0x7f040001; public static final int hello=0x7f040000; } }
Here, each resource is mapped to a unique integer value. In this way, the R.java class provides a way to reference external resources within Java code. For example, to reference the main.xml layout file in Java, the R.layout.main integer is used. To reference the same within XML files, the "@layout/main" string is used.
Referencing resources from within Java or XML files is demonstrated in Table 2.2. Note that to define a new button ID called home_button, the plus sign is added to the identifying string: @+id/home_button. More complete details on resources are given in Chapter 4, "User Interface Layout," but this suffices to cover the recipes in this chapter.
Table 2.2. How Different Resources Are Referenced from Within Java and XML Files
Resource |
Reference in Java |
Reference in XML |
res/layout/main.xml |
R.layout.main |
@layout/main |
res/drawable-hdpi/icon.png |
R.drawable.icon |
@drawable/icon |
@+id/home_button |
R.id.home_button |
@id/home_button |
<string name="hello"> |
R.string.hello |
@string/hello |
Android Package and Manifest File
The Android project, sometimes also referred to as an Android package, is a collection of Java packages. Different Android packages can have the same Java package names, whereas the Android package name must be unique across all applications installed on the Android device.
For the OS to access them, each application must declare its available components in a single AndroidManifest XML file. In addition, this file contains the required permissions and behavior for the application to run. Listing 2.5 shows what it looks like for the "Creating a Project and an Activity" recipe.
Listing 2.5. AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.cookbook.simple_activity" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".SimpleActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> <uses-sdk android:minSdkVersion="3" /> </manifest>
The first line is required and standard across all XML files in Android to specify the encoding. The manifest element defines the Android package name and version. The versionCode is an integer that can be evaluated in programs to determine the upgrade or downgrade relationship. The versionName represents a human readable format that can have major and minor revisions declared.
The application element defines the icon and label the user sees from the Android device menu. The label is a string and should be short enough to display under the icon on a user's device. Generally the name can be up to two words of ten characters each without being cut off.
The activity element defines the main activity that is launched when the application is started and the name shown in the title bar when the activity is active. Here, the Java package name needs to be specified, which is com.cookbook.simple_activity. SimpleActivity in this case. Because the Java package name is usually the same as the Android package name, the shorthand notation is often used: .SimpleActivity. However, it is best to remember that the Android package and Java package are distinct.
The intent-filter element informs the Android system of the capabilities of the component. It can have multiple action, category, or data elements for this purpose. This is seen as it is utilized in different recipes.
The uses-sdk element defines the application programming interface (API) level required to run this application. In general, the API level is specified as follows:
<uses-sdk android:minSdkVersion="integer" android:targetSdkVersion="integer" android:maxSdkVersion="integer" />
Because the Android OS is constructed to be forward compatible, the maxSdkVersion is highly discouraged and not even adhered on devices with Android 2.0.1 or later. Specifying the targetSdkVersion is not required, but allows devices of the same SDK version to disable compatibility settings that might speed up operation. The minSdkVersion should always be specified to ensure the application does not crash when run on a platform that does not support the required features in the application. Always choose the lowest API level possible when specifying this.
The AndroidManifest can also contain permission settings needed to run the application. More complete details about the options are provided in later chapters, but this suffices to cover the recipes in this chapter.
Renaming Parts of an Application
Sometimes a portion of an Android project needs to be renamed. Maybe a file was copied manually into the project, such as from this book. Maybe the application name has changed during development, and it needs to be reflected in the filesystem tree. Automatic tools help with this and ensure cross-references are automatically updated. For example, in the Eclipse IDE, the different ways to rename portions of an application are
- Rename the Android project, as follows:
- Right-click the project and Refactor Move to a new directory in the filesystem.
- Right-click the project and Refactor Rename the project.
- Rename an Android package, as follows:
- Right-click the package and Refactor Rename the package.
- Edit the AndroidManifest.xml to ensure the new package name is reflected.
- Rename an Android class (such as the major components Activity, Service, BroadcastReceiver, ContentProvider), as follows:
- Right-click the .java file and Refactor Rename the class.
- Edit the AndroidManifest.xml to ensure the android:name has the new component name.
Note that renaming other files, such as XML files, usually requires manually changing the corresponding references in the Java code.