Class 升级到 Android Gradle 插件 3.4.0 后不再混淆

Class no longer obfuscated after upgrading to Android Gradle plugin 3.4.0

升级到AndroidGradle插件3.4.0后,基础class不再混淆

以下基本步骤可以重现问题:

  1. 在 Android Studio 中创建一个新的空项目
  2. app/build.gradle 中将 minifyEnabled 更改为 true
  3. 创建以下class,ProguardTestClass.java:

    public class ProguardTestClass {
    
        public interface ProguardTestInnerInterface {
            void proguardTestCallback(String message);
        }
    
        public static void proguardTestMethod(String input, ProguardTestInnerInterface impl) {
            impl.proguardTestCallback("proguardTestMethod received input=[" + input + "]");
        }
    }
    
  4. 参考MainActivity.java中的class:

        public class MainActivity extends AppCompatActivity {
            private static final String TAG = "MainActivity";
    
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
    
                ProguardTestClass.proguardTestMethod("MainActivity's ProguardTestClass", new ProguardTestClass.ProguardTestInnerInterface() {
                    @Override
                    public void proguardTestCallback(String message) {
                        Log.d(TAG, "Proguard test: " + message);
                    }
                });
            }
        }
    
  5. 确认它在build.gradle

  6. 中使用AndroidGradle插件3.4.0
  7. 确认它在 gradle/wrapper/gradle-wrapper.properties
  8. 中使用 gradle-5.1.1
  9. 在“终端”选项卡中打开一个终端window
  10. 运行 ./gradlew clean build
  11. 运行 find . -name mapping.txt | xargs grep "ProguardTestClass -> "

预期输出:

com.example.proguardgradleplugin340.ProguardTestClass -> com.example.proguardgradleplugin340.a:

实际输出:

app/build/outputs/mapping/release/mapping.txt 没有提到 ProguardTestClass.

的任何重命名

要查看之前的 Android Gradle 插件版本是否可以产生预期的输出,请重复上述步骤,但指向 Android Gradle 插件的早期版本和 Gradle:

  1. build.gradle
  2. 中更改为AndroidGradle插件3.3.2
  3. gradle/wrapper/gradle-wrapper.properties
  4. 中更改为gradle-4.10.1

我试图通过查看其他 diagnostic files that we used to get from Proguard 来进行调查,但它们不再输出(至少默认情况下不会):

find . -name seeds.txt find . -name usage.txt

我还查看了 Android Gradle 插件 3.4.0 发行说明,发现它取代了 Proguard,转而支持一项 "integrates desugaring, shrinking, obfuscating, optimizing, and dexing all in one step".

的新技术

尝试设置 useProguard false 让插件使用 R8 而不是 ProGuard 来压缩和混淆您应用的代码和资源。例如。

android {
    ...
    buildTypes {
        debug {
            minifyEnabled true
            useProguard false
        }
        release {
            minifyEnabled true
            useProguard false 
        }
    }
}

或者,如果您想坚持使用 ProGuard,您应该从 gradle.properties 禁用 R8,如下所示:

# Disables R8 for Android Library modules only.
android.enableR8.libraries = false
# Disables R8 for all modules.
android.enableR8 = false

并且记得设置useProguard true


编辑#1

在此处查看如何将 Proguard 迁移到 R8:Android/java: Transition / Migration from ProGuard to R8?

@shizhen 的解决方案是我接受的问题解决方案。但我想记录一个替代方案,以防其他人遇到这个问题。

我能够通过实际实例化 class 让 R8 混淆 class。请注意我的 ProguardTestClass 原始代码如何不包含构造函数,并且我以相当静态的方式使用它。但是当我添加一个构造函数并从 MainActivity.java 实例化它时,我猜这给了 R8 一个混淆它的理由。

修改 ProguardTestClass 使 R8 执行混淆:

public class ProguardTestClass {

    //
    // NEW CODE: BEGIN
    //
    private int avar;

    public ProguardTestClass(int avar) {
        this.avar = avar;
    }

    public int incrementValue() {
        return ++avar;
    }
    //
    // NEW CODE: END
    //

    public interface ProguardTestInnerInterface {
        void proguardTestCallback(String message);
    }

    public static void proguardTestMethod(String input, ProguardTestInnerInterface impl) {
        impl.proguardTestCallback("proguardTestMethod received input=[" + input + "]");
    }
}

然后在 MainActivity.java 我在 onCreate() 上实例化并调用了 ProguardTestClass:

    proguardTestClass = new ProguardTestClass(3);
    Log.d(TAG, "Proguard test: " + proguardTestClass.incrementValue());