Logging in Android – Part I

Introduction

In this topic and the next one in the series, we will take a look at the logging faciility available in the Android platform. Whenever we develop any application, we normally put in log statements in the code. As per the industry standards the log levels are classified based on their severity. So for example in Android platform, we have different logging levels such as VERBOSE, DEBUG, INFO, WARN, ERROR, ASSERT and SUPPRESS. In this part of the session, we will take a look at what is the default logging level in the Android platform and what are the ways to change the logging level in an application already deployed onto the device.

Sample Application

To explore the various levels of logging in the Android platform, let us create a very simple application. The application will have one activity with a TextView and a Button control. We will put several log statements in the onCreate function and the event handler that we will develop for the Button control.

The following is the fragment_logger.xml file.

fragment_loggerFragment_Logger.xml

Notice that we have only one Button with the function called generateLogs() as the onClick event handler. We will take a look at the Strings.xml file and then at the code before we start with looking at the log levels code.

StringsStrings.xml

The code from the LoggerActivity.java is shown below. The entire code is not depicted. Only the code from the onCreate() and the generateLogs() function is presented here. We are using the default Log class provided in the package android.util.

LoggerActivityLoggerActivity.java

Logging

Logging in Android is provided through the class called Log which resides in the android.util package. As seen in the code, we can write out log statements such as

Log.i(TAG, “message”);

Here the static function “i” means informative message, statiic function “d” means debug message and so on. All the log statements are written in the output file as shown in the LogCat window.

Logs1LogCat output for above logging

As seen both the iinformational messages as well as debug messages are printed in the LogCat window. The informational messages are generated from the onCreate() function while the debug messages were written from the generateLogs function. In the generateLogs() function, we are invoking the function isLoggable(TAG, Log_LeveL) to see whether the log level for the specified tag is loggable or not. Now comes the interesting part. Let us see the output of the above code when executed on an actual device.

Logs2The Debug level is NOT loggable

isLoggable function

As mentioned the isLoggable operation checks whether or not a log for the specified tag is loggable at the specified level. But even though the output above shows that the DEBUG level is NOT loggable for our tag, it is still written in the LogCat window. So it really means that the Android system writes the log information irrespective of this setting. So how do we control this?

We have to explicitly call isLoggable on the specified tag and specified level. When the condition returns true, we shoulld make a call to the Logger. This is shown below.

       if (Log.isLoggable(TAG, Log.INFO)){

               Log.i(TAG, “Begin – onCreate function ” + “log.tag.” + TAG);

     }

       if (Log.isLoggable(TAG, Log.DEBUG)){

               Log.d(TAG, “Begin – generateLogs function”);

       }

Thus the log statement should be written in the appropriate condition. With the above condition in place, if we execute our application again, the following output is generated in the LogCat window.

Logs3The debug statements in the generateLogs() function is not displayed

As noticed in the LogCat window, the debug statements in the generateLogs() function do not appear in the output.

So what is the default log level for any tag within Android platform? The default level for any tag within the Android system is Log.INFO. The reason is that we have put the log statements within the isLoggable() condition. As the default log level for the Android platform for any tag is INFO, the condition will evaluate to false. Hence the log statement will never be executed. That is the reason we saw earlier that Debug level is NOT loggable. So how do we change the log level for a device?

Changing the log level of a device – setting property from the ADB Shell

Ensure that the device is connected to the USB port of your laptop and that the USB debugging is enabled. Execute the ADB shell command and type in the following command.

Logs4

Setting the Log Level Property through ADB Shell

The command is setprop Log.tag.<YourTagName> DEBUG.

In our case, we substituted <YourTagName> with LoggerActivity.Now we will execute our application on the mobile device again and see the statements that appear in the LogCat window and also the output that appears on the application screen.

Logs5The debug statements for the generateLogs() function appear in LogCat

Since now we have changed the default level of logging for our tag (i.e. LoggerActivity) to debug, all our logs for debug level now appear in the output of LogCat. Let us check the application screen also.

Logs6Debug level is loggable

With the setprop command that we executed from the ADB shell window, we have now made sure that the debug level is loggable. Is that the only way to change the log level in the Android platform?

Changing the log level of a device – through properties file

There is a second way of changing the default logging level. This is done with the help of properties file. We need to create a local.prop file. The contents of the file would be as follows:

‘log.tag.< YourTagName >=<LOG_LEVEL>’.

The file needs to be placed in the /data directory and should be available as => /data/local.prop.

NOTE: Access to the /data directory is restricted and hence this method of changing the logging level seems impractical on the Android device.

Conclusion

In this part, we have seen how the Log class behaves and how it writes the log statements. It basically writes out all the log statements to the output irrespective of the default logging level set on the Android platform. So we wrapped all the logging statements in an IF condition to check if the logging level for that specific tag is allowed or not. If the logging level for that specific tag is supported, then the log statements are written to the output else they will not be written. This gives control over when the logging statements should be written or not written.

In this session, we have seen that the default logging level for any tag in the Android platform is Log Level INFO. So if, we want to write debug statements with the isLoggable() condition, the debug statements will never get written to the output.

So we need a way to change the default log level. This is achieved by either setting the property of the logging level through the ADB shell or by creating a local.prop file and storing it in the /data directory. To set this property through both of these options, we need to have the device connected to the PC through USB cable with USB debugging enabled.

Are there any other ways of changing the log level -> may be programmatically when the application is actually being executed on the device? – Well, let us explore this option in part 2 of this series.

Happy Learning!!!