57

Shutting off my own app's LogCat output before releasing an app to the market is straightforward. I also know how to selectively filter LogCat message by tag and/or id for my own debug convenience.

But now I am interested in something that may be much more difficult (perhaps impossible?): Disable all LogCat output, including & especially those coming from 3rd-party services like TtsService, GoogleLoginService, etc.

Is this possible?

To further clarify: I am not interested in filtering out messages for myself. I am rather interested in disabling 3rd-party messages for whoever downloads my app from the Android Market. Is this possible?

Android Eve
  • 14,864
  • 26
  • 71
  • 96
  • 2
    So you want to prevent *any app on the user's device* from writing LogCat output? – eldarerathis Apr 05 '11 at 14:07
  • 2
    Do you mean the log messages of those third-party libraries that you include (or use) from your app? – Rajath Apr 05 '11 at 14:11
  • @eldarerathis No, I want to prevent any app that is directly or indirectly being **used by my app**, from writing LogCat output. Sorry for not being clear enough. – Android Eve Apr 05 '11 at 14:21
  • @Rajath DSouza Yes, that's exactly what I mean. I don't care about what other apps are showing when they work independently or used by other apps. I only care about them outputing stuff in response to my app's requestes/calls. – Android Eve Apr 05 '11 at 14:23
  • Okay, that makes more sense... – eldarerathis Apr 05 '11 at 14:42

8 Answers8

197

You can use ProGuard to remove completely any lines where a return value is not used, by telling ProGuard to assume that there will be no problems.

The following proguard.cfg chunk instructs to remove Log.d, Log.v and Log.i calls.

-assumenosideeffects class android.util.Log {
    public static *** d(...);
    public static *** w(...);
    public static *** v(...);
    public static *** i(...);
}

The end result is that these log lines are not in your release apk, and therefore any user with logcat won't see d/v/i logs.

Marcin Orlowski
  • 72,056
  • 11
  • 123
  • 141
David Snabel-Caunt
  • 57,804
  • 13
  • 114
  • 132
  • 1
    This tip is incredible. It already deserves a +1. I will accept the answer after making sure that it indeed yields the desired result in my app. Thank you! – Android Eve Apr 05 '11 at 14:25
  • 2
    ProGuard is really powerful! You can also use this tip to remove other forms of development code, not just logging. – David Snabel-Caunt Apr 05 '11 at 14:35
  • in what other scenarios might we want to remove code? And what forms? – Rajath Apr 05 '11 at 14:48
  • 1
    Code that enables developer features, like additional menu options, perhaps. Logging is the only common thing I can think of that you SHOULD remove. – David Snabel-Caunt Apr 05 '11 at 15:36
  • I finally got to testing your solution. It works beautifully. :) – Android Eve May 11 '11 at 03:57
  • 1
    Will this affect line numbers when trying to match up stacktraces? I've seen some people say it only affects bytecode, so lines will still match, and others say otherwise. Can anyone confirm? – Tony Chan Apr 18 '12 at 01:12
  • 1
    I added that lines in proguard-project.txt and `proguard.config=proguard-project.txt` to `project.properties` and with device connected into PC with Eclipse opened i can always retrieve Logs. Is that normal ? – androniennn Dec 23 '12 at 22:36
  • 12
    You need to be careful with this because you add a comment like Log.d(someStrVar + " sensitive info here"); the sensitive info string will still make it into the classes.dex file in the APK. Because Proguard has issues with optimisation when stringbuilder is used implicitly – pt123 Aug 07 '13 at 11:32
  • They warn in proguard.cfg about problems with allowing proguard optimization and dex. I wasn't able to run it as is. Since I only needed proguard to remove logs, restricting optimization option to removal worked for me (in case someone has similar situation: -optimizations code/removal/* – minsk Dec 07 '13 at 08:29
  • 1
    You have to use proguard-android-optimize.txt, if you want the assumenosideeffects settings to work. In android studio: proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' – phnmnn Jun 02 '16 at 14:06
  • @DavidCaunt Is there any way to hide native layer logs? – 0xAliHn Nov 07 '16 at 16:49
  • I don't know, but I don't think ProGuard is the way to silence native logs – it removes logs from your own code by literally removing the logging calls. – David Snabel-Caunt Nov 07 '16 at 17:07
  • @DavidCaunt, Could you plz verify again whether this works or not. Cause IMHO this piece of code does not work anymore. You will have to specify the exact return type ie. int instead of ***. Plz refer - http://stackoverflow.com/a/13327603/1554935 – Ritesh Gune Dec 20 '16 at 22:13
  • 5
    THIS SHOULD BE ADDED TO THE ANSWER! As @phnmnn said - the following line should be set to the grade.build file: proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' – rubmz Jan 24 '17 at 12:45
9

