Chapter 3: Creating an Android App
In This Chapter
Creating an elementary Android app
Troubleshooting troublesome apps
Testing an app on an emulator or a phone
Dissecting an app
In a quiet neighborhood in south Philadelphia, there’s a maternity shop named Hello World. I stumbled on the store on my way to Pat’s (to get a delicious Philly cheesesteak, of course), and I couldn’t resist taking a picture of the store’s sign.
Computer geek that I am, I’d never thought of Hello World as anything but an app. A Hello World app is the simplest program that can run in a particular programming language or on a particular platform.* Authors create Hello World apps to show people how to get started writing code for a particular system.
* For an interesting discussion of the phrase Hello World, visit www.mzlabs.com/JMPubs/HelloWorld.pdf
.
So I devote this chapter to an Android Hello World app. The app doesn’t do much. (In fact, you might argue that the app doesn’t do anything!) But the example shows you how to create and run new Android projects.
Creating Your First App
A typical gadget comes with a manual. The manual’s first sentence is “Read all 37 safety warnings before attempting to install this product.” Don’t you love it? You can’t get to the good stuff without wading through the preliminaries.
Well, nothing in this chapter can set your house on fire or even break your electronic device. But before you follow this chapter’s instructions, you need a bunch of software on your development computer. To make sure that you have this software and that the software is properly configured, return to Chapter 2 of this minibook. (Do not pass Go; do not collect $200.)
When at last you have all the software you need, you’re ready to start Eclipse and create a real, live Android app.
Starting Eclipse
In this book, almost everything starts with the Eclipse integrated development environment.
1. Launch Eclipse.
For details, see Chapter 2 of this minibook. To read about hundreds of things you can do with Eclipse, see Book II, Chapter 1.
2. If Eclipse shows you its Welcome screen, find that screen’s Workbench icon and then click it to open Eclipse’s main workbench.
For details, see Chapter 2 of this minibook.
3. In the Eclipse workbench, make sure that the Java perspective is active.
Look for the word Java in the upper-right corner of the Eclipse workbench. If you see the word Java
on an indented button (as in Figure 3-1), Eclipse’s Java perspective is active.
Figure 3-1: Eclipse’s Java perspective is active.
For more information about Eclipse perspectives, see Book II, Chapter 1.
4. If the Java perspective isn’t active, choose Window⇒Open Perspective⇒Other⇒Java (Default).
As a result, the Java perspective opens right before your eyes. You’re ready to create an Android app.
Creating a project
To create your first Android application, do the following:
1. In Eclipse’s main menu, choose File⇒New⇒Project.
The New Project dialog box opens.
2. In the New Project dialog box, expand the Android branch. In that branch, select Android Project and then click Next. (See Figure 3-2.)
Figure 3-2: The New Project dialog box.
As a result, Eclipse fires up its New Android Project dialog box. (The top half of the New Android Project dialog box is in Figure 3-3.)
3. In the New Android Project dialog box, type a name for your project in the Project Name field.
In Figure 3-3, I type My First Android Project.
4. In the dialog box’s Build Target panel, select a target.
In Figure 3-3, I select Android 3.0. You can select any target that’s listed, as long as you’ve created an Android Virtual Device (AVD, for short) that can run that target’s projects. For example, an Android 2.3.3 AVD can run projects targeted to Android 2.3.1, Android 2.2, Android 1.6, and so on.
If you mistakenly select a target for which you have no AVD, Eclipse hollers at you when you try to run the project. (While it hollers, Eclipse offers to help you create the necessary AVD.)
For help creating an AVD, see Chapter 2 of this minibook.
5. Find the Properties box of the New Android Project dialog box.
On my computer, with its embarrassingly low screen resolution, the New Android Project dialog box comes with its own scroll bar. To find the Properties box, I have to scroll down to the lower half of the dialog box. (See Figure 3-4.)
Figure 3-3: The top half of the New Android Project dialog box.
6. In the Application Name field, type a name for your app.
In Figure 3-4, I type My First Android App. Whatever name you type appears below your app’s icon in the device’s Apps screen.
7. In the Package Name field, type a name with a valid Java package name.
In Figure 3-4, I type stuff.of.mine. This isn’t the world’s best package name, but it’ll do.
Figure 3-4: The lower half of the New Android Project dialog box.
For the lowdown on Java packages and package names, see Book II, Chapter 2.
Your project and application names may contain blank spaces, but your package name and (in the next step) your activity name must not contain blank spaces. In general, I’m not a fan of blank spaces. They can gum up the works when your software distinguishes the end of one name and the start of the next name. For example, in Windows, the folder name Program Files is a never-ending source of angst for me and other developers. Anyway, my advice is, use blank spaces only where an app’s cosmetics demand blank spaces. If things go wrong, be suspicious of any names with blank spaces.
8. With the Create Activity check box selected, type a name for your application’s main activity.
In Figure 3-4, I type MyActivity. Lazy as I am, I use the name MyActivity
quite often. For your project, you can type the name of any valid Java identifier. Make sure to start with a letter and then include only letters, digits, and underscores (_
).
Your activity is a Java class. So, to adhere to Java’s stylistic conventions, start your activity’s name with an uppercase letter. In the name, don’t include any exotic characters (such as dots, blank spaces, dashes, dollar signs, or pictures of cows).
For the truth about Android’s activities, see Book III, Chapter 1.
9. In the Min SDK Version field, type the number to the far right of whichever target you selected in Step 4.
In Figure 3-4, I type 11 because I find the number 11
at the end of the Android 3.0 target line in the Build Target panel. To find out what you’re promising when you check Android 3.0 and minimum SDK 11, see the nearby “Using Android’s versions” sidebar.
For an overview of Android versions, see Chapter 1 of this minibook.
You can specify a min SDK version with a lower number than the number in the Build Target panel. For example, you can pick Build Target Android 2.3.1 with Min SDK Version 4. When you do this, Eclipse warns you that The API level for the selected SDK target does not match the Min SDK Version.
You can safely ignore this warning.
10. At the bottom of the New Android Project dialog box, click Finish.
As a result, the New Android Project dialog box closes, and the Eclipse workbench comes to the foreground. Eclipse’s Package Explorer tree has a new branch. The branch’s label is the name of your new project. (See Figure 3-5.)
Figure 3-5: The Package Explorer has a MyFirst Android Project branch.
Congratulations! You’ve created an Android application.
Running your project
To kick your new app’s tires and take your app around the block, do the following:
1. Select your app’s branch in Eclipse’s Package Explorer.
(See Figure 3-5.)
2. In Eclipse’s main menu, choose Run⇒Run As⇒Android Application.
As a result, Eclipse’s Console view displays several lines of text. Among these lines, you might find the phrases Launching a new emulator
; Waiting for HOME
; and my personal favorite, Success!
(See Figure 3-6.)
If you don’t see Eclipse’s Console view, you have to coax this view out of hiding. For details, see Book II, Chapter 1.
Figure 3-6: The Console view during the successful launch of an app.
Figure 3-7: Choosing a console in Eclipse’s Console view.
3. Wait for the Android emulator to display a device locked screen, a home screen, or an app’s screen.
First, you see the word ANDROID
as if it’s part of a scene from The Matrix. (See Figure 3-8.) Then you see the word ANDROID
in shimmering, silvery letters. (See Figure 3-9.) Finally, you see Android’s a device locked screen, a home screen, or an app’s screen. (See Figure 3-10.)
Figure 3-8: The emulator starts running.
Figure 3-9: Android starts running on the emulator.
4. I can’t overemphasize this point: Wait for the Android emulator to display a device locked screen, a home screen, or an app’s screen.
Android’s emulator takes a long time to start. For example, on my 2GHz processor with 4GB of RAM, the emulator takes a few minutes to mimic a fully booted Android device. Some people blame the fact that it’s an emulator instead of a simulator. (See Chapter 2 of this minibook.) Others claim that translation of graphics hog the emulator’s time. For whatever reason, you need lots of patience when you deal with Android’s emulator.
5. Keep waiting.
Figure 3-10: The device locked screen for Android 3.0 appears.
While you’re waiting, you might want to visit http://youwave.com
. The people at YouWave have created an alternative to Android’s emulator. The YouWave simulator runs on a Windows PC with a program named VirtualBox (a product from Oracle). YouWave can’t run all Android apps, and I don’t know how faithfully YouWave imitates Android. But one way or another, YouWave looks promising.
Oh! I see that your emulator is finally displaying the device locked screen. It’s time to proceed . . .
6. If the emulator displays the device locked screen, do whatever you normally do to unlock an Android device.
Normally, you slide something from one part of the screen to another. With Android Version 3.0 (pictured in Figure 3-10), you slide the lock from the center to the circumference of a circle.
7. See your app on the emulator’s screen.
Figure 3-11 shows the running of Android’s Hello World app. (The screen even has Hello World
on it.) Android’s development tools create this tiny app when you create a new Android project.
Figure 3-11: Your Hello World app in action.
For this chapter, you use Eclipse to create a project in the earlier “Creating a project” section. But you can create a Hello World project without Eclipse. For details, see Book VI, Chapter 3.
Android’s Hello World app has no widgets for the user to push, and the app doesn’t do anything interesting. But the appearance of an app on the Android screen is a very good start. Following this chapter’s steps, you can start creating many exciting apps.
What if . . .
You try to run your first Android app. If your effort stalls, don’t despair. This section has some troubleshooting tips.
Error message: R cannot be resolved
Every Android app has an R.java
file. Android’s development tools generate this file automatically. So normally, you don’t have to worry about R.java
. Occasionally, the file takes longer than average to be generated. In that case, Eclipse finds references to the R
class in the rest of your project’s code and complains that your project has no R
class. My advice is, wait!
If one minute of waiting doesn’t bring good results, follow these steps to check your project settings:
1. Highlight your project in Eclipse’s Package Explorer.
2. In Eclipse’s main menu, choose Project.
A list of sub-menu items appears.
3. Look for a check mark next to the Build Automatically menu sub-item.
4. If you don’t see a check mark, select the Build Automatically sub-item to add a one.
With any luck your R.java
file appears almost immediately.
If your project is set to Build Automatically, and you still don’t have an R.java
file, try these steps:
1. Highlight your project in Eclipse’s Package Explorer.
2. In Eclipse’s main menu, choose Project.
A list of sub-menu items appears.
3. In Eclipse’s Clean dialog box, select the project that’s giving you trouble along with the Clean Projects Selected Below radio button.
4. Click OK.
Cleaning the project should fix the problem. But if the problem persists, close Eclipse and then restart it. (Eclipse occasionally becomes “confused.”)
Error message: No compatible targets were found
This message probably means that you haven’t created an Android Virtual Device (AVD) capable of running your project. If Eclipse offers to help you create a new AVD, accept it. Otherwise, choose Window⇒Android SDK and AVD Manager to create a new AVD.
The emulator stalls during startup
After five minutes or so, you don’t see Android’s device locked screen or Android’s home screen. Here are several things you can try:
• Lather, rinse, repeat.
Close the emulator and launch your application again. Sometimes, the second or third time’s a charm. On rare occasions, my first three attempts fail, but my fourth attempt succeeds.
• Restart the Android Debug Bridge (adb
) server.
Here’s what you do:
1. Close Eclipse.
2. In a command window, go to your ANDROID_HOME/platform-tools
directory.
To read about your computer’s command window, see Book VI, Chapter 3.
3. In the ANDROID_HOME/platform-tools
directory, type the following two commands:
Windows:
adb kill-server
adb start-server
Macintosh and Linux:
./adb kill-server
./adb start-server
4. Restart Eclipse.
For help finding your ANDROID_HOME/platform-tools
directory, see Chapter 2 of this minibook.
• Switch to an older Android Virtual Device.
In my experience, older AVDs consume fewer resources on your development computer. To change a project’s target AVD, do the following:
1. Close any running emulators.
2. With your project selected in Eclipse’s Package Explorer, choose Project⇒Properties.
A Properties dialog box opens. The Properties dialog box has a tree in its left panel. (See Figure 3-12.)
3. In the Properties dialog box’s tree, select Android.
A form full of options appears in the main body of the Properties dialog box. Among these options is a list of targets. (See Figure 3-12.)
4. Select a new target AVD for your project.
5. Click OK to save the change and dismiss the Properties dialog box.
Wait! You’re not finished yet . . .
6. In your project’s branch of Eclipse’s Package Explorer, double-click the AndroidManifest.xml
file.
Figure 3-12: A project’s Properties dialog box.
Eclipse offers several ways to examine and edit this file.
7. At the bottom of Eclipse’s editor, select the Manifest tab.
Eclipse displays a form like the one shown in Figure 3-13.
8. In the form, click Uses Sdk.
As a result, a set of options appears on the form. This set of options is labeled Attributes for Uses Sdk. (See Figure 3-13.)
9. In the Min SDK Version field, type the number of your project’s new API version.
In Figure 3-13, I type 9, but you can type any of Android’s API version numbers. Just make sure that your min SDK version is no higher than the target you choose in Step 4.
10. Choose File⇒Save to store the new AndroidManifest.xml
file.
You can use these instructions to lower an app’s target and minimum SDK version. But if your app requires features that aren’t available in the lower target or SDK version, you won’t be happy with the results. In the best case, you see an error in Eclipse’s Package Explorer as soon as you make the change. In the worst case, you see no error in the Package Explorer, but your app crashes when it runs.
Figure 3-13: The Manifest tab of a project’s Android Manifest.xml file.
Continuing with my list of things to try if the emulator stalls during startup . . .
• If you have a more powerful computer, try running your app on it.
Horsepower matters.
• Run your app on a phone, a tablet, or some other real Android device.
Testing a brand-new app on a real device makes me queasy. But Android’s sandbox is fairly safe for apps to play in. Besides, apps load quickly and easily on phones and tablets.
For instructions on installing apps to Android devices, see the section “Testing Apps on a Real Device,” later in this chapter.
Error message: The user data image is used by another emulator
If you see this message, some tangle involving the emulator keeps Android from doing its job. First try closing and restarting the emulator.
If a simple restart doesn’t work, try the following steps:
1. Close the emulator.
2. In Eclipse’s main menu, choose Window⇒Android SDK and AVD Manager.
To read about the SDK and AVD Manager, see Chapter 2 in this minibook.
3. In the list of virtual devices, select an AVD appropriate to your project and click Start.
4. In the resulting Launch Options dialog box, select the Wipe User Data check box and then click Launch.
As a result, Android launches a new copy of the emulator, this time with a clean slate.
If the preceding set of steps doesn’t work, take a firmer approach, as follows:
1. Close the emulator.
2. Open whatever file explorer your computer uses to track down files.
3. In your home directory, look for a folder named .android
(starting with a dot).
The name of your home directory depends on your development computer’s operating system.
• On Windows 7 or Windows Vista, your home directory is typically c:Users
your-user-name
.
• On Windows XP, your home directory is typically c:Documents and Settings
your-user-name
.
• On a Mac, your home directory is typically /Users/
your-user-name
.
For example, on my Windows 7 computer, I navigate to c:Users
. From there, I drill down into c:Usersburd
(my home directory), and from there, I drill even further into c:Usersburd.android
.
4. From the .android
directory, drill down even further into the avd
directory.
The avd
directory contains a folder for each AVD that you’ve created.
5. Drill down one level more to the directory for the AVD that’s giving you trouble.
For example, if you were running an AVD named Froyo1 when you saw the data image is used by another emulator
message, navigate to your Froyo1.avd
directory.
6. Inside your AVD’s directory, delete the files named cache.img.lock
and userdata-qemu.img.lock
.
7. Return to the Eclipse workbench and run your app again.
Error message: Unknown virtual device name
Android looks for AVDs in your home directory’s .android/avd
subdirectory, and occasionally Android’s search goes awry. For example, one of my Windows 7 computers lists my home directory on an i
drive. My AVDs are in i:Usersburd.androidavd
. But Android ignores the computer’s home directory advice and instead looks in c:Usersburd
. When Android doesn’t find any AVDs, Android complains.
You can devise fancy solutions to this problem with junctions or symbolic links. But solutions of this kind require special handling of their own. So I prefer to keep things simple. I copy my i:Usersburd.android
directory’s contents to c:Usersburd.android
. That fixes the problem.
Error message: INSTALL_PARSE_FAILED_ INCONSISTENT_CERTIFICATE
This error message indicates that an app that you previously installed conflicts with the app that you’re trying to install. So, on the emulator screen, choose Settings⇒Applications⇒Manage Applications. In the list of applications to be managed, delete any apps that you installed previously.
C:>
adb shell
#
cd data
cd data
#
cd app
cd app
#
rm com.allmycode.menus.apk
rm com.allmycode.menus.apk
#
exit
Your app starts, but the emulator displays a Force Close or Wait dialog box
The formal name for this dialog box is the Application Not Responding (ANR) dialog box. Android displays the ANR dialog box when an app takes too long to do whatever it’s supposed to do. When your app runs on a real device (a phone or a tablet device), the app shouldn’t make Android display the ANR dialog box. (Other chapters in this book give you tips on how to avoid the dialog box.)
But on a slow emulator, a few Force Close or Wait messages are par for the course. When I see the ANR dialog box in an emulator, I usually select Wait. Within about ten seconds, the dialog box disappears and the app continues to run.
Changes to your app don’t appear in the emulator
Your app runs and you want to make a few improvements. So, with the emulator still running, you modify your app’s code. But after choosing Run⇒Run As⇒Android Application, the app’s behavior in the emulator remains unchanged.
When this happens, something is clogged up. Close and restart the emulator. If necessary, use the Wipe User Data trick that I describe in the section “Error message: The user data image is used by another emulator,” earlier in this chapter.
The emulator’s screen is too big
This happens when your development computer’s screen resolution isn’t high enough. (Maybe your eyesight isn’t what it used to be.) This symptom isn’t a deal breaker, but if you can’t see the emulator’s lower buttons, you can’t easily test your app. You can change the development computer’s screen resolution, but adjusting the emulator window is less invasive.
To change the emulator window size, modify the instructions I gave in the “Running your project” section earlier in this chapter just a bit:
1. Follow the steps in Book II, Chapter 1 for creating a run configuration.
2. In the Run Configurations dialog box, click the Target tab.
3. If necessary, scroll down to the bottom of the Target tab.
4. In the Additional Emulator Command Line Options text field, type -scale 0.75.
With the fraction 0.75, the emulator appears at three quarters of its normal size. If three quarters isn’t optimal, change 0.75 to something more suitable.
Testing Apps on a Real Device
You can bypass emulators and test your apps on a phone, a tablet device, or maybe an Android-enabled refrigerator. To do so, you have to prepare the device, prepare your development computer, and then hook together the two. This section describes the process.
1. On an Android device, choose Settings⇒Applications⇒Development.
2. In the Development list, turn on USB debugging.
Here’s what my Honeycomb device displays when I mess with this setting: USB debugging is intended for development purposes. It can be used to copy data between your computer and your device, install applications on your device without notification, and read log data.
On my device, I keep USB Debugging on all the time. But if you’re very nervous about security, turn off USB Debugging when you’re not using the device to develop apps.
3. In your project’s branch of Eclipse’s Package Explorer, double-click the AndroidManifest.xml
file.
Eclipse offers several ways to examine and edit this file.
4. At the bottom of Eclipse’s editor, click the Application tab.
Eclipse displays a form like the one shown in Figure 3-14.
5. In the Debuggable drop-down list, choose True. (Again, see Figure 3-14.)
With Debuggable set to True, your app allows Android’s tools to examine and change things during a run of the app.
The ability to debug is the ability to hack. Debugging also slows down an app. Never distribute an app to the public with Debuggable set to True.
6. Choose File⇒Save to store the new AndroidManifest.xml
file.
7. Set up your development computer to communicate with the device.
• On Windows: Visit http://developer.android.com/sdk/ oem-usb.html
to download your device’s Windows USB driver. Install the driver on your development computer.
Figure 3-14: The Application tab of a project’s Android Manifest.xml file.
• On a Mac: /*
Do nothing. It just works. */
• On Linux: Visit http://developer.android.com/guide/ developing/device.html
and follow the instructions that you find on that page. (Don’t worry. To connect a device, you don’t have to recompile the Linux kernel.)
8. With a USB cable, connect the device to the development computer.
To find out whether your device is connected to the computer, open a command window on the computer. Navigate to the computer’s ANDROID_HOME directory and then type adb devices. (On a Mac or a Linux computer, type ./adb devices.) If your computer’s response includes a very long hexadecimal number, that number represents your connected device. For example, with my Galaxy Tab connected, my computer’s response is
emulator-5554 device
emulator-5556 device
2885046445FF097 device
9. In Eclipse, run your project.
A connected device trumps a running emulator. So if your device’s Android version can handle your project’s minimum SDK version, choosing Run⇒Run As⇒Android Application installs your app on the connected device.
If you need more control over your app’s destination, you can create a run configuration for your project. Book II, Chapter 1 describes run configurations. But if you don’t want to jump to Book II, Chapter 1, choose Run As⇒Run Configurations. In the resulting Target tab, select one of the AVDs in the list.
The Target tab also has a radio button labeled Manual. When you choose Manual, Eclipse offers you a choice of devices. (See Figure 3-15.) To make Eclipse display its Android Device Chooser dialog box, deselect all the AVDs in the Run Configurations dialog box’s Target tab.
Eventually, you want to disconnect your device from the development computer. If you’re a Windows user, you dread reading Windows can’t stop your device because a program is still using it.
To disconnect your device, first issue the adb kill-server
command as described in the “The emulator stalls during startup” section, earlier in this chapter. After that, you get the friendly Safe to Remove Hardware
message.
Figure 3-15: The Android Device Chooser dialog box.
Examining a Basic Android App
If you want to examine an app’s basic building blocks, this chapter’s Hello World app is a good place to start. So with your first project selected in Eclipse’s Package Explorer, take this section’s ten-cent tour.
A project’s files
Figure 3-16 shows some of the directories and files in a simple Android project. When you use Eclipse to create a new project, Android generates all this stuff.
Figure 3-16: The structure of a new Android project.
The project’s directories are src
, gen
, assets
, and res
(and some other stuff that I cover near the end of this chapter).
The src directory
The src
directory contains your project’s Java source code. Files in this directory have names such as MyActivity.java
, MyService.java
, DatabaseHelper.java
, MoreStuff.java
, and so on.
You can cram hundreds of Java files in a project’s src
directory. But when you create a new project, Android typically creates just one file for you. In Figure 3-4 I type the name MyActivity
, so Android creates a file named MyActivity.java
. Listing 3-1 shows you the code in the MyActivity.java
file.
Listing 3-1: Android Creates This Skeletal Activity Class
package stuff.of.mine;
import android.app.Activity;
import android.os.Bundle;
public class MyActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
An Android activity is one “screenful” of components. Think of an activity as a form — perhaps a form for entering information to make a purchase on a website. Unlike most online forms, Android activities don’t necessarily have text boxes — places for the user to type credit card numbers and such. But Android activities have a lot in common with online forms. When you extend the android.app.Activity
class, you create a new Android activity.
An Android application can contain many activities. For example, an app’s initial activity could list the films playing in your area. When you click a film’s title, Android would then cover the entire list activity with another activity (perhaps an activity displaying a relevant film review).
Here’s another (possibly surprising) thing to keep in mind: An Android app can invoke an activity belonging to a different app. For example, your app might display a Help button, and pressing Help might open a web page. With the web page housed somewhere on the Internet, your app’s button fires up an activity belonging to Android’s built-in web browser application. In the Android world, applications don’t Bogart their activities.
Every Android activity has a life cycle — a set of stages that the activity undergoes from birth to death to rebirth, and so on. I describe the activity lifecycle in Book III, Chapter 1. But in this chapter, you get a peek at the activity lifecycle with the method onCreate
in Listing 3-1.
When Android creates an activity, Android calls the activity’s onCreate
method. This happens much more often than you’d think, because Android destroys and then re-creates activities while the user navigates from place to place. For example, if your phone runs low on memory, Android can kill some running activities. When you navigate back to a killed activity, Android re-creates the activity for you. The same thing happens when you turn the phone from portrait to landscape mode. If the developer doesn’t override the default behavior, Android destroys an activity before displaying it in the other mode.
In Listing 3-1, the onCreate
method executes two statements. The first statement, super.onCreate(savedInstanceState)
, calls the parent class’s onCreate
method. The savedInstanceState
variable stores information about the activity’s values the last time the activity was destroyed. With super.onCreate(savedInstanceState)
, the activity takes up where it last left off.
The second method call in Listing 3-1 is setContentView(R.layout.main)
. A call to setContentView
plops a set of buttons, text fields, images, and other stuff on the activity screen. The method parameter, R.layout.main
, is a roundabout way of coding the buttons, text fields, and the way they’re all laid out. For more about this, read the next few sections.
The gen directory
The directory name gen
stands for “generated.” The gen
directory contains R.java
. Listing 3-2 shows the contents of R.java
when you create a brand-new project.
Listing 3-2: Don’t Even Look at This File
/* 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 stuff.of.mine;
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;
}
}
The hexadecimal values in R.java
are the jumping-off points for Android’s resource management mechanism. Android uses these numbers for quick and easy loading of the things you store in the res
directory. For example, the code in Listing 3-1 sets the look of your activity to R.layout.main
, and according to Listing 3-2, R.layout.main
has the hex value 0x7f030000
.
Android’s documentation tells you to put R.java
and its hex values out of your mind, and that’s probably good advice (advice that I break in this section). Anyway, here are two things to remember about the role of R.java
in an Android app:
• You cannot edit R.java
.
Long after the creation of a project, Android continues to monitor (and if necessary, update) the contents of the R.java
file. If you delete R.java
, Android re-creates the file. If you edit R.java
, Android undoes your edit. If you answer Yes in the Do You Really Want to Edit This File? dialog box, Eclipse accepts your change, but immediately after that, Android clobbers your change.
• Many of Android’s predeclared methods expect numbers in R.java
as their parameters.
This can lead to some confusion. Consider the following (very bad) chunk of code:
// THIS IS BAD CODE!
System.out.println(“42”);
System.out.println(42);
TextView textView =
(TextView) findViewById(R.id.textView1);
textView.setText(“42”);
textView.setText(42);
Java’s two System.out.println
calls (rarely used in Android apps) add text to a log file. The first System.out.println
sends the string “42”
to the file, and the second System.out.println
converts the integer value 42
to the string “42”
and then sends the string “42”
to the log file. (Java’s System.out.println
is prepared to print a string, an integer, and various other types of values.)
A call to findViewById
fetches a text view (a place to display text) on your activity’s screen. So in the bad code, textView
refers to a label on the user’s screen. A text view’s setText
method accepts a string parameter or an integer parameter. The call textView. setText(“42”)
is okay. But the integer version of setText
doesn’t convert the integer to a string. Instead, textView.setText(42)
looks for a resource with code number 42 (hex value 0x0000002A
, that is). When Android finds nothing with code number 42 in the res
directory, your app crashes.
The res directory
A project’s res
directory contains resources for use by the Android application. If you look at Figure 3-16, you see that res
has five subdirectories — layout
, values
, and three drawable
directories.
• The drawable
directories contain images, shapes, and other such things.
• The layout
directory contains descriptions of your activities’ screens.
A minimal app’s res/layout
directory contains an XML file describing an activity’s screen. (See the main.xml
branch in Figure 3-16.) Listing 3-3 shows the code in the simple main.xml
file.
Listing 3-3: A Small Layout File
<?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>
An Android app consists of Java code, XML documents, and other stuff. The document in Listing 3-3 describes a vertical linear layout (a layout in which elements appear in a line, one beneath another). Because of its fill_parent
attributes, the layout is large enough to fill its surroundings. Its “surroundings” are the entire screen minus a few doodads.
The only item inside the linear layout is an instance of TextView
— a place to display text on the screen. The text view is wide enough to fill the screen. But because of the wrap_content
attribute, the text view is only tall enough to enclose whatever characters it displays.
The @string/hello
attribute in Listing 3-3 refers indirectly to the words Hello World, MyActivity! in Figure 3-11. Here’s where Android’s resource handling gets interesting. You don’t hard-code character strings into your Java code. Instead, you put character strings in XML documents. To localize your app for French you point to a res/values-fr/strings.xml
file. (Bonjour tout le monde!) To localize your app for Romanian, you point to a res/ values-ro/strings.xml
file. (Salut lume!)
A bare-bones app’s res/values
directory contains a strings.xml
file. (See Figure 3-16.) Listing 3-4 shows the code in a simple main.xml
file.
Listing 3-4: A Small strings.xml File
<?xml version=”1.0” encoding=”utf-8” standalone=”no”?>
<resources>
<string name=
”hello”
>Hello World, MyActivity!
</string>
<string name=”app_name”>My First Android App</string>
</resources>
Listing 3-4 describes a “hello”
string containing the characters Hello World, MyActivity!
. To refer to the “hello”
string in a .java
file, you type R.string.hello. To refer to the “hello”
string in another XML file (such as the file in Listing 3-3), you type “@string/hello”. Either way, you point to the words Hello World, MyActivity!
in Listing 3-4.
The assets directory
When Android packages an app, a tool named aapt (short for Android Asset Packaging Tool) compiles the stuff in the app’s res
directory. In other words, aapt prepares the res
directory’s items for quick retrieval and use. So your application’s access to items in the res
directory is highly optimized.
But plain old Java has its own ways to fetch images and strings. Using Java’s techniques, you generally read byte by byte from the Internet or from a device’s file system. To grab an image or some other data using Java’s standard tricks, put the image or data in the project’s assets
directory.
Other files in an Android project
In Figure 3-16, the tree’s branches include the files proguard.cfg
, default. properties
, and AndroidManifest.xml
.
The file proguard.cfg
contains configuration information for ProGuard, a Java obfuscator program. Obfuscation is a way of making your Java code difficult to understand (which makes the code difficult to steal, difficult to modify, and difficult to infect). To read about ProGuard’s role in Android app development, see Book V, Chapter 1.
The information in the default.properties
file helps automated software keep track of a project’s changes. Programs such as CVS (Concurrent Versions System), Subversion, and Git organize changes when one or more developers contribute updates to a project.
An app’s AndroidManifest.xml
file describes the things a device needs to run the app. (See Listing 3-5.)
Listing 3-5: A Little AndroidManifest.xml File
<?xml version=”1.0” encoding=”utf-8”?>
<manifest xmlns:android=
“http://schemas.android.com/apk/res/android”
package=”stuff.of.mine”
android:versionCode=”1”
android:versionName=”1.0”
>
<uses-sdk android:minSdkVersion=”11”/>
<application
android:icon
=”@drawable/icon”
android:label
=”@string/app_name”>
<activity
android:name=”.MyActivity”
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>
</manifest>
I cover some AndroidManifest.xml
elements in other chapters, and some of the elements in Listing 3-5 are self-explanatory. So in this chapter, I cover only a few of the listing’s highlights.
In the document’s root element, the android:versionCode
and android:versionName
attributes have similar (but slightly different) meanings. The android:versionCode
attribute is an integer. For publication on the Android Market, the android:versionCode
must increase from one version of your app to another. The numbers don’t have to be consecutive. So your first published version can have android:versionCode
47, and the next published version can be number 63. The app’s user doesn’t see the android:versionCode
.
The android:versionName
can be any string of characters, so this attribute’s value is largely cosmetic. The user sees the android:versionName
.
The application
element in Listing 3-5 has two attributes — android: icon
and android:label
. The user sees the application’s icon and label on the device’s Apps screen. The application’s label (and sometimes the icon) appears when one of the app’s activities is in the foreground. (See the words My First Android App and the Android icon in Figure 3-11.)
An app’s activity can have its own icon and label, overriding the app’s icon and label. But in an AndroidManifest.xml
file, an activity element must have an android:name
attribute. The android:name
attribute has either of the following values:
• The fully qualified name of the activity class.
For example, the value of your activity’s android:name
attribute might be com.
yourowndomainname
.MyActivity
. For Listing 3-1, the fully qualified name is stuff.of.mine.MyActivity
.
• The abbreviated activity class name, preceded by a dot.
The name .SomeClass
stands for “the class named SomeClass
in this project’s package.” So in Listing 3-5, the name .MyActivity
stands for stuff.of.mine.MyActivity
.
The manifest
element’s package
attribute isn’t in the android
namespace. In Listing 3-5, I type package, not android:package.
Within an activity
element, an intent-filter
element describes the kinds of duties that this activity can fulfill for apps on the same device. Intent filters consume an entire chapter (see Book III, Chapter 2). So in this section, I don’t dare open the whole intent filter can of worms. But to give you an idea, action android.intent.action.MAIN
indicates that this activity’s code can be the starting point for an app’s execution. And the category android.intent.category.LAUNCHER
indicates that this activity’s icon can appear in the device’s Apps screen.
The android.jar archive
The tree in Figure 3-16 has an Android 3.0
branch, but that branch isn’t a directory on your computer’s file system. In the Package Explorer view, the Android 3.0
branch reminds you that your project’s CLASSPATH includes Android’s predeclared Java code.
The android.jar
file contains code grouped into Java packages, and each package contains Java classes. (Figure 3-17 shows you the tip of the android.jar
iceberg.) The android.jar
file contains classes specific to Android and classes that simply help Java to do its job. Figure 3-17 shows a bunch of Android-specific packages, and Figure 3-18 displays some all-purpose Java packages.
Figure 3-17: Some of the packages and classes in android.jar.
Figure 3-18: The android.jar file includes general-purpose Java packages.
The bin directory
Each Android project has a bin
directory, but Eclipse’s Package Explorer doesn’t display the bin
directory. Android puts the output of its compiling, packaging and other “ing”s in the project’s bin
directory. In particular, the bin
directory stores compiled Java .class
files, doubly compiled Dalvik .dex
files, packaged resource files, and complete .apk
application files.
An APK file contains everything a user’s device needs to know in order to run your app. To install a new app on your Android phone, you download and install a new APK file.