Tutorials Search / Native Mac IDE / Create an Android adaptive icon
📝 Written ● Intermediate Updated 2026-05-17

Create an Android adaptive icon

Android stopped shipping one icon image in 2017. Now your launcher icon is two layers — a foreground and a background — and the OS masks them into whatever shape the user's launcher prefers: circle, squircle, teardrop, square. Once you see the model, the XML and the safe-zone rule fall out of it.

iOS makes you ship one perfectly square 1024×1024 PNG and the OS rounds the corners. Android does something stranger: it asks for two PNGs at 108×108dp each, treats the inner 66×66dp as the "live" area, and lets each device's launcher apply its own mask to the rest. The mental model is upside-down compared to iOS — you're not designing an icon, you're designing the raw material a launcher will compose into an icon.

What you'll learn

Step 1: The two-layer mental model

1

Foreground plus background, masked by the launcher

An adaptive icon is two square PNGs of identical size, layered like a sticker on a card:

  • Background layer (ic_launcher_background) — a flat color, gradient, or pattern. Fills the entire 108×108dp canvas. The launcher masks this layer into its preferred shape.
  • Foreground layer (ic_launcher_foreground) — your logo or glyph. Sits on top, transparent everywhere except the artwork.

The launcher then composes the two with its own mask: Pixel uses a circle, Samsung uses a squircle, Nothing uses a teardrop, the cheap-tablet stock launcher uses a square. Your icon has to look right under all four. That's what the safe-zone rule (Step 2) is protecting.

Step 2: The 108dp / 66dp safe zone

2

Most of your canvas gets clipped — design accordingly

Both layers are 108×108dp. But only the inner 66×66dp is guaranteed to be visible after the launcher's mask is applied. The outer 21dp ring on every side is "bleed" — it exists so parallax animations and motion effects have room to move without exposing the edge.

┌──────────────────────────────┐
│  bleed zone (gets clipped)   │  21dp
│   ┌──────────────────────┐   │
│   │                      │   │
│   │   SAFE ZONE          │   │  66dp × 66dp
│   │   (your art lives    │   │  guaranteed visible
│   │    here)             │   │
│   │                      │   │
│   └──────────────────────┘   │
│                              │  21dp
└──────────────────────────────┘
            108dp × 108dp

The corollary: your logo's bounding box should never exceed 66×66dp. If it does, the Pixel launcher's circle mask will clip the corners. Keep critical elements (text, fine detail) well inside the safe zone. Decorative elements that you don't mind losing under aggressive masks can extend into the bleed.

For PNG export specifically: design at 432×432px (4× the dp for xxxhdpi density). The 66dp safe zone maps to a 264×264px square in the center.

Don't ship a one-layer icon for "older" Android compatibility and call it done. Devices on API 25 and below (pre-Android 8) still need the old single-image PNGs at five density buckets — but every device shipped since 2017 prefers the adaptive set. If you only ship the legacy PNG, your icon looks dated on a Pixel; if you only ship the adaptive set, you crash old launchers. The agent will scaffold both for you — don't skip the legacy fallback.

Step 3: The XML and folder layout

3

Where everything lives in res/

A complete adaptive-icon set is six files spread across four folders:

app/src/main/res/
├── mipmap-anydpi-v26/
│   ├── ic_launcher.xml              ← adaptive icon (foreground + background ref)
│   └── ic_launcher_round.xml        ← same, for circle launchers
├── drawable/
│   └── ic_launcher_foreground.xml   ← vector drawable for foreground
├── values/
│   └── ic_launcher_background.xml   ← color resource for background
└── mipmap-{m,h,xh,xxh,xxxh}dpi/
    ├── ic_launcher.png              ← legacy fallback PNGs
    └── ic_launcher_round.png        ← same, round variant

The adaptive XML in mipmap-anydpi-v26/ic_launcher.xml is the entry point and looks like this:

<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
    <background android:drawable="@color/ic_launcher_background" />
    <foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

That's the whole interface: point at a background (color or drawable) and a foreground drawable. The -v26 suffix on the folder name is what tells the build system "only use this on API 26+." Older devices fall back to the PNG in mipmap-{density}/.

