Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Switching to Gradle: why do I have to keep custom views from being obfuscated?

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:

  1. Why I don't have to deal with is while using Ant?
  2. 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.

like image 786
Sebastiano Avatar asked Dec 14 '14 15:12

Sebastiano


People also ask

Should I use R8 or ProGuard?

R8 is having a faster processing time than Proguard which reduces build time. R8 gives better output results than Proguard. R8 reduces the app size by 10 % whereas Proguard reduces app size by 8.5 %. The android app having a Gradle plugin above 3.4.

Is ProGuard deprecated?

For example, the useProGuard setting has been deprecated a while ago - maybe that's what you saw and you're misremembering it.

What is shrinkResources?

– android developer. Jun 12, 2015 at 10:47. 1. minifyEnabled enables proguard which removes unused classes/code and shrinkResources removes unused resources (pngs, xmls, mostly introduced by libraries which you don't fully utilize).

What is minifyEnabled true?

minifyEnabled true. // Enables resource shrinking, which is performed by the. // Android Gradle plugin. shrinkResources true. // Includes the default ProGuard rules files that are packaged with.


1 Answers

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:

    proguardFile getDefaultProguardFile('proguard-android.txt')
    proguardFile 'your/sepcific/folder/proguard.cfg'

(I remember Ant never used a SDK proguard file and it used to be recommended to copy all the config across).

like image 124
Blundell Avatar answered Oct 05 '22 23:10

Blundell