Basic Android Debugging with Logs

Posted

As with most areas in software engineering, debugging is a crucial aspect of Android development. Properly setting up your application for debugging can save you hours of work and frustration. Unfortunately, in my experience not many beginners learn how to properly make use of the utility classes provided in the Android SDK. Unless you are an experienced developer, it is my personal belief that Android debugging should follow a pattern. This will prove beneficial for a couple reasons:

  • It allows you to anticipate bugs down the line. Setting up your development work space for debugging will give you a head start on bugs you might encounter in the future.

  • It gives you centralized control over the debugging process. Disorganized and sparse placement of log messages in your class can clutter your logcat output, making it difficult to interpret debugging results. The ability to toggle certain groups of log messages on/off can make your life a whole lot easier, especially if your application is complex.

The Log Class

For those of you who don’t know, the Android SDK includes a useful logging utility class called android.util.Log. The class allows you to log messages categorized based severity; each type of logging message has its own message. Here is a listing of the message types, and their respective method calls, ordered from lowest to highest priority:

  • The Log.v() method is used to log verbose messages.
  • The Log.d() method is used to log debug messages.
  • The Log.i() method is used to log informational messages.
  • The Log.w() method is used to log warnings.
  • The Log.e() method is used to log errors.
  • The Log.wtf() method is used to log events that should never happen (“wtf” being an abbreviation for “What a Terrible Failure”, of course). You can think of this method as the equivalent of Java’s assert method.

One should always consider a message’s type when assigning log messages to one of the six method calls, as this will allow you to filter your logcat output when appropriate. It is also important to understand when it is acceptable to compile log messages into your application:

  • Verbose logs should never be compiled into an application except during development. When development is complete and you are ready to release your application to the world, you should remove all verbose method calls either by commenting them out, or using ProGuard to remove any verbose log statements directly from the bytecode of your compiled JAR executable, as described in Christopher’s answer in this StackOverflow post.
  • Debug logs are compiled in but are ignored at runtime.
  • Error, warning, and informational logs are always kept.

A Simple Pattern

A simple way to organize debugging is with the sample pattern implemented below. A global, static string is given to represent the specific class (an Activity in this example, but it could be a service, an adapter, anything), and a boolean variable to represent whether or not log messages should be printed to the logcat.

public class SampleActivity extends Activity {

  /**
   * A string constant to use in calls to the "log" methods. Its
   * value is often given by the name of the class, as this will 
   * allow you to easily determine where log methods are coming
   * from when you analyze your logcat output.
   */
  private static final String TAG = "SampleActivity";

  /**
   * Toggle this boolean constant's value to turn on/off logging
   * within the class. 
   */
  private static final boolean VERBOSE = true;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (VERBOSE) Log.v(TAG, "+++ ON CREATE +++");
  }

  @Override
  public void onStart() {
    super.onStart();
    if (VERBOSE) Log.v(TAG, "++ ON START ++");
  }

  @Override
  public void onResume() {
    super.onResume();
    if (VERBOSE) Log.v(TAG, "+ ON RESUME +");
  }
}

Don’t be afraid to be creative in how you print your log messages to the logcat! For instance, when the sample activity above is launched, the resulting logcat is presented in an nicely formatted and human-readable way:

V SampleActivity +++ ON CREATE +++
V SampleActivity ++ ON START++
V SampleActivity + ON RESUME +

Conclusion

In this post, I have covered the basics in which Android debugging can (and should) be performed. In a future post, I will go into a bit more depth by providing some more advanced patterns that will give you more control over how debugging is performed at runtime.

Leave a comment if this helped… it’ll motivate me to write more of these blog posts in the future! :)

+1 this blog!

Android Design Patterns is a website for developers who wish to better understand the Android application framework. The tutorials here emphasize proper code design and project maintainability.

Find a typo?

Submit a pull request! The code powering this site is open-source and available on GitHub. Corrections are appreciated and encouraged! Click here for instructions.

Apps by me

Shape Shifter simplifies the creation of AnimatedVectorDrawable path morphing animations. View on GitHub.
2048++ is hands down the cleanest, sleekest, most responsive 2048 app for Android!