How to remove all debug logging calls before building the release version of an Android app?

前端 未结 27 1472
有刺的猬
有刺的猬 2020-11-22 07:39

According to Google, I must \"deactivate any calls to Log methods in the source code\" before publishing my Android app to Google Play. Extract from section 3 of th

相关标签:
27条回答
  • 2020-11-22 08:11

    Per android.util.Log provides a way to enable/disable log:

    public static native boolean isLoggable(String tag, int level);
    

    Default the method isLoggable(...) returns false, only after you setprop in device likes this:

    adb shell setprop log.tag.MyAppTag DEBUG
    

    It means any log above DEBUG level can be printed out. Reference android doc:

    Checks to see whether or not a log for the specified tag is loggable at the specified level. The default level of any tag is set to INFO. This means that any level above and including INFO will be logged. Before you make any calls to a logging method you should check to see if your tag should be logged. You can change the default level by setting a system property: 'setprop log.tag. ' Where level is either VERBOSE, DEBUG, INFO, WARN, ERROR, ASSERT, or SUPPRESS. SUPPRESS will turn off all logging for your tag. You can also create a local.prop file that with the following in it: 'log.tag.=' and place that in /data/local.prop.

    So we could use custom log util:

    public final class Dlog 
    {
        public static void v(String tag, String msg)
        {
            if (Log.isLoggable(tag, Log.VERBOSE))
                Log.v(tag, msg);
        }
    
        public static void d(String tag, String msg)
        {
            if (Log.isLoggable(tag, Log.DEBUG))
                Log.d(tag, msg);
        }
    
        public static void i(String tag, String msg)
        {
            if (Log.isLoggable(tag, Log.INFO))
                Log.i(tag, msg);
        }
    
        public static void w(String tag, String msg)
        {
            if (Log.isLoggable(tag, Log.WARN))
                Log.w(tag, msg);
        }
    
        public static void e(String tag, String msg)
        {
            if (Log.isLoggable(tag, Log.ERROR))
                Log.e(tag, msg);
        }
    }
    
    0 讨论(0)
  • 2020-11-22 08:11

    Why not just do

    if(BuildConfig.DEBUG)
      Log.d("tag","msg");
    

    ? No additional libraries needed, no proguard rules which tend to screw up the project and java compiler will just leave out bytecode for for this call when you make release build.

    0 讨论(0)
  • 2020-11-22 08:11

    my Way:

    1) enable Column Selection Mode (alt+shift+insert)

    2) select on one Log.d(TAG, "text"); the part 'Log.'

    3) then do shift + ctrl + alt + j

    4) click left arrow

    5) do shift+end

    6) hit delete.

    this removes all LOG calls at once in a java file.

    0 讨论(0)
  • 2020-11-22 08:13

    As zserge's comment suggested,

    Timber is very nice, but if you already have an existing project - you may try github.com/zserge/log . It's a drop-in replacement for android.util.Log and has most of the the features that Timber has and even more.

    his log library provides simple enable/disable log printing switch as below.

    In addition, it only requires to change import lines, and nothing needs to change for Log.d(...); statement.

    if (!BuildConfig.DEBUG)
        Log.usePrinter(Log.ANDROID, false); // from now on Log.d etc do nothing and is likely to be optimized with JIT
    
    0 讨论(0)
  • 2020-11-22 08:14

    I find a far easier solution is to forget all the if checks all over the place and just use ProGuard to strip out any Log.d() or Log.v() method calls when we call our Ant release target.

    That way, we always have the debug info being output for regular builds and don't have to make any code changes for release builds. ProGuard can also do multiple passes over the bytecode to remove other undesired statements, empty blocks and can automatically inline short methods where appropriate.

    For example, here's a very basic ProGuard config for Android:

    -dontskipnonpubliclibraryclasses
    -dontobfuscate
    -forceprocessing
    -optimizationpasses 5
    
    -keep class * extends android.app.Activity
    -assumenosideeffects class android.util.Log {
        public static *** d(...);
        public static *** v(...);
    }
    

    So you would save that to a file, then call ProGuard from Ant, passing in your just-compiled JAR and the Android platform JAR you're using.

    See also the examples in the ProGuard manual.


    Update (4.5 years later): Nowadays I used Timber for Android logging.

    Not only is it a bit nicer than the default Log implementation — the log tag is set automatically, and it's easy to log formatted strings and exceptions — but you can also specify different logging behaviours at runtime.

    In this example, logging statements will only be written to logcat in debug builds of my app:

    Timber is set up in my Application onCreate() method:

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

    Then anywhere else in my code I can log easily:

    Timber.d("Downloading URL: %s", url);
    try {
      // ...
    } catch (IOException ioe) {
      Timber.e(ioe, "Bad things happened!");
    }
    

    See the Timber sample app for a more advanced example, where all log statements are sent to logcat during development and, in production, no debug statements are logged, but errors are silently reported to Crashlytics.

    0 讨论(0)
  • 2020-11-22 08:14

    Here is my solution if you don't want to mess with additional libraries or edit your code manually. I created this Jupyter notebook to go over all java files and comment out all the Log messages. Not perfect but it got the job done for me.

    0 讨论(0)
提交回复
热议问题