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.
CHAPTER 2: First Steps with the Android SDK
43
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.
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.
CHAPTER 2: First Steps with the Android SDK
45
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.
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.
CHAPTER 2: First Steps with the Android SDK
47
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.
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.
CHAPTER 2: First Steps with the Android SDK
49
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.
Summary
The Android development environment can be a little bit intimidating at times. Luckily, you only need a subset of the available options to get started, and the last couple of pages of this chapter should have given you enough information to get started with some basic coding.
The big lesson to take away from this chapter is how the pieces fit together. The JDK and the Android SDK provide the basis for all Android development. They offer the tools to compile, deploy, and run applications on emulator instances and devices. To speed up development, we use Eclipse along with the ADT plug-in, which abstracts away all the hard work we’d otherwise have to do on the command line with the JDK and SDK tools. Eclipse itself is built on a few core concepts: workspaces, which manage projects; views, which provide specific functionality, such as source editing or LogCat output; perspectives, which tie together views for specific tasks such as debugging; and Run and Debug configurations, which allow us to specify the startup settings used when we run or debug applications.
The secret to mastering all this is practice, as dull as it may sound. Throughout the book, we’ll implement a couple of projects that should make you more comfortable with the Android development environment. At the end of the day, though, it is up to you to take it all one step further.
With all this information stuck in your head, you can move on to what you came here for in the first place: developing games.