Running and Debugging Android Applications

Once we've written the first iteration of our application code, we want to run and test it to identify potential problems or just be amazed at its glory. We have two ways we can achieve this:

We can run our application on a real device connected to the development PC via USB.

We can fire up the emulator that is included in the SDK and test our application there.

In both cases we have to do a little bit of setup work before we can finally see our application in action.

Connecting a Device

Before we can connect our device for testing purposes, we have to make sure that it is recognized by the operating system. On Windows, this involves installing an appropriate driver, which is part of the SDK installation we installed earlier. Just connect your device and follow the standard driver installation project for Windows, pointing the process to the driver/ folder in your SDK installation's root directory. For some devices, you might have to get the driver from the manufacturer's web site.

On Linux and Mac OS X, you usually don't need to install any drivers, as these come with the operating system. Depending on your Linux flavor, you might have to fiddle with your USB device discovery a little bit, usually in the form of creating a new rules file for udev. This varies from device to device. A quick web search should bring up a solution for your device.

Creating an Android Virtual Device

The SDK comes with an emulator that will run so-called Android virtual devices (AVDs). A virtual device consists of a system image of a specific Android version, a skin, and a set of attributes, which include the screen resolution, SD-card size, and so on.

To create an AVD, you have to fire up the SDK and AVD manager. You can either do this as described previously in the SDK installation step, or directly from within Eclipse by clicking the SDK manager button in the toolbar.

1. Select Virtual Devices in the list on the left, and you will be presented with a list of currently available AVDs. Unless you've already messed around with the SDK manager, this list should be empty; let's change that.

2. To create a new AVD, click the New... button on the right, which will bring up the dialog shown in Figure 2-7.

Override the existing AVD with the same name

| Cancel

Figure 2-7. The AVD creation dialog of the SDK manager

3. Each AVD has a name by which you can refer to it later on. The target specifies the Android version that the AVD should use. Additionally, you can specify the size of the SD card of the AVD, as well as the screen size. For our simple Hello World project, you can select an Android 1.5 target and leave everything else as it is. For real-life testing, you'd usually want to create multiple AVDs that cover all the Android versions and screen sizes you want your application to handle.

NOTE: Unless you have dozens of different devices with different Android versions and screen sizes, it is advisable to use the emulator for additional testing of Android version/screen size combinations.

Running an Application

Now that you've set up your devices and AVDs, you can finally run the Hello World application. You can easily do this in Eclipse by right-clicking the "hello world" project in the Package Explorer view, and then selecting Run As > Android Application (or you can click the Run button on the toolbar). Eclipse will then perform the following steps for us in the background:

1. Compile the project to an APK file if any files have changed since the last compilation.

