跪拜 Guibai
← All articles
Android · Kotlin · Google

Google Play Console Flagged Your Bitmaps — Here Are the Configs That Actually Fix It

By Coffeeee ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

A bitmap optimization warning in Google Play Console is a direct signal that the app is wasting memory and install size, which correlates with worse store rankings and higher uninstall rates on low-RAM devices. The fix is not a single config toggle — it spans the image library, the Compose layer, the server API, and every third-party SDK bundled into the APK.

Summary

Google Play Console's automated bitmap optimization scan flags APKs that bundle oversized images, skip WebP conversion, omit density-specific drawables, or decode full-resolution bitmaps at runtime without downsampling. The check is not just a lint warning — it directly affects the app's quality metrics and can surface as a formal rectification suggestion in the Play Console dashboard.

Fixing it means configuring Coil or Glide to always decode at display size, setting a default pixel format like RGB_565 for non-transparent images, and avoiding unconstrained layout sizes that force the library to load the original resolution. Server-side cropping via URL parameters and custom Coil interceptors shifts the work off the device entirely. For Compose projects, passing a Painter object instead of a resource ID or URL triggers unnecessary recompositions because the Compose compiler cannot mark Painter as stable.

Even when every in-house bitmap path is correct, a third-party SDK can still trigger the warning. The last mile is checking whether bundled libraries pack their own unoptimized drawables or decode bitmaps without size constraints, and updating them to versions that have already addressed the issue.

Takeaways
Google Play Console scans for four bitmap problems: oversized assets in the APK, missing WebP conversion, missing density-specific drawables, and runtime decoding without downsampling.
Coil's size resolution follows a strict priority: explicit `size()` on the request, then `Modifier.size()` from layout constraints, and finally the original resolution if nothing constrains it.
Glide requires explicit `override()` calls to avoid decoding full-resolution images; without it, the library may load the original dimensions.
RGB_565 halves memory per pixel compared to ARGB_8888 and is sufficient for over 80% of images that do not need an alpha channel.
Passing a `Painter` object to a Composable causes unnecessary recompositions because the Compose compiler cannot infer stability for types without the `@Stable` annotation.
Adding padding via letterboxing — modifying the bitmap to include transparent borders — increases memory; use `InsetDrawable` or parent padding instead.
Server-side cropping by appending width, height, mode, and quality parameters to image URLs eliminates device-side decode and resize costs entirely.
Hardware bitmaps (API 26+) store pixel data in GPU memory only, and both Coil and Glide enable them by default.
A third-party SDK that bundles its own unoptimized drawables or decodes bitmaps without size constraints can trigger the Play Console warning even when the app's own code is clean.
Conclusions

The Play Console warning is a packaging-time and runtime hybrid check — it scans both what is inside the APK and how the app decodes those assets at runtime, which means a correctly configured image library can still fail if a single unconstrained layout triggers a full-resolution decode.

The Painter stability trap in Compose is a compiler-level footgun: the Compose compiler refuses to mark Painter as stable because Bitmap equality checks are too expensive, so passing a Painter where a resource ID would suffice causes recomposition storms that have nothing to do with bitmap memory.

The advice to check third-party SDKs is the most overlooked root cause — a single bundled library with a 2MB PNG in its res folder or a manual BitmapFactory.decodeStream call without inSampleSize will trigger the warning regardless of how well the app's own image pipeline is tuned.

Concepts & terms
inSampleSize
A BitmapFactory.Options parameter that downsamples an image during decoding by an integer factor. The value must be a power of 2 (1, 2, 4, 8…); the system rounds down to the nearest power of 2. A value of 4 reduces width and height to 1/4, cutting pixel count to 1/16.
Hardware Bitmap
Introduced in Android 8.0 (API 26), a hardware bitmap stores pixel data exclusively in GPU memory rather than on the Java heap or native heap. This reduces CPU memory pressure but means the pixel data cannot be read back by the CPU without copying.
BitmapPool
A memory reuse mechanism in Glide and Coil that keeps a pool of recycled Bitmap objects. When a new Bitmap of a compatible size is needed, the library reuses an existing one from the pool instead of allocating fresh memory, reducing GC pressure.
Letterboxing
Adding transparent or colored borders directly to a bitmap's pixel data to create padding. This increases the bitmap's dimensions and memory footprint. The correct approach is to apply padding via the layout system (InsetDrawable or parent padding) without modifying the bitmap itself.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