Skip to content
All posts
March 20, 20264 min read

How to Reduce Android App Size: R8, Split APKs, and Resource Optimization

App size directly affects install rates and user retention. Every extra MB costs you installs. Here's a systematic approach to analyzing and reducing Android app size using R8, App Bundles, and resource optimization.

AndroidPerformanceTools
Share:

Users abandon app installs when they see the download size. Google data shows install rates drop significantly above 10MB on low-end devices and limited data plans. App size is a user acquisition problem.

Here's how to fix it systematically.


Step 1: Measure What You Have

You can't optimize what you don't measure. Android Studio's APK Analyzer shows exactly where your bytes are going:

Build → Generate Signed Bundle/APK → then: Build → Analyze APK

Or via Gradle:

bash
./gradlew assembleRelease
# Then open: app/build/outputs/apk/release/app-release.apk in APK Analyzer

The breakdown typically shows:

  • code
    classes.dex
    — your code and dependencies
  • code
    res/
    — resources (images, layouts, drawables)
  • code
    lib/
    — native libraries
  • code
    assets/
    — raw assets

Find the biggest categories. Fix those first.


Step 2: Enable R8 (It's Probably Already On)

R8 is the code shrinker and obfuscator, enabled by default for release builds:

kotlin
// build.gradle.kts
android {
    buildTypes {
        release {
            isMinifyEnabled = true       // Enables R8
            isShrinkResources = true     // Removes unused resources
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }
}

R8 does three things:

  1. Shrinking — removes unused code and resources
  2. Obfuscation — renames classes/methods to shorter names
  3. Optimization — inlines methods, removes dead code paths

A typical app might shrink from 8MB to 4MB with R8 enabled.


Step 3: Switch From APK to App Bundle (AAB)

App Bundle lets Google generate optimized APKs per device. A user gets only:

  • The resources for their screen density (no xxhdpi images on an mdpi device)
  • The native libraries for their ABI
  • The language resources for their locale

Result: 15-50% smaller installs for users.

kotlin
// This is already set correctly for Play Store submissions
// App → Generate Signed Bundle → Android App Bundle

[!IMPORTANT] The Play Store requires App Bundle format since August 2021 for new apps. If you're still uploading APKs to the Play Store, you're missing significant size savings and leaving compliance issues on the table.


Step 4: Optimize Images

Images are often the biggest contributor to app size.

WebP instead of PNG/JPEG:

Android Studio can convert automatically: Right-click image folder → Convert to WebP

WebP provides better compression than PNG for lossless and JPEG for lossy, with the same visual quality.

Remove unused drawables:

bash
# Find potentially unused resources
./gradlew lint
# Look for "UnusedResources" warnings

R8's

code
isShrinkResources = true
removes unreferenced resources automatically. But R8 can miss resources referenced via string concatenation — review lint warnings manually.

Vector drawables instead of PNG:

For icons and simple graphics, vector drawables (

code
VectorDrawable
) replace multiple density-specific PNGs with a single scalable file:

xml
<!-- One file instead of mdpi/hdpi/xhdpi/xxhdpi PNGs -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:viewportWidth="24"
    android:viewportHeight="24"
    android:width="24dp"
    android:height="24dp">
    <path android:pathData="M12,2L..." android:fillColor="@color/icon_tint"/>
</vector>

Step 5: Audit Your Dependencies

Each dependency adds to your DEX size. Check what you're actually using:

kotlin
// Remove dependencies you're not using
// Replace heavy dependencies with lighter alternatives

// Example: instead of all of Guava (2MB+) for one utility:
// Bad
implementation("com.google.guava:guava:33.0.0-android")

// Good — use only the specific Kotlin stdlib equivalent

Check your APK's

code
classes.dex
in APK Analyzer. Sort methods by package. If a third-party library contributes 20,000 methods but you use 3 of them, find a lighter alternative.


Step 6: Native Libraries

If your app uses native libraries (

code
.so
files), each ABI (arm64-v8a, armeabi-v7a, x86_64) adds a copy:

kotlin
// If you only support 64-bit devices (Android 5.0+)
android {
    defaultConfig {
        ndk {
            abiFilters += listOf("arm64-v8a")
        }
    }
}

For most apps in 2026, shipping only

code
arm64-v8a
covers 95%+ of active Android devices.


Step 7: Enable Baseline Profiles

Not size reduction, but perceived size — Baseline Profiles speed up first launch by pre-compiling hot code paths:

kotlin
// baseline-prof.txt (generated by Macrobenchmark)
HSPLcom/yourapp/MainActivity;-><init>()V
HSPLcom/yourapp/TaskListViewModel;->loadTasks()V
// ...

Users open the app faster. This compensates for size in user perception.


Size Reduction Checklist

ActionTypical Savings
Enable R8 + resource shrinking30-50%
Switch to App Bundle15-40% reduction in user-facing size
Convert images to WebP10-30% on image-heavy apps
Replace PNGs with VectorDrawable50%+ for icon sets
Remove unused dependenciesVariable, 1-10MB possible
Limit ABI to arm64-v8a20-40% for apps with native libs

Tracking Size Over Time

Set a size budget in CI:

bash
# After building release AAB
AAB_SIZE=$(stat -c%s app/build/outputs/bundle/release/app-release.aab)
MAX_SIZE=10485760  # 10MB

if [ $AAB_SIZE -gt $MAX_SIZE ]; then
    echo "AAB size ${AAB_SIZE} exceeds budget ${MAX_SIZE}"
    exit 1
fi

This prevents size regressions slipping in unnoticed with new dependencies.


Takeaways

  • Measure first: APK Analyzer shows exactly where bytes are going
  • R8 + resource shrinking is non-negotiable for release builds — enable both
  • App Bundle is required for Play Store — if you're using APK, switch now
  • WebP images and VectorDrawable for icons are the highest-ROI image optimizations
  • Set a size budget in CI to prevent gradual size creep
Share:
S

Sudarshan Chaudhari

AI Systems Builder / Product Engineer

Bangkok, Thailand

Solo Android developer with 13+ years in QA, building Android apps, AI automation systems, and developer tools at SudarshanTechLabs.

Stay updated

Get new posts on Android, Kotlin, and solo dev straight to your inbox.

Newsletter preferences

Related Apps

MyFamilyTracker

Real-time family location sharing — Firebase Realtime DB for sub-second propagation, WorkManager + ForegroundService for OS-compliant background collection, geofencing via Google Maps API.

Building something? Available for Android dev and QA consulting.

Work with me

Comments — powered by Giscus