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

前端 未结 27 1415
有刺的猬
有刺的猬 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:27

    ProGuard will do it for you on your release build and now the good news from android.com:

    http://developer.android.com/tools/help/proguard.html

    The ProGuard tool shrinks, optimizes, and obfuscates your code by removing unused code and renaming classes, fields, and methods with semantically obscure names. The result is a smaller sized .apk file that is more difficult to reverse engineer. Because ProGuard makes your application harder to reverse engineer, it is important that you use it when your application utilizes features that are sensitive to security like when you are Licensing Your Applications.

    ProGuard is integrated into the Android build system, so you do not have to invoke it manually. ProGuard runs only when you build your application in release mode, so you do not have to deal with obfuscated code when you build your application in debug mode. Having ProGuard run is completely optional, but highly recommended.

    This document describes how to enable and configure ProGuard as well as use the retrace tool to decode obfuscated stack traces

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

    Christopher's Proguard solution is the best, but if for any reason you don't like Proguard, here is a very low-tech solution:

    Comment logs:

    find . -name "*\.java" | xargs grep -l 'Log\.' | xargs sed -i 's/Log\./;\/\/ Log\./g'
    

    Uncomment logs:

    find . -name "*\.java" | xargs grep -l 'Log\.' | xargs sed -i 's/;\/\/ Log\./Log\./g'
    

    A constraint is that your logging instructions must not span over multiple lines.

    (Execute these lines in a UNIX shell at the root of your project. If using Windows, get a UNIX layer or use equivalent Windows commands)

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

    I have used a LogUtils class like in the Google IO example application. I modified this to use an application specific DEBUG constant instead of BuildConfig.DEBUG because BuildConfig.DEBUG is unreliable. Then in my Classes I have the following.

    import static my.app.util.LogUtils.makeLogTag;
    import static my.app.util.LogUtils.LOGV;
    
    public class MyActivity extends FragmentActivity {
      private static final String TAG = makeLogTag(MyActivity.class);
    
      protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        LOGV(TAG, "my message");
      }
    }
    
    0 讨论(0)
  • 2020-11-22 08:28

    I have a very simple solution. I use IntelliJ for development, so the details vary but the idea should apply across all IDE's.

    I pick to root of my source tree, right-click and select to do "replace". I then choose to replace all "Log." with "//Log.". This removes all log statements. To put them back later I repeat the same replace but this time as replace all "//Log." with "Log.".

    Works just great for me. Just remember to set the replace as case sensitive to avoid accidents such as "Dialog.". For added assurance you can also do the first step with " Log." as the string to search.

    Brilliant.

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

    I know this is an old question, but why didn't you replace all your log calls with something like Boolean logCallWasHere=true; //---rest of your log here

    This why you will know when you want to put them back, and they won't affect your if statement call :)

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

    I suggest having a static boolean somewhere indicating whether or not to log:

    class MyDebug {
      static final boolean LOG = true;
    }
    

    Then wherever you want to log in your code, just do this:

    if (MyDebug.LOG) {
      if (condition) Log.i(...);
    }
    

    Now when you set MyDebug.LOG to false, the compiler will strip out all code inside such checks (since it is a static final, it knows at compile time that code is not used.)

    For larger projects, you may want to start having booleans in individual files to be able to easily enable or disable logging there as needed. For example, these are the various logging constants we have in the window manager:

    static final String TAG = "WindowManager";
    static final boolean DEBUG = false;
    static final boolean DEBUG_FOCUS = false;
    static final boolean DEBUG_ANIM = false;
    static final boolean DEBUG_LAYOUT = false;
    static final boolean DEBUG_RESIZE = false;
    static final boolean DEBUG_LAYERS = false;
    static final boolean DEBUG_INPUT = false;
    static final boolean DEBUG_INPUT_METHOD = false;
    static final boolean DEBUG_VISIBILITY = false;
    static final boolean DEBUG_WINDOW_MOVEMENT = false;
    static final boolean DEBUG_ORIENTATION = false;
    static final boolean DEBUG_APP_TRANSITIONS = false;
    static final boolean DEBUG_STARTING_WINDOW = false;
    static final boolean DEBUG_REORDER = false;
    static final boolean DEBUG_WALLPAPER = false;
    static final boolean SHOW_TRANSACTIONS = false;
    static final boolean HIDE_STACK_CRAWLS = true;
    static final boolean MEASURE_LATENCY = false;
    

    With corresponding code like:

        if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Log.v(
            TAG, "Adding window " + window + " at "
            + (i+1) + " of " + mWindows.size() + " (after " + pos + ")");
    
    0 讨论(0)
提交回复
热议问题