aNNiMON aNNiMON - 2 months ago 63
Android Question

Android Gradle Plugin 2.2.0 ProGuard began to keep inner classes

After updating Android Studio to version 2.2 and Android Gradle plugin to 2.2.0, I have a lot of warnings when I build release apk, such as:


Error:warning: Ignoring InnerClasses attribute for an anonymous inner class

Error:(android.support.graphics.drawable.b) that doesn't come with an

Error:associated EnclosingMethod attribute. This class was probably produced by a

Error:compiler that did not target the modern .class file format. The recommended

Error:solution is to recompile the class from source, using an up-to-date compiler

Error:and without specifying any "-target" type options. The consequence of ignoring

Error:this warning is that reflective operations on this class will incorrectly

Error:indicate that it is not an inner class.


In addition, my release apk size has increased. So, I converted it to jar with dex2jar tool and compared with previous release (which was built with
com.android.tools.build:gradle:2.1.3
). The first thing I noticed is that new release still have some inner classes, which was not in previous versions.

Then I add
-keepattributes EnclosingMethod
to my proguard config to avoid warnings, but it increased file size much more by keeping all inner classes now.

So, can I build apk without unnecessary inner classes and
-keepattributes EnclosingMethod
as it was in Android Gradle plugin 2.1.3?

ProGuard config:

# Retrolambda
-dontwarn java.lang.invoke.*

# okhttp
-dontwarn okio.**
-dontwarn okhttp3.**
-keep class okio.**
-keep class okhttp3.** { *; }
-keep interface okhttp3.** { *; }

# appcompat
-keep public class android.support.v7.widget.** { *; }
-keep public class android.support.v7.internal.widget.** { *; }
-keep public class android.support.v7.internal.view.menu.** { *; }

-keep public class * extends android.support.v4.view.ActionProvider {
public <init>(android.content.Context);
}

-keepclasseswithmembers public class * {
public static void main(java.lang.String[]);
}

-keep public class * implements com.myapppackage.InterfaceClass
-keepattributes EnclosingMethod # was added to avoid 2.2.0 warnings

# Soft obfuscation
-keep public class !com.myapppackage.subpackage.** {
public protected *;
}


Module build.gradle:

buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.0'
classpath 'me.tatarka:gradle-retrolambda:3.2.5'
classpath 'me.tatarka.retrolambda.projectlombok:lombok.ast:0.2.3.a2'
}
configurations.classpath.exclude group: 'com.android.tools.external.lombok'
}


app build.gradle:

apply plugin: 'com.android.application'
apply plugin: 'me.tatarka.retrolambda'

android {
compileSdkVersion 24
buildToolsVersion "24.0.2"

...

compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
lintOptions {
abortOnError false
}
}

Answer

Yes, the default ProGuard rules included in Android Gradle plugin were changed in 2.2-beta2. The main changes were around -keepattributes and -renamesourcefileattribute.

We managed to fix it by copying the files proguard-android.txt and proguard-android-optimize.txt that are included in the plugin, undo some of the changes and make the Gradle plugin use that instead:

proguardFiles 'proguard-android-modified.txt', 'proguard-rules.pro'

If you downgrade the version of the Android Gradle plugin to 2.2-beta1 and compare the ProGuard files then you'll see the differences (yes, these were not the only changes... there is a bunch of new -keep and -keepclasseswithmembernames rules too).

Comments