Proguard (R8) negate operator not working to keep anything except certain packages
Asked Answered
L

2

6

The negator (exclamation mark) in proguard should allow me to keep anthing but the apache libraries:

-keep class !org.apache.**

According to those answers. That's the way to go:

However, it obfuscates all classes in my APK.

That's part of my build.gradle (I have 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'
}

After I added -printconfiguration to my proguard-rules.pro file I saw there are numerous -keep rules following my -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>(...); }

That approach suggested by Ezekiel Baniaga also didn't work. Instead it keeps everything including the apache packages:

proguard-rules.pro

-printconfiguration

-dontshrink

-dontoptimize

-dontobfuscate

-keep,allowshrinking,allowoptimization,allowobfuscation class org.apache.**
Linalinacre answered 9/12, 2019 at 12:10 Comment(0)
L
7

I had to add ,** to get it working. Thanks T. Neidhart!

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

The previous example preserved class names but still obfuscated members. So I had to add { *; }:

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

That's how I obfuscate multiple packages (I have to use them all in one keep rule!)

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

To find out what my problem is with -dontshrink -dontoptimize -dontobfuscate -keep,allowshrinking,allowoptimization,allowobfuscation class org.apache.** I could add -whyareyoukeeping according to https://www.guardsquare.com/en/products/proguard/manual/usage

Linalinacre answered 13/12, 2019 at 11:12 Comment(4)
The trailing ,** could be ,* instead ... the single asterisk is interpreted as any class regardless of package, apparently for backward compatibility.Inhabitant
What should I write in my proguard rules? I wrote -keep class !com.lol.loll.lolllll.appl.MainActivity.** but it doesn't work! I receive tons of warnings!Batish
Did you note the 1st sentence of my answer? Your example lacks ,** at the end. You probably should ask your own question to your specific problem.Linalinacre
I'm a bit unclear why ,** changes behavior, so I asked another question about it #67506693Matias
C
5

You should file a bug report with the R8 project if this does not work anymore.

In order to keep using Proguard in the meantime, you can add this to your gradle.properties files:

android.enableR8=false

Further tests show that the implicit behavior of ProGuard is not implemented like that in R8.

So a rule like:

-keep class !org.apache.**

will implicitly keep all other classes when using ProGuard, but not when using R8. To achieve the same behavior with R8, change the rule to this:

-keep class !org.apache.**,**
Canella answered 10/12, 2019 at 19:2 Comment(11)
So, my syntax is correct?: -keep class !org.apache.**Linalinacre
Yes thats correct, I had a small typo its android.enableR8=falseCanella
With your correction (android.enableR8=false) I managed to turn off R8. However, then proguard wouldn't finish due to lots of warnings. So, I added -dontwarn which finally built an APK. My negated rules were also not recognized with that approach.Linalinacre
I am pretty sure they were. As you wrote, there will be additional keep rules automatically added by the Android gradle plugin. All keep rules are treated independently. So if there are other keep rules that keep certain classes this keep rules will be honored and the specified classes will be kept.Canella
Are you saying the negator only works if I have one keep rule (the one with the negator)?Linalinacre
Yes, every keep rule is treated independently.Canella
So, all those questions I listed above, won't work anymore since Android Studio adds numerous -keep rules itself? I wonder why nobody raised that question before. What about the last approach I described (-dontshrink -dontoptimize -dontobfuscate -keep,allowshrinking,allowoptimization,allowobfuscation class org.apache.**). Why is that not working either? Instead it keeps everything, even the apache packages.Linalinacre
I dont know what goes wrong in your case, but the keep rule should be honored and it works in my tests. When using -dontobfuscate nothing will be obfuscated, so all classes will be kept as expected.Canella
I tested it again, with ProGuard it works correctly, R8 does not seem to take the negated rule correctly into account. As already said I would raise a ticket with the R8 project or switch to ProGuard as explained.Canella
I updated the answer with a rule that works also with R8Canella
What should I write in my proguard rules? I wrote -keep class !com.lol.loll.lolllll.appl.MainActivity.** but it doesn't work! I receive tons of warnings!Batish

© 2022 - 2024 — McMap. All rights reserved.