Engineering

Optimizing Android Asset Delivery for Small Productivity Apps

How to balance high-quality vector graphics against storage constraints in emerging markets for a lean, efficient Android app experience.

Amin Shekh · October 10, 2026
Share

When we built Salah Companion, we faced a specific technical tension. We wanted a UI that felt premium and high-definition on a flagship Google Pixel, but the app also needed to be accessible to users in regions where entry-level devices with 16GB of total storage are still common. In these markets, every megabyte counts. If an app takes too long to download on a metered connection or triggers a 'storage full' warning, it is the first to be uninstalled. Engineering for productivity means respecting the user’s hardware as much as their time.

Optimizing asset delivery is not just about compression; it is about choosing the right format for the right purpose. For a small studio, the goal is to maintain a single codebase that looks sharp across thousands of different screen densities (DPI) without bloating the final APK or App Bundle. This requires a shift from traditional raster-first workflows to a vector-dominant architecture, supplemented by strategic handling of remaining high-resolution bitmaps.

The Move to Vector-First Architecture

The most effective way to reduce asset overhead is to stop using PNGs and JPEGs for UI elements. In Salah Companion, almost every icon, decorative divider, and branding element is a VectorDrawable. Unlike bitmaps, which require separate files for mdpi, hdpi, xhdpi, xxhdpi, and xxxhdpi buckets, a single XML vector file scales mathematically to any resolution without losing clarity.

However, Android’s VectorDrawable is not a one-to-one replacement for standard SVG files. The Android build system must convert SVGs into a specialized XML format that the framework can render efficiently. When you import an SVG into Android Studio, it strips out unsupported elements like complex gradients, filters, or text paths.

Why Vector Complexity Matters

While vectors save disk space, they can cost CPU cycles. Every time a complex vector is drawn, the system must calculate the math for every path and curve. If you have a high-path-count vector in a scrolling list, you will see dropped frames. We learned to simplify paths in tools like Figma or Adobe Illustrator before exporting. A single complex shape with 50 nodes can often be simplified to 10 nodes without any visual change at mobile screen sizes, significantly reducing the rendering load.

Handling Necessary Bitmaps with WebP

There are times when vectors aren't enough—such as for the intricate mosque illustrations or photographic backgrounds we might consider for Mindful Assistant. When bitmaps are unavoidable, the WebP format is our primary tool. WebP provides superior lossy and lossless compression compared to PNG and JPEG.

In our experience, converting a standard PNG to a lossy WebP at 75-80% quality results in a file size reduction of 30% to 50% with no perceivable difference to the naked eye on a mobile screen. Android has supported WebP natively since version 4.0 (lossy) and 4.2.1 (lossless/transparency), making it safe for almost any modern app.

Comparison: PNG vs. WebP in Practice

Asset TypePNG Size (XXHDPI)WebP Size (80% Quality)Savings
App Logo145 KB42 KB71%
Feature Illustration850 KB210 KB75%
Icon Set (24 icons)320 KB115 KB64%

Strategic Density Splitting with App Bundles

Before the advent of the Android App Bundle (.aab), developers often resorted to 'APK splitting' to manage size. Today, the Google Play Store handles this automatically if you upload a bundle instead of a monolithic APK. The store generates 'split APKs' tailored to the specific device requesting the download.

If a user has an hdpi device, they only download the hdpi versions of your raster assets. This is why it is still important to put your remaining bitmaps in the correct res/drawable-density folders rather than dumping everything into a single res/drawable folder. If you place a large high-res image in the default folder, it is served to every device regardless of need, defeating the purpose of the App Bundle’s optimization logic.

Dynamic Asset Delivery and On-Demand Loading

For apps currently in development, like Employ Ready, we are exploring Dynamic Delivery. This allows us to separate non-essential assets into 'feature modules.' For example, the audio files used for mock interview feedback don't need to be part of the initial 5MB download. They can be downloaded in the background the first time a user starts a practice session.

This approach follows the same philosophy we discussed in our article on Onboarding Architecture: The Case for Zero-Screen Setups. The goal is to get the user into the core utility of the app as quickly as possible. Heavy assets should never be a barrier to entry.

The Hidden Cost of Unused Resources

As a product studio, we iterate fast. This often leaves 'ghost' assets in the project—icons from a discarded feature or old versions of branding. These take up space in the source code and, if not caught, in the final binary.

We use two primary methods to clean these up:

  1. 1.Lint Checks: Android Studio’s built-in Lint tool can identify 'Unused Resources.' Running this once a month is a standard part of our maintenance cycle.
  2. 2.Resource Shrinking: In the build.gradle file, we enable shrinkResources. When combined with R8 (code shrinking), the compiler can identify which resources are actually referenced in the code and strip out everything else during the build process.

``gradle android { buildTypes { release { minifyEnabled true shrinkResources true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } } ``

Optimization Checklist for Small Teams

If you are managing a productivity app, use this checklist before every major release to ensure you aren't shipping unnecessary bulk:

  • Convert Icons to VectorDrawables: Any icon that can be a vector, should be a vector. Use the 'Vector Asset' tool in Android Studio to ensure compatibility.
  • Audit Path Complexity: Open your XML vectors. If a simple icon has thousands of lines of path data, re-export it with simplified nodes.
  • Transcode Bitmaps to WebP: Use the 'Convert to WebP' right-click action in Android Studio on all PNGs and JPEGs.
  • Enable R8 and Resource Shrinking: Ensure your release builds are actively stripping unused code and assets.
  • Check the APK Analyzer: Go to Build > Analyze APK to see exactly what is taking up space. You might be surprised to find that a third-party library has bundled 2MB of fonts you don't use.

Balancing Aesthetics and Utility

Engineering for emerging markets or older devices is not about making a 'cheap' looking app. It is about being disciplined. A user who downloads ShariahSignal expects a professional, trustworthy interface to analyze financial data. If the app feels sluggish because the CPU is struggling to render unoptimized vectors, or if the app is deleted because it’s too large, we have failed to provide that utility.

We prioritize 'invisible' optimizations. The user should never know that we spent four hours simplifying a background illustration or converting PNGs to WebP. They should only notice that the app opens instantly, looks crisp on their screen, and doesn't demand they delete their family photos just to make room for a prayer tracker.

What to do next

  1. 1.Analyze your current APK: Use the APK Analyzer in Android Studio to identify your top 5 largest assets. Convert those to WebP or VectorDrawable immediately.
  2. 2.Clean your project: Run Analyze > Inspect Code and look for the 'Unused Resources' section. Delete assets that are no longer linked to your UI.
  3. 3.Switch to App Bundles: If you are still uploading .apk files to the Play Console, switch your build process to generate .aab files to take advantage of Google’s automatic density splitting.
#android development#engineering#asset management#mobile optimization

One email per launch. No spam, unsubscribe any time.