Android Adaptive Icons: A Developer's Complete Guide
The foreground/background layer model, 108dp canvas, density buckets, mask shapes, XML configuration, and common mistakes explained.
Before Android 8.0 (API 26), every app icon was a static PNG. Manufacturers applied their own shapes on top, and the results ranged from acceptable to terrible. Adaptive icons fixed this by separating the icon into two layers — foreground and background — that the OS composites and masks independently.
The system is elegant but has specific dimensional requirements that are easy to get wrong. This guide covers the layer model, the safe zone math, density buckets, and the XML configuration in detail.
The Two-Layer Model
An adaptive icon consists of two layers: a foreground layer containing your logo or symbol, and a background layer that fills the area behind it. Both layers are 108x108 dp (density-independent pixels) canvases. The OS renders the background first, places the foreground on top, then applies a mask to clip both layers into the device's icon shape.
Both layers can be any drawable resource: a vector drawable, a bitmap, a solid color, or a gradient. Using vector drawables is strongly recommended because they scale cleanly across all density buckets without separate raster files for each one.
The 108dp Canvas and the 72dp Safe Zone
Why 108dp? The OS needs room to animate the icon layers. When a user long-presses an app icon or drags it between home screen pages, the foreground layer shifts slightly to create a parallax effect. The extra 18dp on each side (108 minus 72, divided by 2) gives the foreground room to move without exposing empty space at the edges.
The visible area of the icon is a 72dp circle (or squircle, or rounded square) centered within the 108dp canvas. That means only the inner 66.7% of each layer is guaranteed to be visible. Everything outside the 72dp circle is clipping territory.
The safe zone is smaller than you think
Density Buckets Explained
Android scales dp values to actual pixels using density buckets. Each bucket has a multiplier: mdpi is 1x, hdpi is 1.5x, xhdpi is 2x, xxhdpi is 3x, and xxxhdpi is 4x. Since the adaptive icon canvas is 108dp, each density bucket produces a different pixel dimension.
| Density | Scale Factor | Icon Size (px) | Canvas Size (px) | Safe Zone (px) |
|---|---|---|---|---|
| mdpi | 1x | 48x48 | 108x108 | 72x72 |
| hdpi | 1.5x | 72x72 | 162x162 | 108x108 |
| xhdpi | 2x | 96x96 | 216x216 | 144x144 |
| xxhdpi | 3x | 144x144 | 324x324 | 216x216 |
| xxxhdpi | 4x | 192x192 | 432x432 | 288x288 |
The "Icon Size" column shows the final rendered size users see on screen. The "Canvas Size" column shows the full 108dp canvas at each density. The "Safe Zone" column shows the 72dp safe zone in pixels. Your foreground content must fit within the safe zone dimensions.
Icon Size Across Densities
This chart shows the rendered icon size in pixels for each density bucket, plus the Play Store requirement. The jump from xxxhdpi (192px) to the Play Store icon (512px) is significant — the Play Store icon is not just a scaled-up version of your launcher icon, and it deserves its own attention.
How the OS Applies Masks
Device manufacturers choose the mask shape. Google Pixel uses a circle. Samsung uses a squircle (a superellipse that is somewhere between a circle and a rounded square). Other manufacturers use rounded squares, teardrops, or custom shapes. Your adaptive icon must look good under all of them.
The key insight: you do not control the mask shape. The OS does. This is why the safe zone matters so much. If your foreground content stays within the 72dp circle, it will survive any mask shape, because every possible mask inscribes within or closely matches that circle.
You can preview different mask shapes in Android Studio's Image Asset Studio (right-click res > New > Image Asset). It shows your icon under circle, squircle, rounded square, and square masks simultaneously.
Creating the Adaptive Icon XML
The adaptive icon is defined in an XML file that references separate drawable resources for the foreground and background layers. Place this file in res/mipmap-anydpi-v26/ so it is used on API 26+ devices, while older devices fall back to the legacy PNG icon.
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>The background drawable can be a vector, a color resource, or a bitmap. For simple solid-color backgrounds, you can inline the color:
<?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><resources>
<color name="ic_launcher_background">#1A73E8</color>
</resources>Registering the Icon in AndroidManifest.xml
The manifest must reference both the adaptive icon (for API 26+) and a legacy icon (for older devices). Use android:icon for the standard icon and android:roundIcon for devices that specifically request round icons.
<application
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<!-- activities, services, etc. -->
</application>roundIcon is optional but recommended
android:roundIcon attribute was introduced in API 25 (Android 7.1). It lets you provide a pre-masked circular icon for devices that requested round icons before adaptive icons existed. If you use adaptive icons, the round icon is generated automatically, but having an explicit one ensures pixel-perfect rendering on API 25 devices.The Play Store 512x512 Requirement
Google Play requires a 512x512 PNG icon for the store listing. This is separate from your adaptive icon. It is not extracted from your APK. You upload it manually through the Play Console.
The Play Store icon should visually match your launcher icon but does not need to follow the adaptive icon layer structure. It is a flat PNG. Google applies its own rounded-corner mask when displaying it in the store. Like Apple, do not pre-round the corners.
This icon appears in search results, the app detail page, and "similar apps" lists. It is your app's first impression. A blurry or poorly cropped icon here directly impacts download conversion rates.
Common Mistakes
1. Foreground content too close to edges
The most frequent mistake. Designers place the logo in a 72dp square and call it done. But the safe zone is a 72dp circle, not a square. Content in the corners of a 72dp square will be clipped on devices using circular masks. Keep foreground content within roughly 66dp diameter to be safe across all masks.
2. Transparent background on the foreground layer
The foreground layer should have a transparent background — the background layer provides the fill. But some designers accidentally make both layers transparent, resulting in a see-through icon that shows the wallpaper behind it. The background layer must be opaque.
3. Using raster images instead of vectors
Raster (PNG) foreground layers require separate files for each density bucket: five sizes instead of one vector drawable. Vectors scale perfectly and keep APK size down. Unless your icon includes photographic content, use vector drawables for both layers.
4. Forgetting the legacy icon
Devices running Android 7.1 and earlier do not support adaptive icons. They need traditional PNG icons in res/mipmap-mdpi/ through res/mipmap-xxxhdpi/. If you only provide the adaptive XML, your app will crash or show a default icon on older devices.
Use Android Studio's Image Asset Studio
Monochrome Icons for Themed Icons
Android 13 introduced themed icons. When a user enables this feature, the system takes a monochrome layer from your adaptive icon and applies the device's dynamic color palette. If you do not provide a monochrome layer, your icon gets a generic placeholder in themed mode.
<?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" />
<monochrome android:drawable="@drawable/ic_launcher_monochrome" />
</adaptive-icon>The monochrome drawable should be a vector with a single color (typically black or white) on a transparent background. The system replaces the color with the user's palette. Keep the shape simple and recognizable — fine details disappear when the entire icon is one color.