Toggle Menu

Charlie Calvert on Elvenware

Writing Code and Prose on Computers

Core Code

OS and Tools

Art

Elvenware

Logging

Andriod comes with a class designed to help with logging. It is found in this package:

import android.util.Log;

It is typically used like this, where the most important lines are the last import statement, the declaration for the String tag, and the call to Log.d

package com.elvenware.testlogging;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;

public class TestLoggingActivity extends Activity 
{
  String tag = "TestLogging";

  @Override
  public void onCreate(Bundle savedInstanceState) 
  {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.main);

     Log.d(tag, "OnCreate called");
  }
}

Begin by declaring a “tag” which is passed as the first parameter to each call to Log.d. This tag will be used to help you filter logging messages. The second parameter is any arbitrary debug message that you want to log.

Viewing the Log

You can use a tool built into Eclipse called LogCat to view the messages you log. When debugging your applications, you should always be sure LogCat is running. If its not visible right away, choose the following from the Eclipse menu:

Window | Show View | LogCat

If that doesn’t work, or if you want more information, try:

Window | Show View | Other | Android | LogCat

To begin, press the green button in the Saved Filters view on the left of the LogCat window. Use the dialog that appears to create a filter. You can filter by several different fields. Let’s begin by filtering on the Tag we created, as shown in Figure 1.

Logging Setup

Figure 01: Filtering by tag.

When you run your program your log will be recorded in the LogCat window. In Figure 2, notice that I have selected in the Saved Filters view the filter that I set up in Figure 01:

View a log in
LogCat

Figure 02: Viewing the custom filter we created when we used Log.d. (Click to view full sized image.)

NOTE: LogCat has a pause button on the far right near the top. This button must be in the correct state or you won’t see, or be able to properly study, your debug output. It is simpler to let you experiment with the button than to try to say the obvious things about how it works. Pause means – well, just try it and you will see it does what you would expect.

There are six fields visible in the LogCat window:

  • Level: Which in this case is set to D for debug.
  • Time: The time when the message was recorded
  • PID: The Process ID of the application that sent the message.
  • Application: The name of your application. This is usually the namespace of your main Activity.
  • Tag: The tag we specified at the top of the class we created and passed in the first parameter of our call.
  • Text: The text we sent in the second parameter

You can click the disk icon on the right of LogCat to save selected output from the LogCat window to a text file. This can be useful if you want to search through the file in an editor, or send the file to someone else such as another developer or your teacher. Here is the entry shown in Figure 2 as it appears in a text file:

02-02 15:17:38.896: D/TestLogging(1653): OnCreate called

It is sometimes useful to select the All Messages filter in the Save Filters view. At first, there will be so many messages that it is difficult to make sense of them. You can save all these messages to a text file and search through them, or better, double click the All Messages text in the Save Filters view and create a filter, much as you did in Figure 1. For instance, if I filter only on those messages sent by a particular application, I might get output that looks like this:

02-02 15:17:02.376: D/HelloWorld(1593): onCreate.
02-02 15:17:02.376: D/HelloWorld(1593): onStart. UI may be partially visible.
02-02 15:17:02.376: D/HelloWorld(1593): onResume. UI fully visible.
02-02 15:17:02.396: D/MyApplication(1593): configuration changed
02-02 15:17:17.016: D/HelloWorld(1593): onSaveInstanceState. You should load up the bundle
02-02 15:17:17.016: D/HelloWorld(1593): Saved state
02-02 15:17:17.016: D/HelloWorld(1593): onpause. I may be partially or fully invisible
02-02 15:17:17.216: D/HelloWorld(1593): onstop. I am fully invisible
02-02 15:17:38.586: D/HelloWorld(1593): onRestart. UI controls are there.
02-02 15:17:38.586: D/HelloWorld(1593): onStart. UI may be partially visible.
02-02 15:17:38.586: D/HelloWorld(1593): onResume. UI fully visible.
02-02 15:17:38.856: D/HelloWorld(1593): onSaveInstanceState. You should load up the bundle
02-02 15:17:38.856: D/HelloWorld(1593): Saved state
02-02 15:17:38.856: D/HelloWorld(1593): onpause. I may be partially or fully invisible
02-02 15:17:39.066: D/HelloWorld(1593): onstop. I am fully invisible

