I'm using proguard to obfuscate a (SDK) jar file I've created.
The SDK contains a Java Service, a statically compiled C++ lib and a SWIG (ver 2) interface via which the Service and the lib communicates.
I've added relevant '-keep' and '-keepclasseswithmembernames,includedescriptorclasses' statements to the configuration file.
But one file keeps getting (partially) obfuscated.
The first part of the proguard config looks like this (all collected from the net):
-libraryjars '/Library/DevTools/adt-bundle-mac-x86_64-20140702/sdk/platforms/android-21/android.jar'
-libraryjars 'libs/android-support-v4.jar'
-libraryjars "libs/armeabi-v7a/libnativesdk.so"
-dontskipnonpubliclibraryclasses
-injars bin/mysdklib.jar
-verbose
-dontshrink
-dontoptimize
-dontusemixedcaseclassnames
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-keepclasseswithmembernames class * {
native <methods>;
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
My specific classes addition looks like this:
-keepclasseswithmembernames,includedescriptorclasses class com.company.MySdkIfJNI{
private final static native void swig_module_init();
public static *;
public final static native <methods>;
}
-keepclasseswithmembernames,includedescriptorclasses class com.company.MySdkWrapper{
public *;
}
-keep class com.company.IntWrapper
-keep class com.company.StatisticsParcel{
public *;
}
-keep class com.company.JNILibCallbacks
All the classes I keep works fine. The problem is with the 'MySdkIfJNI' class.
This is an Swig (http://www.swig.org/) auto-generated interface between the native lib and the Java service.
I tried various configurations in order to keep this class as is but proguard keeps obfuscating it.
I tried '-keep' , '-keepclasseswithmembernames,includedescriptorclasses', '-keepclasseswithmembernames'
-keepclasseswithmembernames,includedescriptorclasses class com.company.MySdkIfJNI{
private final static native void swig_module_init();
public static *;
public final static native <methods>;
*;
}
both with arguments and without arguments
But after proguard finishes (without any errors / warnings) I find out that only part of the methods has been obfuscated.
The native methods are kept, such as:
public final static native void JniMYSdkClient_setLogLevel(long jarg1, JniMYSdkClient jarg1_, int jarg2);
public final static native void delete_JniMYSdkClient(long jarg1);
But all the Java methods that starts with SwigDirector are obfuscated, such as:
public static void SwigDirector_JNIMyCallbacks_onEvent(JNIMyCallbacks self, int accountId, int eventId, String sessionId, String msg) {
self.onEvent(accountId, eventId, sessionId, msg);
}
This obfuscation causes the Native swig interface to fail finding this callback methods and my lib crashes.
Any ideas of how can I keep this specific class AS-IS ?
Thanks in advance,
Or Pol.
Well, I didn't find any solution to the particular SWIG methods but since the SWIG wrapping code is already really messy I have decided it doesn't have to be obfuscated with Proguard.
I moved the SWIG interface to an external JAR file and imported it as '-libraryjars'
Now the native layer finds this methods and everything works perfect.
Thanks anyway!
Best regards,
Or.
Swig callbacks need to be keep from obfuscation.
First try to keep all generated java files by swig and compile and see. Crash will fix. Like below
-keep com.custom.project** { *; }
-dontwarn com.custom.project**
Next maximize your files for obfuscation.
Hope it helps.
Related
Why android studio can´t infer which classes do we need so the other´s can be removed using shrink?
Why do we need to write manually which classes should be kept?
ProGuard is a general-purpose Java development tool. It knows nothing about classes that might be referred to from the Android manifest, layout resources, menu resources, preference XML, and so on.
More generally, ProGuard has no way of reliably determining what classes are loaded via reflection, which is how all of the above is implemented. For those classes, you need to teach ProGuard to keep them.
Also the "update project" command from /ANDROID_SDK/tools/android will generate a proguard with common classes that should be kept.
The default is enough for most applications.
You should add Innerclasses that are used as listener of JavaScript on WebViews.
And the cases you find that you will need names (reflections or anything else)
The default proguard.cfg looks like this:
-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-keep public class com.android.vending.licensing.ILicensingService
-keepclasseswithmembernames class * {
native <methods>;
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
I have a problem with obfuscation on card.io.
I'm changing the strings on strings.xml with the tags given on card.io official page and while I'm debugging, the app uses the changed strings. But when i export signed apk with proguard, the app uses its own strings. Could you help me? What am I missing?
This is my proguard.cfg content: (I use the sample app's proguard file.)
-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-keepclasseswithmembernames class * {
native <methods>;
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
-keep class io.card.**
-keepclassmembers class io.card.** {
*;
}
## Good practice so that you don't end up logging sensitive info.
# Remove debug, verbose, and info Log calls
-assumenosideeffects class android.util.Log {
public static *** d(...);
public static *** v(...);
public static *** i(...);
## Uncomment to remove warnings and errors as well
# public static *** w(...);
# public static *** e(...);
}
Jeff from card.io here.
card.io no longer supports the strings.xml file as of version 3.1.0+, because the SDK provides translations. Are you using the latest version?
If not, please download the latest SDK. You can either rely on the device language settings to automatically bring up the correct localizations, or force a locale with CardIOActivity.EXTRA_LANGUAGE_OR_LOCALE (see javadocs).
To add to Jeff's response, if there's a problem with a translation, we'd like to fix it! Please file bugs here.
I've also updated the example app to remove the strings examples. Thanks for letting us know that it was out of date.
My application has many activities and uses native library too. With the default ProGuard configuration which Eclipse generates ProGuard removes many things - OnClick methods, static members, callback methods which my native library uses... Is it there a simple way to instruct ProGuard to NOT remove anything from my package? Removing things saves only about 2.5% of the application size, but breaks my application completely. Configuring, testing and maintaining it class by class in ProGuard configuration would be a pain.
EDIT This answer is 10 years old - it may not apply to newer proguard versions.
I think you need to add these flags at the very least (modify for you individual package names):
-keep class javax.** { *; }
-keep class org.** { *; }
-keep class twitter4j.** { *; }
Also, add these flags:
-dontshrink
-dontoptimize
-dontpreverify
Here's my whole config file: of my Proguard.cfg:
-dontshrink
-dontoptimize
-dontpreverify
-verbose
-dontwarn javax.management.**
-dontwarn java.lang.management.**
-dontwarn org.apache.log4j.**
-dontwarn org.apache.commons.logging.**
-dontwarn org.slf4j.**
-dontwarn org.json.**
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-keep public class com.android.vending.licensing.ILicensingService
-keep class javax.** { *; }
-keep class org.** { *; }
-keep class twitter4j.** { *; }
-keepclasseswithmembernames class * {
native <methods>;
}
-keepclasseswithmembernames class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembernames class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
As final result I found that just keeping all class members is not enough for the correct work of my application, nor necessary. I addded to the settings file this:
-keepclasseswithmembers class * {
void onClick*(...);
}
-keepclasseswithmembers class * {
*** *Callback(...);
}
The case with onClick* is for all methods which I address in android:onClick atribute in .xml layout files (I begin the names of all such methods with 'onClick').
The case with *Callback is for all callback methods which I call from my native code (through JNI). I place a suffix 'Callback' to the name of every such method.
Also I added few rows for some special cases with variables which I use from native code, like:
-keep class com.myapp.mypackage.SomeMyClass {
*** position;
}
(for a varible with name 'position' in a class with name 'SomeMyClass' from package com.myapp.mypackage)
All this is because these onClick, callback etc. must not only be present but also kept with their original names. The other things ProGuard can optimize freely.
The case with the native methods is important also, but for it there was a declaration in the generated from Eclipse file:
-keepclasseswithmembernames class * {
native <methods>;
}
I know this is an old question but I hope that the following information might help other people.
You can prevent ProGuard from removing anything in a certain package as follows;
-keep,allowoptimization,allowobfuscation class com.example.mypackage.** { *; }
Using the modifiers allowoptimization and allowobfuscation will make sure that ProGuard still obfuscates and optimizes the code. Shrinking will of course be disabled as intended.
You can easily verify how these -keep rules affect the code without the need to (re-)build using the ProGuard Playground.
I have the following code in my application's proguard.cfg (and yes, I also have proguard.config=proguard.cfg in build.properties):
-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-keep public class com.android.vending.licensing.ILicensingService
-keepclasseswithmembernames class * {
native <methods>;
}
-keepclasseswithmembernames class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembernames class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
Yet, I was surprised to see an error report from the Android Market containing Unobfuscated symbols in the stack trace.
I know I uploaded an ProGuard exported version, so what did I miss?
If your stack trace included unobfuscated class names and methods specified in the --keep statements in your proguard.cfg, then the answer is in the body of your question...
Also note that due to the challenges posed by reflection, ProGuard automatically keeps the following:
Class.forName("SomeClass")
SomeClass.class
SomeClass.class.getField("someField")
SomeClass.class.getDeclaredField("someField")
SomeClass.class.getMethod("someMethod", new Class[] {})
SomeClass.class.getMethod("someMethod", new Class[] { A.class })
SomeClass.class.getMethod("someMethod", new Class[] { A.class, B.class })
SomeClass.class.getDeclaredMethod("someMethod", new Class[] {})
SomeClass.class.getDeclaredMethod("someMethod", new Class[] { A.class })
SomeClass.class.getDeclaredMethod("someMethod", new Class[] { A.class, B.class })
AtomicIntegerFieldUpdater.newUpdater(SomeClass.class, "someField")
AtomicLongFieldUpdater.newUpdater(SomeClass.class, "someField")
AtomicReferenceFieldUpdater.newUpdater(SomeClass.class, SomeType.class, "someField")
Also note that if you somehow provide the file proguard/mapping.txt generated by ProGuard, the tool ReTrace can un-obfuscate everything.
In short, you don't need to put anything in proguard.cfg to enable obfuscation. The default options are sufficient. Theoretically, you may want to remove some of the default --keep options but ProGuard's documentation specifically states that:
For proper results, you should at least be somewhat familiar with the
code that you are processing. Obfuscating code that performs a lot of
reflection may require trial and error, especially without the
necessary information about the internals of the code.
I'm developing apps for Android and using Proguard to obfuscate the code.
Currently i'm using ProGuard configurations:
-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class com.android.vending.licensing.ILicensingService
To maintain custom components names that are used on layouts XML:
-keep public class custom.components.**
To remove debug logs:
-assumenosideeffects class android.util.Log {
public static *** d(...);
public static *** v(...);
}
To avoid changing names of methods invoked on layout's onClick:
-keepclassmembers class * {
public void onClickButton1(android.view.View);
public void onClickButton2(android.view.View);
public void onClickButton3(android.view.View);
}
-keepclasseswithmembernames class * {
native <methods>;
}
-keepclasseswithmembernames class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembernames class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
The question is (are):
Are any other tags recommended? Why and what for?
It's possible to make a comment on a proguard.cfg file? I would like to have it with comments for what some lines are doing so that other developers don't have doubts about why i added.
Also in proguard, is it possible to maintain the comment header of a file (with the copyright)? If it's not, or it's not a good policy where should i add the copyright?
Android SDK (r20 or higher)
Please check the predefined proguard.config refered in project.properties
proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt
More info: http://proguard.sourceforge.net/manual/examples.html#androidapplication
Here you can check a proguard "default" file that I keep updating: https://medium.com/code-procedure-and-rants/android-my-standard-proguard-ffeceaf65521
Android SDK (r19 or lower)
Based on my answer Enabling ProGuard in Eclipse for Android I've ended up with this generic file. I've added comments to remember what each line is for. It might help people out there so here it is:
-optimizationpasses 5
#When not preverifing in a case-insensitive filing system, such as Windows. Because this tool unpacks your processed jars, you should then use:
-dontusemixedcaseclassnames
#Specifies not to ignore non-public library classes. As of version 4.5, this is the default setting
-dontskipnonpubliclibraryclasses
#Preverification is irrelevant for the dex compiler and the Dalvik VM, so we can switch it off with the -dontpreverify option.
-dontpreverify
#Specifies to write out some more information during processing. If the program terminates with an exception, this option will print out the entire stack trace, instead of just the exception message.
-verbose
#The -optimizations option disables some arithmetic simplifications that Dalvik 1.0 and 1.5 can't handle. Note that the Dalvik VM also can't handle aggressive overloading (of static fields).
#To understand or change this check http://proguard.sourceforge.net/index.html#/manual/optimizations.html
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
#To repackage classes on a single package
#-repackageclasses ''
#Uncomment if using annotations to keep them.
#-keepattributes *Annotation*
#Keep classes that are referenced on the AndroidManifest
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class com.android.vending.licensing.ILicensingService
#To remove debug logs:
-assumenosideeffects class android.util.Log {
public static *** d(...);
public static *** v(...);
}
#To avoid changing names of methods invoked on layout's onClick.
# Uncomment and add specific method names if using onClick on layouts
#-keepclassmembers class * {
# public void onClickButton(android.view.View);
#}
#Maintain java native methods
-keepclasseswithmembernames class * {
native <methods>;
}
#To maintain custom components names that are used on layouts XML.
#Uncomment if having any problem with the approach below
#-keep public class custom.components.package.and.name.**
#To maintain custom components names that are used on layouts XML:
-keep public class * extends android.view.View {
public <init>(android.content.Context);
public <init>(android.content.Context, android.util.AttributeSet);
public <init>(android.content.Context, android.util.AttributeSet, int);
public void set*(...);
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}
#Maintain enums
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
#To keep parcelable classes (to serialize - deserialize objects to sent through Intents)
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
#Keep the R
-keepclassmembers class **.R$* {
public static <fields>;
}
###### ADDITIONAL OPTIONS NOT USED NORMALLY
#To keep callback calls. Uncomment if using any
#http://proguard.sourceforge.net/index.html#/manual/examples.html#callback
#-keep class mypackage.MyCallbackClass {
# void myCallbackMethod(java.lang.String);
#}
#Uncomment if using Serializable
#-keepclassmembers class * implements java.io.Serializable {
# private static final java.io.ObjectStreamField[] serialPersistentFields;
# private void writeObject(java.io.ObjectOutputStream);
# private void readObject(java.io.ObjectInputStream);
# java.lang.Object writeReplace();
# java.lang.Object readResolve();
#}
For standard builds with Ant or Eclipse, the Android SDK (r20 or higher) already provides a suitable configuration, referenced by the property proguard.config in the file project.properties (as Michal points out in his answer). In older releases, you always had to specify your own complete configuration, so older advice (like the first answer) can lead to some confusion.
For custom builds, you can find the latest recommended configuration in the ProGuard manual > Examples > A complete Android application. The Proguard distribution also contains a sample file examples/android.pro
Notably, you may want to preserve annotations, and setters in View extensions.
You can add comments after a hash character '#', as extensively done in the sample files.
In your project file called project.properties, set following value:
proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt
This will take the latest version of Proguard settings from Android SDK.