i am using Dexguard in my android application to protect from
reverse engineering.Now in my application which is very big ,i have
used several places System.out.println in many classes in which i am
printing my server URL to debugg for my ease.Now when i am releasing
this application ,and this apk i am giving to other developers ,they
can see all the System.out.println things in their logcat. how
should i avoid that. This has serious issue.
First of all you shouldn't be using System.out.println directly everywhere. Use your own wrapper class for logging.
In dexguard/proguard you can use assumenosideeffects for removing codes that are unnecessary for release.
So for System.out.print you can add following in your dexguard rules.
-assumenosideeffects class java.io.PrintStream {
public void println(%);
public void println(**);
}
But this is risky as this class might be used for purposes other than logging.
Fastest way for you would be to use android.util.Log in place of System.out.print and then add following
-assumenosideeffects class android.util.Log {
public static boolean isLoggable(java.lang.String, int);
public static int v(...);
public static int i(...);
public static int w(...);
public static int d(...);
public static int e(...);
}
See proguard docs
good answer by #vKashyap, you might also want to add this as well...
-assumenosideeffects class java.lang.Exception {
public void printStackTrace();
}
Related
I need to strip down all my Timber logs in my production build. I have added the following in my proguard-project.txt :
-assumenosideeffects class timber.log.Timber* {
public static *** tag(...);
public static *** v(...);
public static *** i(...);
public static *** w(...);
public static *** d(...);
public static *** e(...);
-assumenosideeffects class timber.log.Timber.tag* {*;}
}
However only logs with the format Timber.e() or Timber.i() etc is being stripped. Logs with Timber.tag(..).i(...) are not getting stripped.
Is there any way to achieve this? Thank you
wouldn't it be easier to do something line
if (BuildConfig.DEBUG) {
Timber.plant(Timber.DebugTree())
}
in your Application subclass? This way you will the logs only in debug
Stripping Timber.tag(...) cannot be done via Proguard. According to the usage guide,
In the optimization step, ProGuard can then remove calls to such methods, if it can determine that the return values aren't used.
Since Timber.tag(...) will return a Timber.Tree object, Proguard optimizer will not strip it off for you. Therefore, if you really want to strip off the log, you have to wrap it via a function e.g.
fun printDebugLog(tag: String, message: String) {
Timber.tag(tag).d(message)
}
Then you can use -assumenosideeffects to strip off printDebugLog call. Another thing you have to be aware of that when your class is in Kotlin, the following rules cannot be used to strip off Timber logs also
-assumenosideeffects class timber.log.Timber* {
public static *** d(...);
public static *** v(...);
public static *** i(...);
}
This is because when you decompile the Kotlin class to Java, logging will actually translated to
Timber.Forest.d(...)
Which will not be stripped off for the similar reason.
I've a need to remove all logging from my release App type. I've tried configure proguard to do it for me. My configuration mostly match the one provided in here: proguard doesn't remove logs .
I've changed proguard-android.txt to proguard-android-optimize.txt but with no luck. After going through Proguard manual and checking output of :
-whyareyoukeeping class android.util.Log {
public static boolean isLoggable(java.lang.String, int);
public static int v(...);
public static int i(...);
public static int w(...);
public static int d(...);
public static int e(...);
public static int wtf(...);
}
learned that this couldn't be removed because of:
Explaining why classes and class members are being kept...
Printing usage to [...]...
android.util.Log
is a library class.
android.util.Log: boolean isLoggable(java.lang.String,int)
is a library method.
android.util.Log: int v(java.lang.String,java.lang.String)
is a library method.
android.util.Log: int v(java.lang.String,java.lang.String,java.lang.Throwable)
is a library method.
android.util.Log: int i(java.lang.String,java.lang.String)
is a library method.
android.util.Log: int i(java.lang.String,java.lang.String,java.lang.Throwable)
is a library method.
android.util.Log: int w(java.lang.String,java.lang.String)
is a library method.
android.util.Log: int w(java.lang.String,java.lang.String,java.lang.Throwable)
is a library method.
android.util.Log: int w(java.lang.String,java.lang.Throwable)
is a library method.
android.util.Log: int d(java.lang.String,java.lang.String)
is a library method.
android.util.Log: int d(java.lang.String,java.lang.String,java.lang.Throwable)
is a library method.
android.util.Log: int e(java.lang.String,java.lang.String)
is a library method.
android.util.Log: int e(java.lang.String,java.lang.String,java.lang.Throwable)
is a library method.
android.util.Log: int wtf(java.lang.String,java.lang.String)
is a library method.
android.util.Log: int wtf(java.lang.String,java.lang.Throwable)
is a library method.
android.util.Log: int wtf(java.lang.String,java.lang.String,java.lang.Throwable)
is a library method.
What could be reason for that? Maybe some other Proguard option? Is there any other option to enforce logs removal?
You need to specify that ProGuard should remove these logging calls using a configuration like that:
-assumenosideeffects class android.util.Log
{
public static int d(...);
public static int v(...);
public static int i(...);
public static int e(...);
}
Keep in mind that you need optimization to be enabled to actually remove these calls. For this use this default configuration:
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt')
With help of Guardsquare support I've been able to find out problem. One of libraries has -dontoptimize in its ProGuard config file. Helpful to narrow down this issue is option -printconfiguration [filename]
Doc. for ref - https://www.guardsquare.com/en/products/proguard/manual/usage#generaloptions
I had a strange bug which was hard to find :-(
In my Android app I use Retrofit2 with Moshi do access an api. I also use proguard-android-optimize.txt to make my app clean and small. And in my proguard-rules.pro I have:
-assumenosideeffects class timber.log.Timber { *; }
-assumenosideeffects class android.util.Log { *; }
With this combination I get this error stream was reset: null when I try to access the api.
To fix it I have to remove this assumenosideeffects lines from my proguard config. But why? Has anyone an idea why I get this network problem when proguard removes logging methods?
The wildcard * matches all methods, including methods in super classes, like Object#wait(). You don't really want to remove those invocations, so you should explicitly list the methods for which you want to remove the invocations:
-assumenosideeffects class android.util.Log {
public static boolean isLoggable(java.lang.String, int);
public static int v(...);
public static int i(...);
public static int w(...);
public static int d(...);
public static int e(...);
}
ProGuard already prints out a warning if you specify the wildcard.
I have a proguard.cfg file which contains several statements including optimization passes and logs suppression as :
-assumenosideeffects class android.util.Log { *; }
-assumenosideeffects class com.badlogic.gdx.Application {
public static void debug(...);
public static void error(...);
public static void log(...);
}
Calls to Log.* are correctly removed in the final output APK file. But gdx log calls are still in the code. For example I can still see things like that in the output :
Gdx.app.debug("debug()", "^");
Gdx.app.error("error()", "^");
Gdx.app.log("log()", "^");
I also tried to put this part of my config in a proguard-optimize.txt file as I have seen on similar questions and then setting the proper value in project.properties files like this : proguard.config=proguard-optimize.txt:proguard.txt but it doesn't work !
These calls get removed only if I put a general wildcard :
-assumenosideeffects class com.badlogic.gdx.Application {
*;
}
But I don't want to remove calls to other Application's static methods, like add* and get*() ones.
Optimization step is enabled (6 passes).
Gdx.app.debug is not static its an instance method (app is a static field of the Gdx class).
Try:
-assumenosideeffects class com.badlogic.gdx.Application {
public void debug(...);
public void error(...);
public void log(...);
}
Try something like this in your application's code:
Gdx.app.setLogLevel(Application.LOG_NONE);
That will prevent messages from being logged.
Cheers!
I have an application that uses a lot of Log.d() or Log.e() calls for debugging. Now I want to create my final package for release. The Android Export feature from Eclipse mentions to remove the "Debuggable" flag in the manifest, which I have done. Should I also comment all the Log calls to improve the performance of my application or these calls will do nothing in the non debuggable final version package ?
I have subclassed the Log class to a class called Trace, which mirrors methods on Log. So I do Trace.d(TAG,"blah") and then within the Trace.d method the code only executes based on a static final class variable called LOGGING_LEVEL, which has levels 1-5 (none, errors only, errors & warnings, errors & warnings & info, and everything including debug) . When producing a production APK, Proguard removes all the code that isn't used in the application, so it does it for me.
For me, logging is far too important to remove from the source, but it must be removed from the production application, for performance, secure and intellectual property reasons.
This structure allows me to add a lot MORE logging to the application, which makes debugging problems much easier, but with no impact whatsoever on the production APK
public class Trace
{
public static final int NONE = 0;
public static final int ERRORS_ONLY = 1;
public static final int ERRORS_WARNINGS = 2;
public static final int ERRORS_WARNINGS_INFO = 3;
public static final int ERRORS_WARNINGS_INFO_DEBUG = 4;
private static final int LOGGING_LEVEL = ERRORS_ONLY; // Errors + warnings + info + debug (default)
public static void e(String tag, String msg)
{
if ( LOGGING_LEVEL >=1) Log.e(tag,msg);
}
public static void e(String tag, String msg, Exception e)
{
if ( LOGGING_LEVEL >=1) Log.e(tag,msg,e);
}
public static void w(String tag, String msg)
{
if ( LOGGING_LEVEL >=2) Log.w(tag, msg);
}
public static void i(String tag, String msg)
{
if ( LOGGING_LEVEL >=3) Log.i(tag,msg);
}
public static void d(String tag, String msg)
{
if ( LOGGING_LEVEL >=4) Log.d(tag, msg);
}
}
This made me check my assumption that the log.d lines in the code would somehow not appear on a signed release apk without the debuggable flag set in the manifest, I was wrong, they still appear.
A quick search on SO led me to the accepted answer to this question:
Remove all debug logging calls before publishing: are there tools to do this?
It works very well and you don't have to change any code.
From developer.android.com:
Turn off logging and debugging and clean up data/files For release, you
should make sure that debug facilities
are turned off and that debug and
other unnecessary data/files are
removed from your application project.
Remove the android:debuggable="true"
attribute from the
element of the manifest. Remove log
files, backup files, and other
unnecessary files from the application
project. Check for private or
proprietary data and remove it as
necessary. Deactivate any calls to Log
methods in the source code.
Source
I would remove the logging code as below:
-assumenosideeffects class android.util.Log {
public static boolean isLoggable(java.lang.String, int);
public static int v(...);
public static int i(...);
public static int w(...);
public static int d(...);
public static int e(...);
public static java.lang.String getStackTraceString(java.lang.Throwable);
}
-assumenosideeffects class java.lang.Exception {
public void printStackTrace();
}
-assumenosideeffects class * implements org.slf4j.Logger {
public void trace(...);
public void debug(...);
public void info(...);
public void warn(...);
public void error(...);
public boolean isTraceEnabled(...);
public boolean isDebugEnabled(...);
public boolean isInfoEnabled(...);
public boolean isWarnEnabled(...);
public boolean isErrorEnabled(...);
}
If required, the error and warn categories may be retained. But be sure that optimization and shrinking is enabled for the build only then the code removal is effective