if you don't use proguard, you have to manage the log yourself and in the manifest file make dubuggable false

<application
    android:name="MyApplication"
    android:icon="@drawable/gift"
    android:label="@string/app_name" android:debuggable="@bool/build_log">

Here my custom log class

public class Lol {

    public static final boolean ENABLE_LOG = true & MyApplication.sDebug;

    private static final boolean DEBUG = true & ENABLE_LOG;

    private static final boolean VERBOSE = true & ENABLE_LOG;

    private static final boolean TEMP = true & ENABLE_LOG;

    private static final boolean WARNING = true & ENABLE_LOG;

    private static final boolean INFO = true & ENABLE_LOG;

    private static final boolean ERROR = true & ENABLE_LOG;

    public static void obvious(String tag, String msg) {
        if (DEBUG) {
            msg = "*********************************\n" + msg
                    + "\n*********************************";
            Log.d(tag, msg);
        }
    }

    public static void d(String tag, String msg) {
        if (DEBUG)
            Log.d(tag, msg);
    }

    public static void d(boolean bool, String tag, String msg) {
        if (TEMP&bool)
            Log.d(tag, msg);
    }

    public static void i(String tag, String msg) {
        if (INFO)
            Log.i(tag, msg);
    }

    public static void e(String tag, String msg) {
        if (ERROR)
            Log.e(tag, msg);
    }

    public static void e(boolean bool, String tag, String msg) {
        if (TEMP&bool)
            Log.e(tag, msg);
    }

    public static void v(String tag, String msg) {
        if (VERBOSE)
            Log.v(tag, msg);
    }

    public static void w(String tag, String msg) {
        if (WARNING)
            Log.w(tag, msg);
    }

    public static String getStackTraceString(Exception e) {
        return Log.getStackTraceString(e);
    }

    public static void w(String tag, String msg, Exception e) {
        if (WARNING)
            Log.w(tag, msg,e);
    }
}
Win Myo Htet
  • 5,377
  • 3
  • 38
  • 56
  • 8
    Since [SDK Tools 8](http://developer.android.com/sdk/tools-notes.html) it has not been necessary to set the android:debuggable flag manually. This removes the risk of shipping a debuggable release. – David Snabel-Caunt Apr 18 '12 at 10:44
  • 5
    Just curious (I stumbled upon this question just now), is there any reason why you use `true & ENABLE_LOG` instead of only `ENABLE_LOG`? I don't see any difference functionality wise... – Andrew T. Nov 09 '15 at 08:24
  • you're still trying to call functions and send arguments, don't think it' a good idea, just better to use `if (BuildConfig.DEBUG) Log.i(TAG, msg);` – user25 Mar 24 '18 at 16:37
3

The great answer provided by David Caunt doesn't seem to work for the rules defined in proguard-android-optimize.txt.

Instead of using the wildcard ***, current versions of ProGuard seem to expect the return parameter's type qualifier:

-assumenosideeffects class android.util.Log {
    public static int   d(...);
    public static int   w(...);
    public static int   v(...);
    public static int   i(...);
    public static int wtf(...);
}
Mapsy
  • 4,192
  • 1
  • 37
  • 43
3

In app build.gradle file set:

release {
    minifyEnabled true
     ……
}

In proguard-rules.pro put:

-assumenosideeffects class android.util.Log {
  public static *** v(...);
  public static *** d(...);
  public static *** i(...);
  public static *** w(...);
  public static *** e(...);
}
-ignorewarnings

It worked for me.

snehal
  • 181
  • 1
  • 10
0

I usually do next:

if (BuildConfig.DEBUG) Log.i(TAG, msg);

though if you have a lot of dependencies (libraries) and they written bad then yeah just use https://stackoverflow.com/a/5553290/4548520

making lines shorter:

private final static boolean DEBUG = BuildConfig.DEBUG;

if (DEBUG) Log.i(TAG, msg_1);

if (DEBUG) Log.e(TAG, msg_error_2);
user25
  • 2,873
  • 2
  • 30
  • 66
0

I combined David Snabel-Caunt's accepted answer in addition to swapping out the default ProGuard settings ("proguard-android.txt" file) from the Android SDK for the "proguard-android-optimize.txt" optimized file. The file is also available in this Android SDK folder with the same rules but with optimizations enabled.

0

Instead of enumerating all the class's methods it looks like you can also simply use the <methods> shorthand :

-assumenosideeffects class a.b.c.DebugLogs {
    <methods>;
}

Worked for me with com.android.tools.build:gradle version 4.0.0.

Mickäel A.
  • 9,012
  • 5
  • 54
  • 71
-1

You can put debuggable false on buildTypes release.

buildTypes {

     release {
        debuggable false
        ...
     }

}
heronsanches
  • 524
  • 7
  • 12