I am moving a project from Ant to Gradle, but there's something I just can't figure out.
FACTS
After building a release APK (i.e., obfuscated), I noticed that the app was crashing badly. The error can be summed up by this:
java.lang.NoSuchMethodException: <init> [class android.content.Context, interface android.util.AttributeSet]
A debug (i.e., non obfuscated) APK works just fine, so I guessed it had to do with my ProGuard/DexGuard configuration.
I tried to keep the class reference by adding the following statement:
-keep class com.mypackage.MyCustomView
and, as a result, the release APK works just fine. I then did some research and I tried this more specific ProGuard/DexGuard configuration:
-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);
}
which also works, and it is class-independent.
QUESTION
I wonder:
- Why I don't have to deal with is while using Ant?
- What is the exact reason for that error to show up? (follows answer to first question)
ANSWER
The answer from @Blundell was substantially correct. Turns out I was missing one line from the build.gradle
configuration:
android {
...
buildTypes {
debug {
...
}
release {
proguardFile getDefaultDexGuardFile('dexguard-release.pro') # <----- this line
proguardFile 'dexguard-project.txt'
}
}
}
It appears that line is actually mandatory, since it serves as a base set of rules for ProGuard/DexGuard. In fact, this is part of the dexguard-release.pro
file:
-keepclassmembers !abstract class !com.google.ads.** 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*(...);
}
-keepclassmembers !abstract class * {
public <init>(android.content.Context, android.util.AttributeSet);
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclassmembers class * extends android.content.Context {
public void *(android.view.View);
}
I found the documentation a little bit too vague on this, I hope it can be redacted to clear any ambiguity it might have. All in all, my fault.
Most likely Ant was using a different configuration file,
Also with Gradle you need to explicitly state you want to also use the Android proguard config file i.e. use multiple rules files like so:
(I remember Ant never used a SDK proguard file and it used to be recommended to copy all the config across).