Android Gradle Plugin 2.2.0 ProGuard 开始保留内部类

Posted

技术标签:

【中文标题】Android Gradle Plugin 2.2.0 ProGuard 开始保留内部类【英文标题】:Android Gradle Plugin 2.2.0 ProGuard began to keep inner classes 【发布时间】:2017-02-01 16:39:03 【问题描述】:

android Studio更新到2.2版本,将Android Gradle插件更新到2.2.0后,我在构建release apk时出现很多警告,比如:

错误:警告:忽略匿名内部类的 InnerClasses 属性 错误:(android.support.graphics.drawable.b) 不附带 错误:关联的 EnclosureMethod 属性。这个类可能是由一个 错误:没有针对现代 .class 文件格式的编译器。推荐 错误:解决方案是使用最新的编译器从源代码重新编译类 错误:并且没有指定任何“-target”类型选项。忽视的后果 错误:这个警告是这个类的反射操作会错误 错误:表明它不是一个内部类。

此外,我的发布 apk 大小有所增加。因此,我使用 dex2jar 工具将其转换为 jar,并与之前的版本(使用 com.android.tools.build:gradle:2.1.3 构建)进行了比较。我注意到的第一件事是新版本仍然有一些内部类,这在以前的版本中是没有的。

然后我将 -keepattributes EnclosingMethod 添加到我的 proguard 配置中以避免警告,但现在通过保留所有内部类来增加文件大小。

那么,我可以像在 Android Gradle 插件 2.1.3 中那样构建没有不必要的内部类和 -keepattributes EnclosingMethod 的 apk 吗?

ProGuard 配置:

# 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 *;

模块构建.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'

应用程序构建.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
    

【问题讨论】:

【参考方案1】:

是的,Android Gradle 插件中包含的默认 ProGuard 规则在 2.2-beta2 中已更改。主要变化是围绕-keepattributes-renamesourcefileattribute

我们设法通过复制插件中包含的文件 proguard-android.txtproguard-android-optimize.txt 来修复它,撤消一些更改并让 Gradle 插件使用它:

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

如果您将 Android Gradle 插件的版本降级到 2.2-beta1 并比较 ProGuard 文件,那么您会看到差异(是的,这些不是唯一的变化......还有一堆新的 -keep-keepclasseswithmembernames 规则)。

【讨论】:

目前有两张官方门票:code.google.com/p/android/issues/detail?id=222989和code.google.com/p/android/issues/detail?id=222775

以上是关于Android Gradle Plugin 2.2.0 ProGuard 开始保留内部类的主要内容,如果未能解决你的问题,请参考以下文章

gradle/gradle plugin/Android studio关系

Gradle之Android Gradle Plugin 主要 Task 分析

Android Studio Gradle Plugin开发入门指南

Android Studio Gradle Plugin开发入门指南

Android自定义Aop的Gradle Plugin

Android Gradle 插件Gradle 自定义 Plugin 插件 ⑥ ( 在 buildSrc 模块中依赖 Android Gradle 插件 | 完整代码示例 )