Skip to content

fix(android): generate adaptive icon layers at adaptive-icon sizes - #653

Closed
shivapoudel wants to merge 1 commit into
ionic-team:mainfrom
shivapoudel:fix/android-adaptive-icon-sizes
Closed

shivapoudel wants to merge 1 commit into
ionic-team:mainfrom
shivapoudel:fix/android-adaptive-icon-sizes

Conversation

@shivapoudel

Copy link
Copy Markdown

Problem

generateAdaptiveIconForeground() and generateAdaptiveIconBackground() filter AndroidAssetTemplates on AssetKind.Icon:

const icons = Object.values(AndroidAssetTemplates).filter(
  (a) => a.kind === AssetKind.Icon,
) as AndroidOutputAssetTemplateAdaptiveIcon[];

That yields the legacy launcher sizes rather than the adaptive-icon sizes:

density emitted (Icon) expected (AdaptiveIcon)
ldpi 36 81
mdpi 48 108
hdpi 72 162
xhdpi 96 216
xxhdpi 144 324
xxxhdpi 192 432

Every adaptive layer is written 0.444x (48/108) too small.

It goes unnoticed because two passes write the same paths. When icon-foreground.png / icon-background.png are supplied as standalone sources, generateFromLogo() first emits correct adaptive-icon-sized layers, then these two handlers overwrite them at legacy sizes:

CREATE android adaptive-icon .../mipmap-xxxhdpi/ic_launcher_foreground.png (10.12 KB)
CREATE android icon         .../mipmap-ldpi/ic_launcher_foreground.png (816 B)

Android then upscales the layers 2.25x to fill the 108dp adaptive layer, so the launcher icon renders visibly blurry on device.

The as AndroidOutputAssetTemplateAdaptiveIcon[] cast on the same expression suppressed the type error that would otherwise have flagged this.

Fix

Filter on AssetKind.AdaptiveIcon in both handlers. generateLegacyIcon() keeps AssetKind.Icon, which is correct for the pre-API-26 ic_launcher assets.

Output paths and filenames are unchanged — the two template sets share the same density keys and differ only in width/height.

Reproducing

Place icon-foreground.png and icon-background.png (1024x1024) in assets/, run capacitor-assets generate --android, then check the layer dimensions:

file android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
# before: 192 x 192
# after:  432 x 432

Verification

  • npm run build — passes
  • npm test — 7 suites, 17 passed / 1 skipped
  • npm run lint — passes (the 12 no-non-null-assertion warnings are pre-existing in src/platforms/ios/index.ts)
  • Applied as a local patch on 3.0.5 in a real app: adaptive layers now 81-432px, legacy ic_launcher still 36-192px, mipmap-anydpi-v26/*.xml unchanged, :app:assembleDebug passes, blur gone.

generateAdaptiveIconForeground and generateAdaptiveIconBackground filter
AndroidAssetTemplates on AssetKind.Icon, so they emit the legacy launcher
sizes (36/48/72/96/144/192) instead of the adaptive-icon sizes
(81/108/162/216/324/432) — every layer comes out 0.444x too small.

Both generator passes write the same mipmap-*/ic_launcher_foreground.png
and ic_launcher_background.png paths, and the undersized pass runs last,
so its output wins. Android then upscales the layers 2.25x to fill the
108dp adaptive layer and the launcher icon renders visibly blurry.

The `as AndroidOutputAssetTemplateAdaptiveIcon[]` cast on the same
expression suppressed the type error that would otherwise have caught
this.

generateLegacyIcon keeps AssetKind.Icon, which is correct for the
pre-API-26 ic_launcher assets.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@shivapoudel

Copy link
Copy Markdown
Author

Moving this to the Capawesome fork instead: capawesome-team#4. Closing here.

@shivapoudel
shivapoudel deleted the fix/android-adaptive-icon-sizes branch October 16, 2026 09:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant