Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Removing Logging from Production Code in Android?

Tags:

android

What is the best way to remove logging from production android application. It appears that proguard does not do this completely, strings still get written, so I was wondering what is best solution to remove the logging from production code?

like image 236
Code Droid Avatar asked Apr 24 '12 18:04

Code Droid


People also ask

Why is it important to remove all debug log statements before releasing an app for general distribution and use?

Logs can lead to unauthorized access to your application or/and server. Such access can lead to very serious security problems (for example user data leaks).

What is e printStackTrace () in Android?

The printStackTrace() method in Java is a tool used to handle exceptions and errors. It is a method of Java's throwable class which prints the throwable along with other details like the line number and class name where the exception occurred.


5 Answers

The IMO best solution is to write code like below wherever you call your logging methods.

if (SOME_LOG_CONSTANT) Log.d(TAG, "event:" + someSlowToEvaluateMethod());

By changing 1 constant you strip away every logging that you don't want. That way the part behind if (false) should not even get into your .class file since the compiler can completely remove it (it is unreachable code).

This also means that you can exclude whole code blocks from your release software if you wrap them in that if. That's something even proguard can't do.

the SOME_LOG_CONSTANT can be BuildConfig.DEBUG if you use SDK Tools r17 and above. That constant is automatically changed for you depending on build type. Thx @Christopher

like image 110
zapl Avatar answered Nov 11 '22 02:11

zapl


Use Timber, it's a nice library to configure your logs: https://github.com/JakeWharton/timber

Example of use: Timber.d("Activity Created");

Example of configuration:

public class ExampleApp extends Application {
  @Override public void onCreate() {
   super.onCreate();

    if (BuildConfig.DEBUG) {
     Timber.plant(new DebugTree());
    } else {
     Timber.plant(new CrashReportingTree());
    }
  }




/** A tree which logs important information for crash reporting. */
 private static class CrashReportingTree extends Timber.Tree {
   @Override protected void log(int priority, String tag, String message, Throwable t) {
     if (priority == Log.VERBOSE || priority == Log.DEBUG) {
       return;
     }

     FakeCrashLibrary.log(priority, tag, message);

     if (t != null) {
       if (priority == Log.ERROR) {
         FakeCrashLibrary.logError(t);
       } else if (priority == Log.WARN) {
         FakeCrashLibrary.logWarning(t);
       }
     }
   }
 }
like image 28
Yair Kukielka Avatar answered Nov 11 '22 04:11

Yair Kukielka


Configuring Your Application for Release tells you to simply remove Log commands before releasing your application.

You can deactivate logging by removing calls to Log methods in your source files.

What I do is to create a proprietary static log method that reads a global boolean of something like this:

class MyLog {

    private static final boolean LOGGING = true; //false to disable logging

    public static void d(String tag, String message) {
        if (LOGGING) {
            Log.d(tag, message);
        }
    }

    /* ... same for v, e, w, i */
}

Use this everywhere you want to log.

MyLog.d("Tag", "This will only work with LOGGING true");
like image 6
tyler Avatar answered Nov 11 '22 03:11

tyler


I suggest you to see this Log extension class.

It enables you to have a fine control on logs. For example, you can disable all logs (thanks to a configuration file) or just the logs of some packages or classes.

Moreover, it adds some useful functionalities (for instance you don't have to pass a tag for each log).

like image 1
Donkey Avatar answered Nov 11 '22 02:11

Donkey


Simply add this method to your code and use Logd instead of Log.d

private static final String TAG = "your own tag to recognize log entries from this app";

public static void Logd(String txt) {
    if (BuildConfig.DEBUG&&BuildConfig.BUILD_TYPE.equals("debug")) Log.d(TAG,txt);
}

I know that the string will still be evaluated, but we are talking microseconds in extra processing time. Noone will ever notice a difference in app speed, unless you are doing many thousands of loggings in a loop.

The DEBUG and BUILD_TYPE are available and working in Android Studio. The DEBUG boolean is the "debuggable" option in the build.gradle file:

buildTypes {
    debug {
        debuggable true
        runProguard false
        proguardFile getDefaultProguardFile('proguard-android.txt')
    }
    release {
        debuggable false
        runProguard true
        proguardFile getDefaultProguardFile('proguard-android.txt')
    }
}

The BUILD_TYPE is set automatically to "debug" when you run in Android Studio.

So if you set debuggable to false OR the user has a release version, then logs will be gone.

like image 1
Martin B Avatar answered Nov 11 '22 04:11

Martin B