Android is a Java platform, albeit a slightly different Java platform. As such, many new Android developers I encounter are at first confused by Android’s logging features. Admittedly, it is a bit different that some of the logging APIs and apparatus one encounters in Java SE or Java EE. So I’m going to attempt to clarify some of Android’s logging capability and also highlight some very interesting points about how logging works.
The Log class
First off, logging is accomplished through Android’s android.util.Log class. There are a collection of static methods that are called on the class itself to write to what is called the LogCat. The documentation for the Log class can be found here, but below are the more significant methods.
|Android Log method||Purpose|
|e(String tag, String message)||Log an error|
|w(String tag, String message)||Log a warning|
|i(String tag, String message)||Log an informational message|
|d(String tag, String message)||Log a debug statement|
|v(String tag, String message)||v stands for verbose. Log verbose forms of the informational messages|
|wtf(String tag, String message)||My favorite – indicating the Android developers truly have a sense of humor. Log a failure (probably critical) that was never expected/anticipated to occur. According to the documentation, wtf stands for what a terrible failure. Ahhh – sure. This method was added with Android 2.2 (API 8). So it is not available in all Android environments.|
Note, there are additional methods and those above are overloaded, but this is enough to get you started logging.
As you can see by the methods’ purpose, each method allows you to suggest the severity and importance of the log message. The purpose of the first parameter to these methods, the tag parameter, is to identify the component that originated the log message. The tag string can be very helpful in helping to filter out log messages (more on this topic below). The second parameter to the Log methods is the message to be deposited in the LogCat.
As a matter of good Android development practice, create static final String constants to keep the tags consistent.
Use the Log class and its methods from anywhere in your Android code to add messages to the log file like the Activity below.
So where do all those log messages go? Android maintains a circular buffer (i.e. file) for log messages, stack traces, etc. This file is located in /dev/log/main on the device (or Android Virtual Device during testing). It is circular in that the file is maintained within a fixed size. As new messages come in and the buffer/file fills up, old messages are pulled off the file (making room for the new messages). The size of the LogCat buffer varies per device. You can use the adb tool to see the size of the log (see details about adb here). Call the following command:
adb logcat -g
Below is an example result indicating my device has a buffer size of 64K.
You access LogCat for an AVD or on an actual device (via USB cable) from either DDMS or an adb shell. You can even use the same tools to control entries and formatting to the LogCat file. See here for more details on reading and writing to the log. If you use Eclipse, there is a DDMS perspective that provides a LogCat view for viewing (and filtering
In fact, these tools allow you to filter the log so as to be able to find relevant entries. You can filter by message severity (as shown below).
You can also create other custom filters that filter messages by tag (and the reason why establishing good tags is good Android developer convention), message, process id, or application name.
Turn Logging Off in Production
While access to the log file is limited (via the tools mentioned), you still have to be careful in that it is very easy to hook up a real device to a laptop via USB and see the information logged. A Belgian bank create a very large security concern by logging information from a server to the log file during development and forgetting to remove the logging when the application went to production. See here for the details of the story. No doubt, you will hear and see of other such security concerns. In fact, the Android Developer site provides some prudent guidance regarding the preparation of an application before it is ready to be released. In that guidance, they tell us to “Make sure you deactivate logging and disable the debugging option before you build your application for release.”
Turning Off (or Down) Logging
To stop debugging, you can remove Log calls in your code. Alternately, you can conditionalize Log calls and thereby allow a single variable (or set of variables) to help control what (if anything) gets logged.
public static boolean LOG_ON = true;
if (LOG_ON) Log.e(VIEW_TAG, “error message goes here”);
adb shell setprop log.tag.MyAppTag WARN
As a final alternative, you can also use a tool such as ProGuard to strip out logging statements. ProGuard is a tool that shrinks, optimizes, and obfuscates Android Java code and is integrated into Android build systems. You can learn more about these options from a nice StackOverflow thread here.
Why not System.out.println()
In “normal” Java, you may have used System.out.println() (and System.err) calls to drop debug and other log calls into the standard output (and standard error). Good ol’ System.out still works in Android, but it should be avoided. First of all, by default, System.out.println( ) calls are routed to an alternate /dev/null file. These log statements can be rerouted to the LogCat file with some additional configuration. However, another reason why you may find System.out.println() less than helpful is that these println() messages are tagged with default “System.out” tags and with info (I) level priority. So it is not as easy to determine what component launched the logging and the severity may not be inline with the info level attributed to the log message.
Log4j (and other such common Java logging packages)
For those more familiar with Log4J or SLF4J logging packages, you will find these frameworks are also available in Android. In fact, their Android versions serve as a wrapper to the LogCat functionality. You’ll find Log4j for Android here and SLF4J for Android here.
Other Android Logging Secrets
There are a couple of other secrets to Logging that are often missed by Android developers. In fact, these are not secrets but information that is buried a little bit in the Android documentation.
As mentioned already, all logging should be removed or at least reduced prior to shipping any Android application. But you might be interested to know that debug log messages are compiled in to the Android code, but get stripped at runtime. This is not the case with verbose log statements. Therefore, as the documentation says, “Verbose should never be compiled into an application except during development.” (Reference: http://developer.android.com/reference/android/util/Log.html).
Another little hidden gem of knowledge deep in the documentation is that there are actually several circular log files. Log messages go to /dev/log/main, but there exist telephony logs, event logs and system logs as well. These can be found in /dev/log/radio, /dev/log/events and /dev/log/system respectively. Use the following command to view these logs.
adb logcat -b <alternate log name like radio>
Hopefully, this post can help you navigate your way around the Android log capability. If you are just starting out and would like to learn more about Android, please join me for Complete Android at Intertech. Contact Dan McCabe in our office for details on our next public class offering.