Greetings!

The main purpose of this website is to support Android indie game developers with tutorials, reviews and promotion of their games. The main difficulty for the developers is not to make the game, but to get exposure. To get it out there. If you find anything useful here, please spread the word. Like my page on Facebook, follow me on Google+ or Twitter. Thank you!

Google+ Facebook Twitter

× close

Tuesday, 27 August 2013

Tutorial - Android Logging and Logging in AndEngine

This tutorial is part of AndEngine basics.


<< List of all tutorials


If you have been working as a software developer, you probably use logging daily. But for beginning game developers, the whole concept of logging might be quite new. So what exactly is logging?

When you want to print a message from your program, you have usually two options. Print it on screen or print it to some log. A log is simply a list of messages. It can be later printed in a console, a file, or anywhere else.

In games, where you usually work with fullscreen graphical interface, it's not very practical to print anything on screen. You can use good-old Java System.out.println() method, but using logging is more convenient.

Android comes with a log facility called LogCat. You can view LogCat output through adb or if you are using Eclipse, go to Window -> Show View -> and search for LogCat (the one with rainbow tail is the one). If your device is connected you will immediately see some messages.



The log messages have the following attributes:

  • Log Level - this is the severity of the message. It can be verbose, debug, info, warning, error or assert (a.k.a.WTF - what a terrible failure)
  • Time - Timestamp when the message added
  • PID - process ID of the app that printed the message
  • TID - Thread ID
  • Application - identified by the package name
  • Tag - your custom identifier
  • Text - your custom message

You can select what level you want to see and also use filtering to show only messages containing certain string (just type the string) or tag (type tag:name). Other options are available, see the hint in Eclipse.

How to use logging in code


You can use standard Android logging or if you are using AndEngine, then it's log wrapper. Few examples:


Log.v("kulis", "This is a very detailed message");
Debug.v("This is a very detailed message");
// notice missing tag above, "AndEngine" will be used

Log.i("kulis", "Info level message");
Debug.i("kulis", "Info level message");

try {
  doSomethingDangerous();
} catch (Exception e) {
  // never swallow exceptions, at least print them to log!
  Log.e("kulis", "Oops!", e);
  Debug.e("Oops!", e);
}

Debug.setDebugLevel(DebugLevel.ERROR);
Log.i("kulis", "This message still will be printed");
Debug.i("kulis", "This will not be printed, current level is ERROR");
  
Log.wtf("kulis", "This should never happen");


Notice that when using the Android class Log, you have to specify tag, message and optionally a throwable object (exception). AndEngine Debug class adds methods without the tag. In that case "AndEngine" tag will be used. Also notice the method setDebugLevel - this will limit AndEngine logging to the set level and higher. AndEngine doesn't implement the wtf() method. It should be used for things that should never happen - so in case they happen, you will know ;)

Best practices

Always log exceptions. Never use emtpy catch block. If you are expecting the exception to happen, at least print a debug message that it happened - the code above might change later and you will be surprised if you don't print anything. Also try to use specific exception handling (don't simply catch Exception, but the Exception that you expect, e.g. NullPointerException) and use different messages for different types.

  • Verbose - used for low level debugging. Print stuff like position of your character when you are debugging why the hell it's going off screen etc.
  • Debug - Messages that could be useful to determine where something went wrong. E.g. put a debug level message to each method beginning and end.
  • Info - These messages can be useful in production as well. Log important events in info level, e.g. Engine created
  • Warning - something not quite right, but it's not a bug. E.g. you can't connect to Facebook to submit Highscore - not nice, but you can live with it.
  • Error - Log exceptions and errors that you will need to analyze later and solve.
  • Assert - this is the WTF level. Simply log things that should never happen, e.g. a case in switch statement, that you expect never to be called.

Be careful with assembling messages from several parts. For each statement where you concatenate:

Log.d("kulis", "Position: " + x + ", " + y);

Java will create a StringBuilder object, use three method calls and then throw the StringBuilder away. This can have serious impact on performace! Imagine doing this in your game loop, that is being called 60 times per second...

What you should do is one of the three following options:



if (BuildConfig.DEBUG) {
  Log.d("kulis", "Position: " + x + ", " + y);
}

if (MainActivity.DEBUG) {
  Debug("Position: " + x + ", " + y);
}

if (Debug.getDebugLevel().isSameOrLessThan(DebugLevel.DEBUG)) {
  Debug("Position: " + x + ", " + y);
}

The first option, BuildConfig.DEBUG,  is Android's built-in property that should be set to false during export with production certificate. But it doesn't work very well, so I can't recommend it.

The second option is your own boolean property - highly recommended, because you will probably want to use it elsewhere too.

And finally the third option is AndEngine's built-in mechanism to test for the current Debug level (see above). It's seems too complicated, but still can be useful.

When using any of these (except the first one in some cases ;)), the concatenation will not be called if the condition is false.

Also if you are using AndEngine Debug class set debug level to NONE  for production to avoid printing anything.

Conclusion

Use debugging whenever you need to pass a message from you application and be careful not to use too much of the concatenation. If you need it, wrap it in the if statement. Leverage the Debug class if you are already using AndEngine.

You might have noticed, that the LogCat view icon in Eclipse is droid flying with rainbow tail. This is certainly an easter egg. Another easter egg in Ice Cream Sandwich is the actual nyandroid swarm. Go to Settings -> About and start tapping on Version (that should say 4.0.x). After a while a droid dressed in ice cream sandwich appears. Tap and hold on it. Enjoy...

Martin Varga is a Czech software developer who likes pygmy owls (hence Kulíš), running, ramen, travelling and living in foreign countries. He is also known as smartus or sm4 on the internet (read as smartass, but there are too many of them). He currently tries to make games in AndEngine like Mr. Dandelion's Adventures and hangs around a lot at the AndEngine forums.