0Pricing
Android Academy · Lesson

Preparing a Release Build

App bundles and shrinking.

Preparing a Release Build is a free Android Academy lesson on CoddyKit — lesson 1 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Android Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

From Debug to Release

Every day you run the debug build from Android Studio. But Google Play needs a release build: smaller, faster, and not tagged as debuggable.

A release build is different in three key ways: it is signed with your release key, it has debuggable false, and it is usually shrunk to remove unused code and resources.

In this lesson you will prepare a proper release build and produce the file Google Play wants: an Android App Bundle (.aab).

Build Types in Gradle

Gradle defines two build types by default: debug and release. You configure them in your module's build.gradle.kts.

The release block is where you turn on optimizations. Notice isMinifyEnabled and isShrinkResources below — these are the switches that make your app smaller.

android {
    buildTypes {
        release {
            isMinifyEnabled = true
            isShrinkResources = true
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }
}

AAB vs APK

Google Play requires an Android App Bundle (.aab), not a plain .apk.

  • An .apk contains code and resources for every device — all screen densities, all CPU architectures, all languages.
  • An .aab is uploaded to Play, and Play generates a small, optimized APK for each user's exact device.

The result: users download less, your app installs smaller. You still use APKs for direct testing on a phone, but you publish an AAB.

What Is R8 / Shrinking?

When isMinifyEnabled = true, Android Studio runs R8. R8 does three jobs in one pass:

  • Shrinking — removes classes and methods your app never calls.
  • Obfuscation — renames classes and methods to short names like a, b, c to save space and deter reverse engineering.
  • Optimization — inlines and rewrites code to run faster.

Resource shrinking (isShrinkResources = true) additionally drops unused drawables, layouts and strings.

Keep Rules with ProGuard

R8 sometimes removes or renames code that is referenced only by reflection (for example by Gson, Retrofit, or serialization). You protect that code with keep rules in proguard-rules.pro.

A keep rule tells R8: "do not rename or delete these classes."

# proguard-rules.pro

# Keep data classes used with Gson reflection
-keep class com.example.app.model.** { *; }

# Keep Retrofit interface methods
-keepattributes Signature
-keepattributes *Annotation*

# Keep Kotlin metadata used by libraries
-keep class kotlin.Metadata { *; }

Versioning Your App

Every release needs two version values in build.gradle.kts:

  • versionCode — an integer that must increase with every upload. Play uses it to know which build is newer.
  • versionName — a human-readable string like "1.4.0" shown to users.

If you forget to bump versionCode, Play rejects the upload as a duplicate.

android {
    defaultConfig {
        applicationId = "com.example.app"
        minSdk = 24
        targetSdk = 35
        versionCode = 12
        versionName = "1.4.0"
    }
}

Building the Bundle in Android Studio

To create a signed release bundle from the UI:

  • Open Build → Generate Signed Bundle / APK.
  • Choose Android App Bundle.
  • Select (or create) your keystore and key.
  • Pick the release build variant.

Android Studio runs R8, signs the bundle, and drops the .aab into app/release/. That single file is what you upload to Play.

Building from the Command Line

For CI/CD or scripts, build the bundle with Gradle directly. The task name follows the pattern bundle<Variant>.

bundleRelease produces the AAB. The file lands in app/build/outputs/bundle/release/.

# Build a release App Bundle (.aab)
./gradlew bundleRelease

# Output:
# app/build/outputs/bundle/release/app-release.aab

# Build a release APK instead (for direct install/testing)
./gradlew assembleRelease

Inspecting and Testing the AAB

You cannot install an .aab on a phone directly. To test the exact APKs Play would generate, use Google's bundletool.

This builds device-specific APKs from your bundle and installs them on a connected device — the closest thing to a real Play download.

# Generate APKs from the bundle for the connected device
java -jar bundletool.jar build-apks \
  --bundle=app-release.aab \
  --output=app.apks \
  --connected-device

# Install them on the device
java -jar bundletool.jar install-apks --apks=app.apks

Removing Debug Code from Release

A release build should not log sensitive data or leave debug-only features on. Use BuildConfig.DEBUG to branch behavior. It is true only in debug builds.

R8 can even strip out blocks guarded by a constant false, so this also reduces size.

fun setupLogging() {
    if (BuildConfig.DEBUG) {
        // Verbose logging only in debug builds
        Log.d("App", "Debug logging enabled")
        Timber.plant(Timber.DebugTree())
    } else {
        // Release: send to crash reporting only, no console spam
        Timber.plant(CrashReportingTree())
    }
}

A Release-Ready Checklist

Before you build the final bundle, confirm:

  • versionCode bumped and versionName updated.
  • isMinifyEnabled and isShrinkResources on for release.
  • Keep rules added for any reflection-based libraries.
  • targetSdk meets Play's current requirement.
  • No debug-only logging or test endpoints in release code.
  • You tested the AAB via bundletool on a real device.

Once these pass, your .aab is ready to upload.

Quick Check

You set isMinifyEnabled = true and your app crashes in release with a "class not found" error from your JSON parser, but it works fine in debug. What is the most likely cause?

Recap: Preparing a Release Build

You now know how to turn a debug app into a publishable build:

  • Play requires a signed .aab, and Play generates per-device APKs from it.
  • The release build type enables R8 via isMinifyEnabled and isShrinkResources to shrink, obfuscate and optimize.
  • Keep rules protect reflection-based code from being removed.
  • Always bump versionCode and update versionName.
  • Build with ./gradlew bundleRelease and test the result with bundletool.

Next: how the signing that makes this build trustworthy actually works.

Frequently asked questions

Is the “Preparing a Release Build” lesson free?

Yes — the full text of “Preparing a Release Build” is free to read here on the web, and the Android Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Android Academy course, upgrade to CoddyKit PRO.

What will I learn in “Preparing a Release Build”?

App bundles and shrinking. You practise Android Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Android Academy?

No prior experience is required. Android Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 1 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Preparing a Release Build” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Android Academy lesson?

Yes. Every Android Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Preparing a Release Build
  2. App Signing
  3. The Play Console & Listing
  4. Rollouts and Updates
← Back to Android Academy