Step 4: The fast path — App Icon Generator (covers Android too)

4

Mobile menu → App Icon Generator… → Android target → Generate

LingCode's App Icon Generator sheet — opened from the menu bar via Mobile → App Icon Generator… — handles Android adaptive icons in the same pass it does iOS. Toggle iOS off if you only want Android, point the Android target at app/src/main/res/, and either drop a 1024×1024 master or type a prompt and let the built-in image generator produce one.

The Android pass writes three files per density bucket — ic_launcher.png (the legacy square), ic_launcher_round.png (the legacy round fallback), and ic_launcher_foreground.png (the adaptive foreground) — across mipmap-mdpi through mipmap-xxxhdpi. The sheet lists every file written so you can verify before closing.

Two things the sheet does not do automatically: it doesn't write the adaptive XML (mipmap-anydpi-v26/ic_launcher.xml) or the background color resource. Those are tiny — a few lines each (see Step 3) — and the agent can scaffold them via a one-line chat prompt: "add the adaptive-icon XML wrappers for ic_launcher and ic_launcher_round, background color #5B6CFF." Together the two passes get you a complete adaptive icon set.

Step 5: Or do it via chat

5

One prompt, the whole set

Open a Claude chat in your Android project root and ask:

Add an adaptive launcher icon to this Android project.
- Foreground: ~/Desktop/logo.svg (already sized for the 66dp safe zone)
- Background color: #5B6CFF
Generate the adaptive XML, the foreground vector drawable, and PNG
fallbacks for mdpi through xxxhdpi.

The agent will produce roughly eight files: the two adaptive XML files (square and round), the foreground vector drawable, the background color resource, and ten PNG fallbacks (one round, one square, at five densities each). It'll also touch AndroidManifest.xml if needed — but the default android:icon="@mipmap/ic_launcher" is usually already in place from the project template.

Don't have a logo yet? Ask the chat's generate_image tool first — "generate a 1024×1024 icon foreground: minimalist letter L glyph in white on transparent background, flat, no shadow, centered with 25% padding" — and the agent saves it to <project>/assets/ via Gemini. Once you like it, ask for the adaptive-icon scaffold pointing at that file. Two prompts, complete icon set.

Verify by opening app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml and confirming the <adaptive-icon> block references the resources you expect. Then build and install — see Step 6.

Don't have a vector logo? The agent can convert a PNG to a vector drawable using Android's VectorDrawableCompat format — paste the path to your PNG and ask. Vector is preferred because the foreground layer gets rendered at every density without re-rasterizing, so a tiny logo file ends up razor-sharp at xxxhdpi.

Step 6: Preview in the emulator

6

Build, install, check the launcher

Hit ⌘R in your project. The Run Destination Picker opens with an Android emulators section listing every configured AVD — offline AVDs auto-boot when selected. Pick yours and LingCode builds, runs adb install, and launches the app.

Press the home button (or swipe up, depending on the AVD's launcher) and look at your app's launcher icon. You should see your foreground centered on the background, masked into whatever shape the AVD's launcher uses. If the icon looks clipped on the edges, your foreground extends into the bleed zone — pull it back into the 66×66dp safe area.

To see the icon under multiple launcher masks without rebuilding, install one of the "launcher icon preview" apps from the Play Store inside the AVD. Cheaper than maintaining four physical devices.

Step 7: Diagnose a failure

7

Three things that go wrong

SymptomCauseFix
Icon is the default Android green robot AndroidManifest.xml doesn't point at @mipmap/ic_launcher, or the file isn't in the right folder. Open the manifest, confirm <application android:icon="@mipmap/ic_launcher">. Confirm res/mipmap-anydpi-v26/ic_launcher.xml exists.
Icon shows but the foreground is clipped at the corners Foreground art extends past the 66dp safe zone. Rescale the foreground inside its 432×432 canvas so the artwork is within the central 264×264 region.
Old Android devices (API ≤ 25) show no icon or a fallback Missing legacy PNG fallbacks in mipmap-{density}/ folders. Add 48/72/96/144/192px PNGs (one per density bucket). The agent will generate these from your foreground if asked.

What's next