You've been shipping Android builds for a while. Maybe you've noticed your APK creeping up by a few hundred kilobytes each sprint. Or you're tired of hearing users complain about slow downloads on patchy networks. The usual response is a frantic optimization sprint before a major release, followed by months of neglect. That's exhausting and inefficient.
This guide proposes a different rhythm: a 15-minute weekly audit that fits into your existing workflow. No all-nighters, no heroic refactors. Just a repeatable checklist that catches bloat, misconfigurations, and stale resources before they compound. We've seen teams adopt this habit and consistently shave 10–20% off their APK size while improving cold start times by 100–300 ms—without dedicated optimization sprints.
Who is this for? Solo developers juggling multiple projects, CI maintainers who want automated checks, and tech leads who need a lightweight process that doesn't require everyone to become an APK wizard. By the end of this article, you'll have a concrete checklist you can run every Monday morning (or any day you deploy). Let's build the habit.
Why a Weekly Audit Matters More Than a Pre-Release Fire Drill
Most teams treat APK optimization as a one-time event—a panicked week of shrinking images, enabling ProGuard, and hoping nothing breaks. But APKs are living artifacts. Every commit, every library update, every new feature adds weight. Without regular maintenance, the bloat accumulates silently.
The cost of that bloat is real. Larger APKs mean lower install conversion rates, especially in markets with slower connections. According to Google's own data, every 1 MB increase can reduce conversion by up to 1% on some networks. That's a direct hit to your user acquisition. But beyond downloads, a bloated APK often correlates with slower cold start times, more memory pressure, and higher crash rates on low-end devices.
A weekly audit flips the dynamic from reactive to preventive. Instead of discovering that your APK has grown 15 MB over the quarter, you catch a 200 KB spike the week it happens. That spike might be an accidentally bundled debug library or an oversized vector asset that slipped past review. With a short, focused checklist, you can identify and fix these issues in minutes—not hours.
The psychological benefit matters too. When optimization becomes a habit, it stops feeling like a chore. Your team builds muscle memory around the checklist, and the metrics (APK size, dex count, resource count) become part of your regular vocabulary. You start making better decisions during development because you know they'll be checked weekly.
The Cost of Ignoring the Creep
Consider a typical scenario: a team adds a new image carousel feature. They import a lightweight library for lazy loading, add a few PNGs for placeholder states, and call it done. Individually, those changes add maybe 500 KB. But over six months, similar decisions across the team can balloon the APK by 8–12 MB. That's the creep. A weekly audit catches each addition in context, making it easier to decide whether that library is worth the weight or if a smaller alternative exists.
How 15 Minutes Changes Everything
Fifteen minutes is short enough to fit into a busy schedule but long enough to run through a structured checklist. It's not about deep analysis—you won't be profiling every bytecode instruction. Instead, you'll focus on the high-impact areas that account for 80% of common bloat: resources, native libraries, ProGuard configuration, and unused code paths. With practice, you can spot anomalies in under ten minutes, leaving five for quick fixes or logging tickets for deeper investigation.
The Core Levers: What You're Actually Checking
To keep the audit fast, you need to focus on the levers that give the most bang for your time. We've identified four core areas that consistently yield improvements: resource optimization, native library pruning, ProGuard and R8 rules, and dynamic delivery configuration. Each area has a specific checklist item that takes 2–4 minutes to verify.
Resource Optimization
Resources—images, drawables, layouts, strings—often account for 30–50% of an APK's size. The first check is to run Android Studio's APK Analyzer or a simple command-line tool like apkanalyzer to list the largest files. Look for anything over 500 KB that isn't a critical UI element. Common culprits: high-resolution PNGs that should be WebP, unoptimized vector drawables, and duplicate strings across locales.
Next, verify that your resConfigs in build.gradle are set correctly. Many projects accidentally bundle all locale resources when they only support a handful. Adding resConfigs('en', 'es') can trim 2–5 MB instantly. Also check that unused resource shrinking is enabled via shrinkResources true. This removes resources that are referenced in code but not actually used—though you should verify that the shrinker hasn't removed something you need (a common edge case we'll cover later).
Native Library Pruning
Native libraries (.so files) are often the largest single contributors to APK size. A typical app might bundle libraries for all architectures (arm64-v8a, armeabi-v7a, x86, x86_64) when only arm64-v8a is needed for modern devices. Check your abiFilters configuration. If your app targets API 21+, you can safely exclude x86 and x86_64 for most apps. This can cut 10–20 MB from a library-heavy app.
Also look for duplicate or unnecessary native libraries. Some SDKs bundle their own copies of common libraries like OpenSSL or libpng. If you're already using a system-provided version or a different SDK's copy, you can exclude duplicates via Gradle configurations. Use the APK Analyzer's "Native Libraries" tab to spot duplicates quickly.
ProGuard and R8 Rules
ProGuard or R8 shrinking, obfuscation, and optimization are essential, but many teams enable them without verifying effectiveness. In your weekly audit, check the mapping file (generated in build/outputs/mapping/) to see how much code was removed. A healthy shrink should reduce the dex count by 20–40%. If your mapping shows minimal shrinking, your rules might be too permissive—or you have a keep rule that prevents shrinking of entire packages.
Review your proguard-rules.pro for any broad -keep statements. Developers often add -keep class com.example.** { *; } during debugging and forget to remove it. That single line can prevent R8 from shrinking thousands of classes. Also check for -keepattributes that might be unnecessary; only keep the attributes you actually need for runtime reflection.
Dynamic Delivery Configuration
If you're using Android App Bundle (AAB), dynamic delivery is your friend. But it's easy to misconfigure. Check that you're not accidentally including assets in the base module that could be deferred. For example, large feature-specific images should go into a feature module's resources, not the base. Use the BundleTool or Android Studio's "Build > Analyze APK" to see which modules contain what.
Also verify that you're not using dist:install-time for features that could be dist:on-demand. On-demand delivery reduces initial install size significantly. The weekly audit is a good time to review your AndroidManifest.xml in each feature module to ensure the dist:delivery setting matches your actual usage pattern.
How It Works Under the Hood: The 15-Minute Routine
Now that you know what to check, let's structure the 15 minutes. The routine is designed to be run from your local machine or a CI job. We recommend using a script that automates the data collection so you can focus on interpretation.
Here's the step-by-step timeline:
- Minutes 0–3: Generate a fresh APK and run basic size metrics. Use
./gradlew :app:assembleReleaseand then the APK Analyzer CLI:apkanalyzer apk summary app/build/outputs/apk/release/app-release.apk. Note the total size, download size (if AAB), and the number of dex files. Compare with last week's values. Any jump over 1 MB warrants investigation. - Minutes 3–6: Scan for large resources and native libraries. Run
apkanalyzer apk file-size app/build/outputs/apk/release/app-release.apkand sort by size. Identify the top 20 files. Look for anything over 1 MB that isn't expected. Also runapkanalyzer apk native-librariesto list all .so files and their sizes. - Minutes 6–9: Review ProGuard/R8 effectiveness. Open the
mapping.txtand check the shrink ratio. Also runapkanalyzer dex classes app/build/outputs/apk/release/app-release.apkto count the number of classes before and after shrinking. If the ratio is below 20%, flag it. - Minutes 9–12: Check dynamic delivery configuration. If using AAB, generate an APK from the bundle using
bundletool build-apksand inspect the modules. Ensure that feature modules are not included in the base module's resources. - Minutes 12–15: Decide and log. For each anomaly you found, either fix it immediately if it's trivial (e.g., remove a debug library) or log a ticket with the context. Update a shared weekly audit spreadsheet with the metrics so you can track trends over time.
Automating the Data Collection
To speed up the routine, create a shell script that runs all the apkanalyzer commands and outputs a summary. Many teams then pipe that into a Slack webhook or a CI artifact. The goal is to make the first three minutes near-instant. We've seen scripts that reduce the entire audit to a single command: ./audit.sh. That leaves you with 15 minutes of pure analysis and decision-making.
What to Do When You Find a Problem
Not every issue needs an immediate fix. Use a simple triage: if the fix takes less than 5 minutes (e.g., adding a ProGuard rule, removing a duplicate resource), do it now. If it requires a code change or coordination with another team (e.g., replacing a third-party SDK), log a ticket with the estimated size impact and priority. The audit's value is in surfacing these issues early, not in forcing immediate action.
Worked Example: A Typical Weekly Audit Walkthrough
Let's walk through a real-world composite scenario. Imagine you're maintaining a mid-sized e-commerce app. Last week's APK was 38.2 MB. This week, after adding a new payment integration library, the APK jumped to 41.5 MB. That's a 3.3 MB increase—enough to trigger your audit protocol.
You run the checklist. The APK Analyzer shows that the largest new file is a 2.1 MB native library: libPaymentCore.so included for all four architectures. That's suspicious because the library is only used in the checkout flow, which is delivered on-demand via a feature module. Checking the build configuration, you find that the library was added to the base module's dependencies instead of the feature module's. A quick refactor moves it to the feature module and enables on-demand delivery. Result: the base APK drops to 39.4 MB (a 2.1 MB reduction).
Further down the list, you spot a 900 KB PNG file in drawable-xxhdpi that's a full-screen background image. It's only used in one activity. You convert it to WebP lossy at 80% quality, reducing it to 320 KB. That's another 580 KB saved.
Finally, you check the ProGuard mapping file. The shrink ratio is only 12%, well below the 20% threshold. Looking at the rules, you see a broad -keep class com.payment.** { *; } that was added during integration testing and never removed. Removing it and re-running R8 improves the shrink ratio to 28%, shaving another 1.1 MB from the dex files. Total savings from the 15-minute audit: 3.8 MB, bringing the APK back down to 37.7 MB—even smaller than last week.
The Cumulative Effect
Over eight weeks of consistent audits, this team averaged 1.2 MB reduction per week. By the end of the quarter, they had trimmed 9.6 MB without any major refactoring effort. The habit paid for itself in the first week.
Edge Cases and Exceptions: When the Standard Checklist Fails
Not every situation fits the checklist. Here are common edge cases where you need to adapt the routine.
Multi-Module Projects
If your app has 20+ modules, the standard APK Analyzer may not give a clear picture of which module contributed the bloat. In this case, use Gradle's dependencies task to visualize the dependency tree. Focus on implementation vs api usage—misusing api can leak transitive dependencies into the base module. Also, run the audit per module by generating a release APK for each feature module individually to isolate size contributions.
Third-Party SDK Bloat
Some SDKs are notoriously heavy. If your audit consistently flags a particular SDK's resources or libraries, consider alternatives. For example, if an analytics SDK bundles its own image loading library, and you already use Glide, you can exclude the duplicate via exclude statements in your dependencies. But be careful: some SDKs rely on those libraries internally, so test thoroughly.
Resource Shrinker Over-Removal
The shrinkResources tool can sometimes remove resources that are used dynamically via reflection or resource IDs from libraries. If your app crashes after enabling resource shrinking, check the resources.arsc file for missing entries. You can add a keep.xml file in res/raw/ to explicitly keep certain resources. A common pattern is to keep all resources in a package used by a third-party SDK: .
Large Assets That Are Actually Needed
Sometimes a large asset is genuinely necessary—for example, a high-resolution map tile set for offline use. In that case, consider moving it to on-demand delivery via Play Feature Delivery or using Play Asset Delivery for large files. The audit should flag it, but the solution may be architectural rather than a simple removal.
Limits of the Approach: What a 15-Minute Audit Can't Do
While a weekly audit is powerful, it has boundaries. Being aware of them helps you avoid false confidence.
It's Not a Deep Performance Profiler
This audit catches size bloat and configuration issues, but it won't identify inefficient algorithms, memory leaks, or slow database queries. Those require dedicated profiling sessions with tools like Android Studio's CPU Profiler or Memory Profiler. The audit complements those efforts but doesn't replace them.
It Misses Code-Level Inefficiencies
Even with ProGuard, your code may still contain redundant calculations or overly complex layouts. The audit looks at the output APK, not the source. For example, a developer might write a loop that creates thousands of temporary objects, causing GC churn. The audit won't catch that. You need separate code review practices and performance testing.
It Can't Fix Architectural Problems
If your app has a monolithic architecture where everything is in the base module, the audit will repeatedly flag large base APK sizes. The fix is to modularize your app, which is a significant engineering effort. The audit can surface the symptom, but the solution requires planning and buy-in from the whole team.
It Requires Consistent Buy-In
The routine only works if someone runs it every week. If the audit gets skipped for three weeks, the bloat creeps back. We recommend integrating the checks into your CI pipeline so that every release build triggers a summary report. That way, even if the weekly manual audit lapses, you still have automated safety nets. Over time, the manual audit becomes a review of the CI output rather than a data-gathering exercise.
When Not to Use This Checklist
If your app is in rapid prototyping mode (MVP, hackathon), the 15-minute audit is overkill. Focus on shipping first. Also, if your APK is already under 5 MB and you have no performance complaints, the audit may not provide enough value to justify the time. In that case, run it monthly instead.
The bottom line: the 15-minute audit is a maintenance habit, not a magic bullet. It keeps small problems from becoming big ones, but it won't solve every performance issue. Use it as part of a broader quality strategy that includes unit tests, integration tests, and periodic deep dives.
Your next move: this week, run the audit manually once. Note the time it takes and the issues you find. Then, invest an hour to automate the data collection. By next week, you'll have a script that does the heavy lifting. Share the results with your team and make the audit a recurring calendar event. After a month, you'll wonder how you ever shipped without it.
Comments (0)
Please sign in to post a comment.
Don't have an account? Create one
No comments yet. Be the first to comment!