Android, ProGuard, and keepclasseswithmembernames

Matthias picture Matthias · Apr 26, 2011 · Viewed 7.1k times · Source

A common pattern in ProGuard configs for Android applications is to preserve custom View classes, since they are probably referenced only from layout XML instead of application code.

Upon project creation, the ADT therefore add these rules to a project's proguard.cfg:

-keepclasseswithmembernames class * {
   public <init>(android.content.Context, android.util.AttributeSet);
}

-keepclasseswithmembernames class * {
   public <init>(android.content.Context, android.util.AttributeSet, int);
}

I guess the idea here is to say that whenever a class defines a constructor that may be called by a layout inflater, then preserve it. However, according to the ProGuard docs, the keepclasseswithmembernames qualifier is shorthand for keepclasseswithmembers and allowshrinking, which if I understand correctly means: it's allowed to remove these classes, but if they're kept, don't obfuscate its member names (probably to not break bindings between XML attribute names and class setters).

But doesn't that mean that those classes will still be removed during the shrinking phase (allowshrinking = true), unless they are referenced directly in code? Indeed that is what happened with a custom widget we're using in our app, and I could fix the issue by setting the rule to just keepclasseswithmembers since that will simply preserve the matching classes entirely (it's worth noting that this is what the official ProGuard Android example does, too).

Am I misreading the ProGuard docs or is this a bug in the ADT project wizard?

Answer

Eric Lafortune picture Eric Lafortune · Apr 27, 2011

The configuration in the Android SDK (at least up to version 11) is not entirely correct, indeed.

The configuration for Android in the ProGuard documentation correctly specifies "-keepclasseswithmembers", not "-keepclasseswithmembernames".