I have an application that uses a lot of Log.d()
or Log.e()
calls for debugging. Now I want to create my final package for release. The Android Export feature from Eclipse mentions to remove the "Debuggable"
flag in the manifest, which I have done. Should I also comment all the Log
calls to improve the performance of my application or these calls will do nothing in the non debuggable final version package ?

- 6,511
- 13
- 49
- 53

- 1,581
- 1
- 15
- 22
4 Answers
I have subclassed the Log class to a class called Trace, which mirrors methods on Log. So I do Trace.d(TAG,"blah") and then within the Trace.d method the code only executes based on a static final class variable called LOGGING_LEVEL, which has levels 1-5 (none, errors only, errors & warnings, errors & warnings & info, and everything including debug) . When producing a production APK, Proguard removes all the code that isn't used in the application, so it does it for me.
For me, logging is far too important to remove from the source, but it must be removed from the production application, for performance, secure and intellectual property reasons.
This structure allows me to add a lot MORE logging to the application, which makes debugging problems much easier, but with no impact whatsoever on the production APK
public class Trace
{
public static final int NONE = 0;
public static final int ERRORS_ONLY = 1;
public static final int ERRORS_WARNINGS = 2;
public static final int ERRORS_WARNINGS_INFO = 3;
public static final int ERRORS_WARNINGS_INFO_DEBUG = 4;
private static final int LOGGING_LEVEL = ERRORS_ONLY; // Errors + warnings + info + debug (default)
public static void e(String tag, String msg)
{
if ( LOGGING_LEVEL >=1) Log.e(tag,msg);
}
public static void e(String tag, String msg, Exception e)
{
if ( LOGGING_LEVEL >=1) Log.e(tag,msg,e);
}
public static void w(String tag, String msg)
{
if ( LOGGING_LEVEL >=2) Log.w(tag, msg);
}
public static void i(String tag, String msg)
{
if ( LOGGING_LEVEL >=3) Log.i(tag,msg);
}
public static void d(String tag, String msg)
{
if ( LOGGING_LEVEL >=4) Log.d(tag, msg);
}
}

- 28,313
- 34
- 134
- 217
-
1I thought this was already included in the Log class of Android. Why can't we just do Log.setLogLevel(Log.ERROR)? If not your solution seems really good. – jmbouffard Feb 10 '11 at 16:25
-
18"with no impact whatsoever on the production APK" ... wrong. this is a well-known anti-pattern. the problem is that the msg argument is always evaluated whether or not you actually log the message. for example Trace.e("blah", "error was: " + error.getCode() + ", ruh roh!"). whether or not you log, there's three temp string objs created and two superfluous method calls. – Jeffrey Blattman Feb 10 '11 at 16:30
-
@jmbouffard There's no method on Log called setLogLevel() – Ollie C Feb 10 '11 at 16:40
-
@farble1670 You make a very good point, though I expect it only applies where there's a statement evaluation being performed within the logging method call? Thanks for pointing out this limitation, do post an answer if you know a way that solves this problem. – Ollie C Feb 10 '11 at 16:44
-
2the only way is to wrap each log statement with an if like: if (Log.getLevel() > Log.DEBUG) then Log.d(...); then the worst you are doing is a simple type comparison. it makes for some really, very ugly code. the other alternative would be to apply some AOP solution to inject log statements, or not, at compile time. i have no experience applying that in an android environment however. – Jeffrey Blattman Feb 10 '11 at 16:57
-
@JeffreyBlattman So, the use of Slf4j, backlog and other logging facilities is an anti pattern, too? – OneWorld Jun 20 '13 at 20:36
-
1@OneWorld all logging facilities have a "get log level" method that can be used as i suggested. – Jeffrey Blattman Jun 20 '13 at 20:52
-
Note: this is what `isLoggable()` is for. – Edward Falk Feb 08 '22 at 03:23
This made me check my assumption that the log.d
lines in the code would somehow not appear on a signed release apk without the debuggable flag set in the manifest, I was wrong, they still appear.
A quick search on SO led me to the accepted answer to this question: Remove all debug logging calls before publishing: are there tools to do this?
It works very well and you don't have to change any code.
-
Seems to be a good solution but I'm not sure if I want to use Proguard. – jmbouffard Feb 10 '11 at 16:19
-
@jmbouffard: If you're already using Ant to build your release apk, then it's pretty simple to add Proguard, as there's already a target in the SDK's main_rules.xml. If you're not familiar with Ant, then I agree, it might be a bit of a pain. – NickT Feb 10 '11 at 16:29
From developer.android.com:
Turn off logging and debugging and clean up data/files For release, you should make sure that debug facilities are turned off and that debug and other unnecessary data/files are removed from your application project.
Remove the android:debuggable="true" attribute from the element of the manifest. Remove log files, backup files, and other unnecessary files from the application project. Check for private or proprietary data and remove it as necessary. Deactivate any calls to Log methods in the source code.

- 33,439
- 9
- 77
- 71
-
2I would not be so strict to remove all logging, but debug logging for sure. – Heiko Rupp Feb 10 '11 at 15:37
-
I already saw that information on android dev website but it was not clear to me if there was a mechanism to "Turn off logging" other than commenting everything. Also, when they say "Deactivate any calls to Log methods in the source code" it is not clear if they mean "comment" or if there is another way. – jmbouffard Feb 10 '11 at 16:10
-
16i wonder what hypocrite wrote that? the android log is 98% full of messages from stock android apps and services. maybe what they meant was "disable all your logging so it won't clutter the log when we want to find our log messages." – Jeffrey Blattman Feb 10 '11 at 16:16
I would remove the logging code as below:
-assumenosideeffects class android.util.Log {
public static boolean isLoggable(java.lang.String, int);
public static int v(...);
public static int i(...);
public static int w(...);
public static int d(...);
public static int e(...);
public static java.lang.String getStackTraceString(java.lang.Throwable);
}
-assumenosideeffects class java.lang.Exception {
public void printStackTrace();
}
-assumenosideeffects class * implements org.slf4j.Logger {
public void trace(...);
public void debug(...);
public void info(...);
public void warn(...);
public void error(...);
public boolean isTraceEnabled(...);
public boolean isDebugEnabled(...);
public boolean isInfoEnabled(...);
public boolean isWarnEnabled(...);
public boolean isErrorEnabled(...);
}
If required, the error and warn categories may be retained. But be sure that optimization and shrinking is enabled for the build only then the code removal is effective

- 101
- 3