Proguard (R8) 否定操作员不工作以保留某些包以外的任何东西

Posted

技术标签:

【中文标题】Proguard (R8) 否定操作员不工作以保留某些包以外的任何东西【英文标题】:Proguard (R8) negate operator not working to keep anything except certain packages 【发布时间】:2020-04-02 13:04:41 【问题描述】:

proguard 中的否定符(感叹号)应该允许我保留除 apache 库之外的东西:

-keep class !org.apache.**

根据这些答案。这就是要走的路:

How to negate classname with Proguard Enable Proguard for only two packages in large android application Android proguard Ignore All Classes except of one Proguard Android do not obfuscate anything except few classes Proguard: How to keep everything except specific condition? Can we shrink all classes but only obfuscate some with proguard?

但是,它混淆了我的 APK 中的所有类。

这是我的 build.gradle 的一部分(我有 Android Studio 3.5.3)

compileSdkVersion 29
buildToolsVersion "29.0.2"
//...
buildTypes 

    release 

        minifyEnabled true
        proguardFiles /*getDefaultProguardFile('proguard-android.txt'),*/  'proguard-rules.pro'

        // Enables resource shrinking, which is performed by the
        // Android Gradle plugin.
        shrinkResources false
    


dependencies 
    //Utility libs
    implementation 'org.apache.commons:commons-collections4:4.1'
    implementation 'org.apache.commons:commons-lang3:3.4'
    implementation group: 'commons-io', name: 'commons-io', version: '2.5'

在我将-printconfiguration 添加到我的proguard-rules.pro 文件后,我看到有许多-keep 规则遵循我的-keep class !org.apache.**

-printconfiguration
-keep class !org.apache.**

# Referenced at ***anonymized***\app\build\intermediates\merged_manifests\release\AndroidManifest.xml:180
-keep class android.support.v4.app.CoreComponentFactory  <init>(); 
# Referenced at ***anonymized***\app\build\intermediates\merged_manifests\release\AndroidManifest.xml:180
-keep class com.mycompany.MyApplication  <init>(); 
# Referenced at C:\Users\***anonymized***\.gradle\caches\transforms-2\files-2.1\7f5f0b3369d8fa8a72a20e2278ec0acc\appcompat-v7-28.0.0\res\layout\abc_action_menu_item_layout.xml:17
-keep class android.support.v7.view.menu.ActionMenuItemView  <init>(...); 

Ezekiel Baniaga 建议的方法也不起作用。相反,它保留了包括 apache 包在内的所有内容:

proguard-rules.pro

-printconfiguration

-dontshrink

-dontoptimize

-dontobfuscate

-keep,allowshrinking,allowoptimization,allowobfuscation class org.apache.**

【问题讨论】:

【参考方案1】:

如果这不再起作用,您应该向 R8 项目提交错误报告。

为了在此期间继续使用 Proguard,您可以将其添加到您的 gradle.properties 文件中:

android.enableR8=false

进一步的测试表明,ProGuard 的隐式行为并没有像 R8 那样实现。

所以这样的规则:

-keep class !org.apache.**

在使用 ProGuard 时会隐式保留所有其他类,但在使用 R8 时不会。要使用 R8 实现相同的行为,请将规则更改为:

-keep class !org.apache.**,**

【讨论】:

那么,我的语法正确吗?:-keep class !org.apache.** 是的,没错,我有一个小错字,它的 android.enableR8=false 通过您的更正 (android.enableR8=false) 我设法关闭了 R8。但是,由于大量警告,proguard 无法完成。所以,我添加了-dontwarn,它最终构建了一个 APK。这种方法也无法识别我的否定规则。 我很确定他们是。正如您所写,Android gradle 插件会自动添加额外的保留规则。所有保留规则都被独立处理。因此,如果有其他保留规则保留某些类,则将遵守此保留规则并保留指定的类。 你是说只有当我有一个保留规则(带有否定符的那个)时,否定符才有效?【参考方案2】:

我必须添加 ,** 才能使其正常工作。谢谢T. Neidhart!

-keep class !org.apache.**,**

前面的例子保留了类名,但仍然混淆了成员。所以我不得不添加 *;

-keep class !org.apache.**,**  *; 

这就是我混淆多个包的方式(我必须将它们全部使用在一个保留规则中!)

-keep class !org.apache.**, !org.zeroturnaround.**, !com.drew.**, **  *; 

要了解-dontshrink -dontoptimize -dontobfuscate -keep,allowshrinking,allowoptimization,allowobfuscation class org.apache.** 的问题,我可以根据https://www.guardsquare.com/en/products/proguard/manual/usage 添加-whyareyoukeeping

【讨论】:

尾随的,** 可能是,* ...单个星号被解释为任何类,而与包无关,显然是为了向后兼容。 我应该在我的 proguard 规则中写什么?我写了 -keep class !com.lol.loll.lollllll.appl.MainActivity.** 但它不起作用!我收到大量警告! 你注意到我回答的第一句话了吗?你的例子最后缺少,**。您可能应该针对您的具体问题提出自己的问题。 我有点不清楚为什么,**会改变行为,所以我问了另一个问题***.com/questions/67506193/…

以上是关于Proguard (R8) 否定操作员不工作以保留某些包以外的任何东西的主要内容,如果未能解决你的问题,请参考以下文章

Firebase + Proguard/R8

R8 和 Proguard 规则

proguard-rules.pro 似乎不适用于 R8

使用 proguard / R8 删除数据类元数据

如果在proguard中包含带有注释的字段,如何保持类的成员不受影响

Proguard和R8有啥区别?