Skip to content

Code Obfuscation

Code Obfuscation Techniques with ProGuard/R8

ProGuard and its successor, R8, are Java-based tools used to shrink, obfuscate, and optimize Android applications. While Flutter apps are primarily built with Dart, the Android-specific components (e.g., native plugins, Flutter engine, and Java/Kotlin code) can be obfuscated using ProGuard/R8. This section explains how to configure these tools to protect Flutter apps from reverse engineering.


How ProGuard/R8 Works in Flutter

Flutter apps for Android are compiled into native code, but the Android app includes a Java-based Flutter engine and any Java/Kotlin code from plugins. ProGuard/R8 obfuscates this Java code, making it harder to reverse engineer. However, Dart code itself is not directly obfuscated by these tools. Instead, the Dart source code is compiled into machine code (e.g., .so files), which can still be decompiled using tools like dart2native or jadx.


Enabling ProGuard/R8 in Flutter Projects

  1. Update build.gradle
    Ensure your android/build.gradle file uses the latest Android Gradle plugin (e.g., 7.4.x or higher), which includes R8 by default.
buildscript {
    ext.kotlin_version = '1.8.0'
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:7.4.x'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}
  1. Configure proguard-rules.pro
    Create a proguard-rules.pro file in android/app/src/main/ to define obfuscation rules. For example:
-keep class com.example.** { *; }
-keep class io.flutter.** { *; }
-keep class androidx.** { *; }
-keep class android.** { *; }
-keep class java.** { *; }

These rules preserve critical classes (e.g., Flutter engine, Android SDK) while obfuscating others.

  1. Enable Obfuscation
    Set minifyEnabled true in android/app/build.gradle to activate R8:
android {
    ...
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

What ProGuard/R8 Does

  • Shrinking: Removes unused code, classes, and resources.
  • Obfuscation: Renames classes, methods, and fields to meaningless names (e.g., a, b, c).
  • Optimization: Removes redundant code and optimizes performance.

Example obfuscated output:

public class a {
    public void a() {
        // ...
    }
}


Limitations and Alternatives

  • Dart Code: ProGuard/R8 does not obfuscate Dart code. Use tools like dart2native or obfuscate_dart for Dart-specific protection.
  • Native Plugins: Obfuscate Java/Kotlin code in plugins to protect business logic.
  • Binary Protection: Combine with code signing, APK encryption, or native compilation to further secure the app.

Key takeaways

  • ProGuard/R8 obfuscates Java/Kotlin code in Flutter apps, not Dart.
  • Configure proguard-rules.pro to preserve critical classes while obfuscating others.
  • Use additional tools for Dart code protection and combine with binary encryption for comprehensive security.
  • Always test obfuscated builds to ensure functionality isn’t broken.