I would like proguard to obfuscate classnames. I have this line in Proguard.cfg
-keepclasseswithmembers class * {
public static <fields>;
}
-keepnames class * implements java.io.Serializable
-keep public class com.google.**
And I notice that what is not obfuscated is the class names. So running jdgui i see
com/test/abcd/ActualClass.java
public class ActualClassName extends Activity etc
moreover I see methods returning real classnames. like
ActualClassname aa();
and imports statements like
import com.abcd.ActualClassName
How do I get Proguard to obfuscate the classname itself. Its not just for Activities that I see this my Adapters are not being obfuscated. Well there is obfuscation going on but not class names.
Is the rules above what prevents the class names from being obfuscated?
Update: i have since removed the rules above and a Utility class that does not extend anything from Android is not being obfuscated. I'm now wondering if there is some implicit rule about keeping class names of classes that are referenced from classes that are being kept like Activity derivied classes? The classes whose names are not being obfuscated have a few things in common:
1) Static methods
2) Import of other types which are kept like those deriving from activity or serializable.
3) They have methods with parameters of other classes (Some of which might need to be kept).
However there is no where that I am specifically requesting that these utility classes should be kept.
There are several class that appear in your code that must retain the same fully qualified class name in order for android to be able to find them. One example as above are all Activity classes, as they are defined in the manifest by their full name as a String. If proguard were to rename the class then Android would no longer be able to find them.
The typical Proguard config will refer to the Proguard config in the Android SDK which will include several important lines like this one:
-keep public class * extends android.app.Activity
I think your problem is coming from your first line: '-keepclasseswithmembers' includes the class name, so in your case any class with a static field will keep its name. Changing it to simply '-keepclassmembers' will obfuscate the class names while leaving the static fields intact(which I'm assuming you want to do).
That said, I'm not sure why you want to do this, though. If you're trying to preserve the static variable names, shouldn't you want to preserve the class names as well, seeing as how that's how you'll be accessing the static fields? Why are you trying to preserve all of your static variable names?
Related
For the following Proguard rule(take Kotlin Serialization)
-if #kotlinx.serialization.Serializable class **
-keepclassmembers class <1> {
static <1>$Companion Companion;
}
Here what is the meaning of -if in context with the above rule? I tried looking into official proguard documentation but couldn't find easy to any info around that
I wrote those ProGuard rules. :) The pull request discussion about these changes may provide relevant background.
I understand your confusion, the ProGuard rules documentation is quite sparse.
-if class_specification
Specifies classes and class members that must be present to activate the subsequent keep option (-keep,
-keepclassmembers,...). The condition and the subsequent keep option can share wildcards and references to wildcards. For example, you can
keep classes on the condition that classes with related names exist in
your project, with frameworks like Dagger and Butterknife.
As written in the comments of the rules you copied this from:
# Keep `Companion` object fields of serializable classes.
# This avoids serializer lookup through `getDeclaredClasses` as done for named companion objects.
-if #kotlinx.serialization.Serializable class **
...
So, -if #kotlinx.serialization.Serializable class ** should be read as: for all classes which have the #Serializable annotation applied (i.e., "serializable classes"). The <1> in -keepmembers subsequently refers to the ** wildcard, i.e., the fully-qualified class name.
Working with an Android project in Android Studio 3.2, having enabled Proguard and some specific rules, I'm not able to figure out the following:
a specific package (and its subpackages) in a library module, used by client code, is preserved through the rule:
-keep public class com.mylib.mypackage.** {
public protected *;
}
Now, within this package there are also a number of package-private classes, which should not be picked by that rule. Some of those classes are effectively obfuscated, both in their own names and their member names, which is fine.
Instead there are some classes, implementing public interfaces, whose class names are not obfuscated, while I'd expect they should. For completeness, their member names, when not part of interface, are effectively obfuscated.
Example:
/* package */ class InternalComponent implements ExternalInterface {
// ExternalInterface is kept: Ok
// InternalComponent is kept: don't like, I'd like it renamed
#Override
public void ExternalMethod() {
// this is kept: Ok
}
public void InternalMethod() {
// this is renamed: Ok
}
}
I'd like to highlight that InternalComponent is created within some other (kept) class and only returned to client code through the ExternalInterface.
How can I also obfuscate their class names as well, if possible?
Edit #1
After #emandt answer on Proguard output files, I double checked and com.mylib.mypackage.InternalComponent is listed in seeds.txt, which according to this blog post lists all items matched by keep rules. So, for some reason, the rule above also picks package-private classes, which still seems wrong to me.
Edit #2
In the meantime, I ended up doing exactly the same approach proposed by #shizhen. For completeness, in order to extend the exclusion to any package named internal, I modified my proguard rule as:
-keep public class !com.mylib.mypackage.**.internal.*, com.mylib.mypackage.** {
public protected *;
}
(note the first part before the comma, prefixed by !)
I'll mark #shizhen answer, though I'd like to be curious as to why the original rule is also picking package-private components.
Are you working on an Android Library project? Probably YES.
In order to achieve your purpose, I am afraid that you need to re-organise your packages into something like below:
Public interfaces
com.my.package.apiforusers
Private/Internal implementations
com.my.package.apiforusers.internal
Then for your obfuscation rules, you can have it like below:
-keep public class com.my.package.apiforusers.** { public *; }
So that only the public classes/interfaces are kept and all those ones inside com.my.package.apiforusers.internal will be obfuscated.
Please note the double-asterisk at the end so that public classes/interface are also kept for the sub-packages.
In "/build/outputs/mapping/release/" folder there are few files ("usage.txt", "seeds.txt", etc..) that contain the REASONS of why and which classes/variables/methods/etc.. are not-processed/not-shrinked/ot-obfuscated via ProGuard utilities.
I know that keep class is suppose to keep the class.
But let's say if I keep class on a specific class, will it not obfuscate the said class?
-keep class com.myproject.activities.**
What is the difference between keep class vs keep public class
I know this is too late to answer but this may helpfull for someone.
From Guard Square documentation about -keep
-keep Specifies classes and class members (fields and methods) to be preserved as entry points to your code. For example, in order to keep an application, you can specify the main class along with its main method. In order to process a library, you should specify all publicly accessible elements.
You can check below links for more details about ProGuard specifires.
https://www.guardsquare.com/en/proguard/manual/usage
http://omgitsmgp.com/2013/09/09/a-conservative-guide-to-proguard-for-android/
As above.
My ProGuard config is
-keepclassmembers public class myApp.interfaces.**
-keepclasseswithmembernames public class myApp.interfaces.**
-keepattributes Signature
-keepparameternames
Really new to this and no real idea what I'm doing.
What I'm trying to achieve is to make Proguard not change the method and variable names of all Classes inside myApp.interfaces.*. If they want to rearrange some algo stuff to optimise it or whatever, it's fine. As long as the names are not changed.
This must be done because of the Serializable issue between server and client.
Simply use:
-keep class myApp.interfaces.** { *; }
It will not touch the class or its members. If you get errors / warnings, Rebuild the project.
We're using ORMLite in our Android app. It's working fine, except when we try to do a build with proguard switched on.
I've read various similar posts, and so far I've got in my proguard-project.txt
-keep class com.j256.** {
*;
}
as suggested in the following discussion http://sourceforge.net/p/proguard/discussion/182456/thread/6765bb69
and I've got
-keepclassmembers class * {
public <init>(android.content.Context);
public <init>(android.app.Activity,int);
}
as suggested in another stackoverflow question Proguard with OrmLite on Android
But it still not working. I can get it to run if I add
-dontobfuscate
but that somewhat missing the point of using proguard in the first place.
When I run I get an
IllegalStateException: Could not find OpenHelperClass because none of the generic
parameters of class class <our.package.name>.LaunchActivity extends
OrmLiteSqliteOpenHelper. You should use getHelper(Context, Class) instead.
Where
public class LaunchActivity extends OrmLiteBaseActivity<DatabaseHelper>
and
public class DatabaseHelper extends OrmLiteSqliteOpenHelper
I've added
-keep public class * extends com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper
-keep public class <our.package.name>.LaunchActivity
But still no luck. This question seems to have been asked before (Problems with OrmLite and proguard obfuscation) but I'm hoping somebody will know what the solution is!
The error message mentions generic parameters, so ORMLite is probably using reflection to retrieve generic type information. This information is stored in optional Signature attributes (Java erases generic types), which ProGuard removes by default. You can keep them with
-keepattributes Signature