Debugging
As mentioned before, the easiest way to debug an Android application running on either a device or an AVD instance is to output debug messages to the log output (LogCat
) so that they can be read via ADB. The API in Android for this purpose is the Log
class. It uses various categories to distinguish between the importance of the messages, ranging from verbose to error.
For example, to output a debug string to LogCat
, we use the following code in Java:
Log.d("AndEngineOnTour", "This is debug output.");
The first part is the tag for the application or class that we output from, and the second part is the actual message. The tag is used in filtering to, for example, only see the output from our own application. We can also use a filter on the log category.
When writing native code in C/C++ using the Native Development Kit (NDK), we may also want to use LogCat
. Here, we just have to include one header and use a slightly modified function call, like this:
#include <android/log.h> __android_log_print(ANDROID_LOG_DEBUG, "AndEngineOnTour", "This is debug output");
Finally, we can use a debugger. For Java, this is easy, with IDEs such as Eclipse/ADT offering ready-to-use debugging functionality with full integration. This allows easy debugging, adding of breakpoints, and the like. For native code, this is slightly more complex, as we have to resort to using gdb
.
The gdb
tool is part of the GNU Compiler Collection (GCC), which also contains the compiler used to compile the native code for an Android application. In this case, we want to use its gdb
debugger to attach to the native code process on the Android device or AVD so that we can set breakpoints and otherwise monitor the execution.
For gdb
to be able to work with such a process, we need to compile the native code with debug symbols enabled, and modify the Android manifest. This involves the following steps:
AndroidManifest.xml
needs theandroid:debuggable="true"
setting in the<application>
tag- The
Application.mk
file needsAPP_OPTIM := debug
added - Finally, we use
NDK_DEBUG=1
in the command that we use to build the native code
The NDK contains a script called ndk-gdb
that automates the process of setting up gdb
, but the essence of what is involved is that we need to push the gdbserver
instance onto the device or AVD that we intend to debug on, and connect to this server remotely with gdb
. The details of this procedure are beyond the scope of this book, however.