3

After upgrading to Android Gradle plugin 3.4.0, a basic class no longer gets obfuscated.

The following basic steps can reproduce the problem:

  1. In Android Studio create a new empty project
  2. In app/build.gradle change minifyEnabled to true
  3. Create the following 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. Refer to the class from MainActivity.java:

        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. Confirm that it's using Android Gradle plugin 3.4.0 in build.gradle

  6. Confirm that it's using gradle-5.1.1 in gradle/wrapper/gradle-wrapper.properties
  7. Open a Terminal window in the Terminal tab
  8. Run ./gradlew clean build
  9. Run find . -name mapping.txt | xargs grep "ProguardTestClass -> "

Expected output:

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

Actual output:

app/build/outputs/mapping/release/mapping.txt does not mention any renaming of ProguardTestClass.

To see that prior Android Gradle plugin versions could produce the expected output, repeat the steps above but point to prior versions of Android Gradle plugin and Gradle:

  1. Change to Android Gradle plugin 3.3.2 in build.gradle
  2. Change to gradle-4.10.1 in gradle/wrapper/gradle-wrapper.properties

I tried to investigate by looking into other diagnostic files that we used to get from Proguard, but they're no longer output (at least not by default anyway):

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

I also checked the Android Gradle plugin 3.4.0 release notes and found out that it replaced Proguard in favor of a new technology that "integrates desugaring, shrinking, obfuscating, optimizing, and dexing all in one step".

shizhen
  • 12,251
  • 9
  • 52
  • 88
Michael Osofsky
  • 11,429
  • 16
  • 68
  • 113

2 Answers2

5

Try to set useProguard false to let the plugin use R8 instead of ProGuard to shrink and obfuscate your app’s code and resources. E.g.

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

Or alternatively, if you want to stick to ProGuard, you should disable R8 from gradle.properties like below:

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

And remember to set useProguard true.


Edit #1

Check here for how to migrate Proguard to R8: Android/java: Transition / Migration from ProGuard to R8?

shizhen
  • 12,251
  • 9
  • 52
  • 88
  • Disabling R8 from `gradle.properties` and setting `useProguard true` fixed the problem. Now `find . -name mapping.txt | xargs grep "ProguardTestClass -> "` shows the expected mapping occurred: `com.example.proguardgradleplugin340.ProguardTestClass -> com.example.proguardgradleplugin340.a:`. However the first suggestino (set `useProguard false`) did not fix the problem. – Michael Osofsky May 08 '19 at 15:43
1

The solution from @shizhen is what I accepted as the solution to the problem. But I wanted to document an alternative in case anyone else runs into this problem.

I was able to make R8 obfuscate the class by actually instantiating the class. Notice how my original code for ProguardTestClass contained no constructor and I used it in a fairly static way. But when I added a constructor and instantiated it from MainActivity.java, that gave R8 a reason to obfuscate it I guess.

Revised ProguardTestClass that made R8 perform the obfuscation:

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 + "]");
    }
}

Then in MainActivity.java I instantiated and called the ProguardTestClass on onCreate():

    proguardTestClass = new ProguardTestClass(3);
    Log.d(TAG, "Proguard test: " + proguardTestClass.incrementValue());
shizhen
  • 12,251
  • 9
  • 52
  • 88
Michael Osofsky
  • 11,429
  • 16
  • 68
  • 113