Musings on Android Development: Stripping Logging from your App

Clive Lee
3 min readNov 16, 2017

So I’ve read several posts online on how you should strip logging from your app for release builds. This itself is a great idea. I’d argue that it even has security implications, especially if you tend to leave logging statements in your codebase. I’ve also read some people suggesting that you use Proguard to strip logging.

I would strongly advise you to not do that.

Let me first explain how you can use Proguard to strip logging. To be clear, I’m first describing what you shouldn’t do. In your module-level build.gradle file (e.g. the ‘app’ android application module), you might have the following lines:

release {  
minifyEnabled true
proguardFiles
getDefaultProguardFile('proguard-android-optimize.txt'),
'your-proguard-rules.pro'
}

The getDefaultProguardFile('proguard-android-optimize.txt') grabs the default Proguard optimize file from your Android SDK installation. The your-proguard-rules.pro file would contain your custom Proguard rules. If you’re trying to strip logging statements, you may have added the following lines in your custom Proguard rules file:

-assumenosideeffects class android.util.Log { 
public static boolean isLoggable(java.lang.String, int);
public static int v(...);
public static int i(...);
...
}

What does this do, you may ask? According to the official Proguard documentation, this statement “[s]pecifies methods that don’t have any side effects (other than maybe returning a value). With some care, you can also use the option to remove logging code.” Which sounds like exactly what you need to remove logging, but did you catch the cautionary phrase “with some care?” Why should you be cautious when using this?

Here’s why. Suppose later on in the project, your release build stops working for some reason. More often then not, it’s likely due to some class being obfuscated when it shouldn’t be, such as for retrofit2 TypeAdapters. (Quick side note: with recent support libraries, you can use @Keep annotations, which will respect the `minifyEnabled` settings in gradle. I’d suggest using that going forward instead of using `-keep` statements in Proguard files, as there are other obfuscation tools you might want to use in the future. Google’s working on one as well, as Jake Wharton mentioned in his Droidcon UK talk!).

However, you may run into strange issues where Proguard’s optimization steps mess up your release build. If that happens, you have to modify your gradle file to not use the optimize version of the Proguard file. Instead, you might use the regular, non-optimize default Proguard file:

release {  
minifyEnabled true
proguardFiles
getDefaultProguardFile('proguard-android.txt'),
'your-proguard-rules.pro'
}

Side Note: if you can bear working on obfuscation and waiting for release builds, you really should try to include all of the optimizations in proguard-android-optimize.txt in your-proguard-rules.pro file that wont bork your release build.

Suppose you just fixed the release build by using proguard-android.txt. Guess what? You are now including logging statements in your release build again. Turns out that the default proguard-android.txt has the line -dontoptimize, and the lines that turn off logging, -assumenosideeffects are optimizations that get turned off. Furthermore, even if you did try to put most of the optimization settings from the default proguard-android-optimize.txtin your own Proguard file, you’ll still have the same issue if you ended up putting in the line -dontoptimize in your custom Proguard file or if you also use the default proguard-android.txt!

I hope it’s evident why using Proguard to strip logging is a bad idea. To put it succinctly, it’s relying on a setting specified in a file you don’t usually see (your custom .pro file) that is affected by a setting in other files you see even less (default Proguard files.)

So what should you use to strip logging? If you have a simple android-only project (cf. android + java/kotlin library project), I’d recommend Timber. It’s a Jake Wharton library and pretty simple to use and even comes with lint checks. I’m sure there are others out there.

If your project does have java or kotlin library modules, then you’ll have to be a bit fancier. And, conceptually, it’ll be cleaner to log based on build-type source sets instead of checking for BuildConfig fields, because that would mean you’re not including logging code at all in your production code.

But, oh my! Look at the time! I’ll save that little bit for the next post. Stay tuned!

--

--