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,cto 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 assembleReleaseInspecting 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.apksRemoving 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:
versionCodebumped andversionNameupdated.isMinifyEnabledandisShrinkResourceson for release.- Keep rules added for any reflection-based libraries.
targetSdkmeets 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
releasebuild type enables R8 viaisMinifyEnabledandisShrinkResourcesto shrink, obfuscate and optimize. - Keep rules protect reflection-based code from being removed.
- Always bump
versionCodeand updateversionName. - Build with
./gradlew bundleReleaseand 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
- Preparing a Release Build
- App Signing
- The Play Console & Listing
- Rollouts and Updates