2. Create a new Run configuration for the Android project if one does not already exist. (We'll have a look into Run configurations in a minute.)

3. Install and run the application by starting or reusing an already running emulator instance with a fitting Android version, or by deploying and running the application on a connected device (which must also run at least the minimum Android version you specified as the Min SDK Level parameter when you created the project).

If you only created an Android 1.5 AVD, as suggested in the previous section, then the ADT Eclipse plug-in will fire up a new emulator instance running that AVD, deploy the Hello World APK file, and start the application. The output should look like Figure 2-8.

Figure 2-8. The awesome Hello World application in action!

The emulator works almost exactly like a real device, and you can interact with it via your mouse just as you would with your finger on a device. Here are a few differences between a real device and the emulator:

■ The emulator only supports single-touch input. Simply use your mouse cursor and pretend it is your finger.

■ The emulator is missing some applications, such as the Android Market.

■ To change the orientation of the device on the screen, don't tilt your monitor! Instead, use the 7 key on your numpad to change it. For this, you have to first press the Num Lock key above the numpad to disable its number functionality.

■ The emulator is really, really slow. Do not assess the performance of your application by running it on the emulator.

■ The emulator currently only supports OpenGL ES 1.0 with a few extensions. We'll talk about OpenGL ES in Chapter 7. For our purposes this is fine, except that the OpenGL ES implementation on the emulator is buggy and will often give you different results from those you'll get on a real device. For now, just keep in mind that you should not test any OpenGL ES applications on the emulator.

Play around with it a little and get comfortable with it.

NOTE: Starting a fresh emulator instance takes considerable time (up to minutes depending on your hardware). You can leave the emulator running for your whole development session so you don't have to restart it over and over again.

Sometimes when we run an Android application, the automatic emulator/device selection performed by the ADT plug-in is a hindrance. For example, we might have multiple devices/emulators connected, and want to test our application on a specific device/emulator. To deal with this, we can turn off the automatic device/emulator selection in the Run configuration of the Android project. So, what is a Run configuration?

A Run configuration provides a way to tell Eclipse how it should start your application when you tell it to run it. A Run configuration usually allows you to specify things like command-line arguments passed to the application, VM arguments (in the case of Java SE desktop applications), and so on. Eclipse and third-party plug-ins offer different Run configurations for specific project types. The ADT plug-in adds an Android Application Run configuration to the set of available Run configurations. When we first ran our application earlier in the chapter, Eclipse and ADT created a new Android Application Run configuration for us in the background with default parameters.

To get to the Run configuration of your Android project, do the following:

1. Right-click the project in the Package Explorer view and select Run As > Run Configurations.

2. From the list on the left side, select the "hello world" project.

3. On the right side of the dialog, you can now modify the name of the Run configuration, and change other settings on the Android, Target, and Commons tabs.

4. To change automatic deployment to manual deployment, click the Target tab and select Manual.

When you run your application again, you'll be prompted to select a compatible emulator or device to run the application on. Figure 2-9 shows the dialog. In this figure, I added a couple more AVDs with different targets and also connected two devices.

Android Device Chooser

Select a device compatible with target Android 1.5. (*) Choose a running Android device

Serial Number emulator-5554 0 HT97JL901589 Q HT019P803783

AVD Name androidl.5

O Launch a new Android Virtual Device

Target

Androidl.5

Debug State Yes Online Online Online

O Launch a new Android Virtual Device

AVD Name

Target Name

Platform

API Level

android2.2

Android 2.2

2.2

Retresh Manager...

Retresh Manager...

OK I I Cancel

Figure 2-9. Choosing an emulator/device to run the application on

The dialog shows all the running emulators and currently connected devices, as well as all other AVDs that are not running at the moment. You can choose any emulator or device to run your application on.

Debugging an Application

Sometimes our application will behave in unsuspected ways or crash. To figure out what exactly is going wrong, we want to be able to debug our application.

Eclipse and ADT provide us with incredibly powerful debugging facilities for Android applications. We can set breakpoints in our source code, inspect variables and the current stack trace, and so forth.

Before we can debug our application, we have to modify its AndroidManifest.xml file first to enable debugging. This presents a bit of a chicken-and-egg problem, as we haven't looked into manifest files in detail yet. For now, it suffices to know that the manifest file specifies some attributes of our application. One of those attributes is whether the application is debuggable. This attribute is specified in the form of an xml attribute of the <application> tag in the manifest file. To enable debugging, we add the following attribute to the <application> in the manifest file:

android:debuggable="true"

While developing your application, you can safely leave that attribute in the manifest file. But don't forget to remove it before you deploy your application to the market.

Now that you've set up your application to be debuggable, you can debug it on an emulator or device. Usually, you will set breakpoints before debugging to inspect the program state at certain points in the program.

To set a breakpoint, simply open the source file in Eclipse and double-click the gray area in front of the line you want to set the breakpoint at. For demonstration purposes, do that for line 23 in the HelloWorldActivity class. This will make the debugger stop each time you click the button. The source code view should show you a small circle in front of that line after you double-click, as in Figure 2-10. You can remove breakpoints by again double-clicking them in the source code view.

button. setText ("Touched rne "+touchCount+" tiine(s)"); Figure 2-10. Setting a breakpoint

Starting the debugging is much like running the application, as described in the previous section. Right-click the project in the Package Explorer view and select Debug As > Android Application. This will create a new Debug configuration for your project, just like in the case of simply running the application. You can change the default settings of that Debug configuration by choosing Debug As > Debug Configurations from the context menu.

NOTE: Instead of going through the context menu of the project in the Package Explorer view, you can use the Run menu to run and debug applications, as well as get access to the configurations.

If you start your first debugging session, Eclipse will ask you whether you want to switch to the Debug perspective, which you can happily confirm. Let's have a look at that perspective first. Figure 2-11 shows how it would look after starting debugging our Hello World application.

Figure 2-11. The Debug perspective

If you remember our quick tour of Eclipse, then you know that there are a couple of different perspectives, which consist of a set of views for a specific task. The Debug perspective looks a lot different from the Java perspective.

■ The first new view to notice is the Debug view at the top left. It shows all currently running applications and the stack traces of all their threads if they are run in debug mode.

■ Below the Debug view is the source-editing view we also used in the Java perspective.

■ The Console view prints out messages from the ADT plug-in, telling us what it is doing.

■ The LogCat view will be one of our best friends on our journey. It shows us logging output from the emulator/device that our application is running on. The logging output comes from system components, other applications, and our own application. It will show us a stack trace when our application crashes, and will also allow us to output our own logging messages at runtime. We'll have a closer look at LogCat in the next section.

■ The Outline view is not very useful in the Debug perspective. You will usually be concerned with breakpoints and variables, and the current line that the program is suspended at while debugging. I often remove the Outline view from the Debug perspective to leave more space for the other views.

■ The Variables view is especially useful for debugging purposes. When the debugger hits a breakpoint, we will be able to inspect and modify the variables in the current scope of the program.

■ Finally, the Breakpoints view shows a list of breakpoints we've set so far.

If you are curious, you've probably already clicked the button in the running application to see how the debugger reacts. It will stop at line 23, as we instructed it by setting a breakpoint there. You will also have noticed that the Variables view now shows the variables in the current scope, which consist of the activity itself (this) and the parameter of the method (v). You can further drill down into the variables by expanding them.

The Debug view shows us the stack trace of the current stack down to the method we are currently in. Note that you might have multiple threads running and can pause them at any time in the Debug view.

Finally, notice that the line where we set the breakpoint is highlighted, indicating the position in the code where the program is currently paused.

You can instruct the debugger to execute the current statement (by pressing F6), step into any methods that get called in the current method (by pressing F5), or continue the program execution normally (by pressing F8). Alternatively, you can use the items on the Run menu to achieve the same. Also notice that there are more stepping options than the ones I've just mentioned. As with everything, I suggest you experiment to see what works for you and what doesn't.

NOTE: Curiosity is a building block for successfully developing Android games. You have to get really intimate with your development environment to get the most out of it. A book of this scope can't possible explain all the nitty-gritty details of Eclipse, so again I urge you to experiment.

LogCat and DDMS

The ADT Eclipse plug-in installs many new views and perspectives to be used in Eclipse. One of the most useful views—already briefly touched on in the last section — is the LogCat view.

LogCat is the Android event-logging system, which allows system components and applications to output logging information of various logging levels. Each log entry is composed of a time stamp, a logging level, the process ID the log came from, a tag defined by the logging application itself, and the actual logging message.

The LogCat view gathers and displays this information from a connected emulator or device. Figure 2-12 shows some sample output from the LogCat view.

LogCat

H

¡Runj

®@(j)©© +

a ~

; Log j

Time

pid

tag

Message

10-13

23

16 . . .

D

393

dalvikvm

GC freed 1231 objectsV 49136 byt. . .

10-13

23

16 . . .

D

119

dalvikvm

GC freed 949 objects / 35712 byte...

10-13

23

16 . . .

D

212

dalvikvm

GC freed 1480 objects / 70632 byt...

10-13

23

18. . .

D

69

Keygu...

receive ACTI0N_BATTERY_CHANGED

10-13

2 3

18. . .

D

69

HtcLo...

onRefreshBatterylnfo: 45

10-13

23

18. . .

I

69

HtcLo...

upda t eS t a tusV i ewByPri ori t y

10-13

23

18. . .

I

69

HtcLo..

createDeviceStatusView

10-13

23

18. . .

D

295

UsbCo..

ACTION_BATTERY_CHANGED

10-13

23

18. . .

D

295

UsbCo...

unplugged = 2

10-13

23

18. . .

D

295

UsbCo...

USB Connected.

10-13

23

18. . .

D

295

UsbCo...

mObexServerS tarted=true

10-13

23

18. . .

D

295

UsbCo...

mA t CommandServerS t ar t ed = t rue

10-13

23

18. . .

D

295

UsbCo..

Show Notification...

10-13

23

18. . .

I

124

Conta...

android.intent.act ion.NOTIFICATIO. . .

10-13

23

20. . .

I

9195

jdwp

received file descriptor 24 from ADB

10-13

23

2 0...

¥

9195

Syste. .

Can't dispatch DDM chunk 46454154...

Figure 2-12. The LogCat view

Figure 2-12. The LogCat view

Notice that there are a number of buttons at the top right of the LogCat view.

■ The first five allow you to select the logging levels you want to see displayed.

■ The green plus button lets you define a filter based on the tag, the process ID, and the log level, which comes in handy if you want to show only the log output of your own application (which will probably use a specific tag for logging).

■ The rest of the buttons allow you to edit a filter, delete a filter, or clear the current output.

If several devices and emulators are currently connected, then the LogCat view will only output the logging data of one of these. To get finer-grained control and even more inspection options, you can switch to the DDMS perspective.

DDMS (Dalvik Debugging Monitor Server) provides a lot of in-depth information about the processes and Dalvik VMs running on all connected devices. You can switch to the DDMS perspective at any time via Window > Open Perspective > Other > DDMS. Figure 2-13 shows what the DDMS perspective usually looks like.

As always, there are a couple of specific views that are suitable for our task at hand. In this case, we want to gather information about all the processes, their VMs and threads, the current state of the heap, LogCat information about a specific connected device, and so on.

■ The Devices view displays all currently connected emulators and devices, as well as all the processes running on them. Via the toolbar buttons of this view, you can perform various actions, including debugging a selected process, recording heap and thread information, and taking a screenshot.

■ The LogCat view is the same as in the previous perspective, with the difference that it will display the output of the device currently selected in the Devices view.

■ The Emulator Control view lets you alter the behavior of a running emulator instance. You can force the emulator to spoof GPS coordinates for testing, for example.

DDMS

S n ¡X

hello world/default .properties - Eclipse

1 File Edit

Refactor Run Navigate Search Project Window Help

y Devices |

=

H

Ä 80»! g

I*

®

»

Name

com.bac 9195

i 86

_

Mr Q HT019P803 Online

2.2

=

com.bac 1198

m

86

a

V

<

i

Q Emulator Control

M Latency:

Threads £2 (j Heap @ Allocation Tracker jyi File Explorer Tid Status utime stime Name

1198

wait

63

15

main

1199

vmwait

2

0

HeapWorker

1200

vmwait

0

0

Signal Catcher

1201

running

1

0

JDWP

1202

vmwait

76

11

Compiler

1203

native

0

0

Binder Thread #1

1204

native

0

0

Binder Thread U2

1206

native

33

0

android, hardware. S ensorM anager$SensorT hread

Refresh

Telephony Status

Refresh

File

M Latency:

Telephony Actions

Incoming number: I

<z ta iffi LogCat Log

Time

tag dalvikvm

Message

GC_EXPLICIT freed 6493 objects

Filter:

Figure 2-13. DDMS in action

The Threads view will display information about the threads running on the process currently selected in the Devices view. It will only show this information if you also enable thread tracking, which can be achieved by clicking the fifth button from the left in the Devices view.

The Heap view, which is not shown in Figure 2-13, gives information about the status of the heap on a device. As with the thread information, you have to explicitly enable heap tracking in the Devices view by clicking the second button from the left.

The Allocation Tracker view shows what classes have been allocated the most within the last few moments. It provides a great way to hunt down memory leaks.

Finally, there's the File Explorer view, which allows you to modify files on the connected Android device or emulator instance. You can drag and drop files into this view as you would with your standard operating system file explorer.

DDMS is actually a standalone tool that is integrated with Eclipse via the ADT plug-in. You can also start it as a standalone application from the $ANDROID_HOME/tools directory (%ANDROID_HOME%/tools on Windows). It does not directly connect to devices, but uses the Android Debug Bridge (ADB), another tool included in the SDK. Let's have a look at ADB to round off your knowledge about the Android development environment.

Using ADB

ADB lets you manage connected devices and emulator instances. It is actually a composite of three different components:

A client that runs on the development machine, which you can start from the command line by issuing the command adb (which should work if you set up your environment variables as described earlier). When we talk about ADB, we refer to this command-line program.

A server that also runs on your development machine. It is installed as a background service and is responsible for communication between an ADB program instance and any connected device or emulator instance.

The ADB daemon, which also runs as a background process on every emulator and device. The ADB server connects to this daemon for communication.

Usually, we use ADB via DDMS transparently and ignore its existence as a command-line tool. Sometimes it can come in handy for small tasks, so let's just go quickly over some of its functionality.

NOTE: Check out the ADB documentation on the Android Developers site at http://developer.android.com for a full reference of the available commands.

A very useful task to perform with ADB is to query for all devices and emulators that are connected to the ADB server (and hence your development machine). To do this, execute the following command on the command line (note that > is not part of the command).

> adb devices

This will print a list of all connected devices and emulators with their respective serial numbers, and will resemble the following output:

List of devices attached HT97JL901589 device HT019P803783 device

The serial number of a device or emulator is used to target specific subsequent commands at it. The following command will install and APK file called myapp.apk located on the development machine on the device with the serial number HT019P803783.

> adb -s HT019P803783 install myapp.apk

The -s argument can be used with any ADB command that performs an action that is targeted at a specific device.

There also exist commands that will copy files to and from the device or emulator. The following command copies a local file called myfile.txt to the SD card of a device with the serial number HT019P803783.

> adb -s HT019P803783 push myfile.txt /sdcard/myfile.txt

To pull a file called myfile.txt from the SD card, you could issue the following command:

> abd pull /sdcard/myfile.txt myfile.txt

If there's only a single device or emulator currently connected to the ADB server, you can omit the serial number. The adb tool will automatically target the connected device or emulator for you.

There are of course a lot more possibilities offered by the ADB tool. Most of them are exposed through DDMS, and we'll usually use that instead of going to the command line. For quick tasks, though, the command-line tool is ideal.

0 0

Post a comment