Here I can see that this application sent out two types of debug information: one has the tag HelloWorld, and the other MyApplication.

Exceptions

LogCat can help you track down errors in your program. Suppose we modified the code shown above to look like this:

public void onCreate(Bundle savedInstanceState) 
{
   super.onCreate(savedInstanceState);
   setContentView(R.layout.main);
        
   Log.d(tag, "OnCreate called");
        
   TextView view = (TextView)this.findViewById(1);
   view.setText("Error");
}

This program will raise an exception on the call to setText because there is no such TextView resource in this program and hence view will be set to null. If you run this program, you will get an exception. After you see the error, be sure to toggle to off the pause button on the far right of the LogCat view. Select All Messages on the left of LogCat,  Scroll up from the bottom of the LogCat view, and look for a “sea of red.” Hover your mouse over the second line in the redness. You should see an explanation of what is wrong. 

Alternatively, or in addtion, you can create a filter on All Messages with the Tag AndroidRuntime, or set the LogLevel in your Filter to error. If you do that, it should be fairly easy for you to isolate the error messages:

02-02 16:20:17.986: E/AndroidRuntime(1688): FATAL EXCEPTION: main
02-02 16:20:17.986: E/AndroidRuntime(1688): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.elvenware.testlogging/com.elvenware.testlogging.TestLoggingActivity}: java.lang.NullPointerExceptionion
02-02 16:20:17.986: E/AndroidRuntime(1688): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1647)
02-02 16:20:17.986: E/AndroidRuntime(1688): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663)
02-02 16:20:17.986: E/AndroidRuntime(1688): at android.app.ActivityThread.access$1500(ActivityThread.java:117)
02-02 16:20:17.986: E/AndroidRuntime(1688): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
02-02 16:20:17.986: E/AndroidRuntime(1688): at android.os.Handler.dispatchMessage(Handler.java:99)
02-02 16:20:17.986: E/AndroidRuntime(1688): at android.os.Looper.loop(Looper.java:130)
02-02 16:20:17.986: E/AndroidRuntime(1688): at android.app.ActivityThread.main(ActivityThread.java:3683)
02-02 16:20:17.986: E/AndroidRuntime(1688): at java.lang.reflect.Method.invokeNative(Native Method)
02-02 16:20:17.986: E/AndroidRuntime(1688): at java.lang.reflect.Method.invoke(Method.java:507)
02-02 16:20:17.986: E/AndroidRuntime(1688): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
02-02 16:20:17.986: E/AndroidRuntime(1688): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
02-02 16:20:17.986: E/AndroidRuntime(1688): at dalvik.system.NativeStart.main(Native Method)
02-02 16:20:17.986: E/AndroidRuntime(1688): Caused by: java.lang.NullPointerException
02-02 16:20:17.986: E/AndroidRuntime(1688): at com.elvenware.testlogging.TestLoggingActivity.onCreate(TestLoggingActivity.java:20)
02-02 16:20:17.986: E/AndroidRuntime(1688): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
02-02 16:20:17.986: E/AndroidRuntime(1688): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611)
02-02 16:20:17.986: E/AndroidRuntime(1688): ... 11 more

The most important lines are the second and the sixteenth, where the sixteenth is also identifiable as the fourth from the bottom. The second line tells us that we have a null pointer exception, and the sixteenth tells us that the error occurred on Line 20 of TestLoggingActivity.java. Here is that line:

view.setText("Error");

As you can see, LogCat has correctly located our error.

Summary

LogCat can help you understand your program, record important events in your program, and debug errors. I use LogCat multiple times every day. I believe it is a well designed tool that does its job well.

There is more to LogCat than I have explained here, but this information should be sufficient to get you up and running. For additional information, search online or read the relevant text in books such as Pro Android 3, pages 54 through 56, found in Chapter 2, in the section called “Debugging your App.”

Copyright © Charlie Calvert | Elvenware Home | Writing Code | Delphi | CSharp | My Books