Pocket Studio Academy
HomePart 66.1

App icons that look real (adaptive, vector)

Full course12 min read·4 questions

Your icon is the only part of your app that everyone sees, including people who never open it. This lesson takes apart the real adaptive vector icon shipped with Dice Duel — two layers, one 108-unit grid, a safe zone, and not a single picture file.

The one screen you do not control

You have built three apps. They run, they save, they survive rotation. And there is still one surface where all three can be spotted as homemade from two metres away: the home screen.

Everything else about your app is drawn by your code. The icon is not. The launcher draws it, at a size you did not choose, in a shape you did not choose, next to Spotify and WhatsApp. It is the only part of the app that people who never install it will see.

The good news: Dice Duel, Pocket Notes and Focus Flow already ship proper icons, and the entire thing is four small text files with no pictures in them at all. This lesson is a tour of those files, so you can make your own.

Think of it like this

Think about rolling out biscuit dough.

You roll one big sheet. Then everyone in the kitchen presses a different cutter into it: a circle, a rounded square, a squircle, a teardrop. Whatever is under the cutter survives. Whatever was near the edge of the sheet gets scraped back into the bowl.

That is exactly the deal Android offers. You hand in one oversized sheet of artwork. Every phone presses its own into it — and the phone chooses, not you. Samsung cuts a squircle. A Pixel cuts a circle. Some launchers let the user pick.

So you do not design a circle, or a square. You design a sheet, and you keep everything that matters well away from the edges.

Two layers, not one picture

Before Android 8.0, an app icon was a flat picture with its own shape already baked into it — a . Every app looked different, because every designer drew a different outline, and the launcher could not do anything about it.

Android 8.0 replaced that with the : two layers.

  • A background layer, which fills the whole sheet. Usually a flat colour.
  • A foreground layer, which holds the artwork, floating over the background.

The launcher lays one on top of the other, presses its mask into the pair, and gets a shape that matches every other icon on the phone. Keeping the layers separate also buys you : on some launchers the foreground slides a little against the background when the icon is dragged or pressed. You get that for free, and only because the two layers are separate files.

Here is Dice Duel's, in full. Four lines of it are the whole idea.

The grid: 108, 72, 66

The sheet is 108 by 108 units. Not pixels — units, the same idea as . Android scales the whole thing to whatever size the launcher wants.

Of those 108 units, the outer 18 on every edge are reserved. They exist so the mask has something to cut into and so parallax has somewhere to slide. That leaves an inner square of 72 by 72 that no mask will ever reach past.

Inside that, there is a stricter rule. Masks are not all squares — a circle mask cuts the corners off the 72-square too. So the guaranteed area, the , is a circle of diameter 66 in the middle of the sheet.

RegionSizeWhat it means
Whole sheet108 x 108What you draw on
Reserved edge18 on each sideMasking and parallax live here
Never masked out72 x 72No mask reaches past this square
Safe zone66 circleGuaranteed visible on every phone

Pocket Notes puts the rule in a comment at the top of its own foreground file, and then obeys it:

res/drawable/ic_launcher_foreground.xmlxml
1<!--
2  An adaptive icon is 108x108, but only the middle
3  72x72 is always visible. Everything below stays
4  inside x=28..80, y=24..84 so no launcher shape
5  can crop it.
6-->

x from 28 to 80 is a 52-wide block centred on 54, which is the middle of the sheet. That is comfortably inside 72, and the page shape has rounded corners, so the parts that poke outside the 66 circle are corner radius rather than anything you would miss. This is the normal way to work: draw well inside 72, keep anything that carries meaning inside 66.

The commonest icon mistake

Drawing your artwork at full size, edge to edge, because it looks great in the editor. Then the phone cuts a circle out of it and the top of your logo is gone.

Draw small. An adaptive icon looks correct when the artwork occupies roughly the middle two thirds and there is generous background all around it. Every icon on your home screen right now is drawn that way.

Why the foreground is a vector

Here is the file the foreground points at — the top of Dice Duel's die, with the shadow group left out for room:

res/drawable/ic_launcher_foreground.xmlxml
1<?xml version="1.0" encoding="utf-8"?>
2<vector
3xmlns:android="http://schemas.android.com/apk/res/android"
4    android:width="108dp"
5    android:height="108dp"
6    android:viewportWidth="108"
7    android:viewportHeight="108">
8
9  <group
10    android:pivotX="54"
11    android:pivotY="54"
12    android:rotation="-14">
13
14    <path
15      android:fillColor="#FFFDFBFF"
16      android:pathData="M40,30 H68 A10,10 0 0 1 78,40
17        V68 A10,10 0 0 1 68,78 H40 A10,10 0 0 1 30,68
18        V40 A10,10 0 0 1 40,30 Z" />
19  </group>
20</vector>

It is a : a description of shapes rather than a grid of coloured dots.

android:width and android:height say how big it is by default. viewportWidth and viewportHeight set the the shapes are described on — 108 by 108, matching the icon sheet exactly, which is why the numbers in pathData can be read straight off the grid above.

The <group> wrapper rotates everything inside it by 14 degrees around the point (54, 54) — dead centre. Rotating the die makes it look thrown rather than placed. One attribute, and no maths on your part.

The string is the shape itself. M40,30 moves the pen to x 40, y 30. H68 draws a horizontal line to x 68. A10,10 0 0 1 78,40 sweeps a 10-unit arc to make the rounded corner. Z closes it. The die face is one rounded square; all five pips are a second path.

The four numbers 40, 30, 68, 78 are all inside the 66 circle. That is not a coincidence.

Vector against PNG, honestly

The alternative is a — a fixed grid of dots. To ship one you need a copy per : 48, 72, 96, 144 and 192 pixels. And an adaptive icon has two layers, so that is ten files, plus a round variant. Fifteen pictures for one icon.

Three reasons the vector wins here, and only one of them is about file size.

It is sharp everywhere. Your icon is not drawn at one size. The launcher draws it small, the recents screen draws it medium, Settings draws it in a list, the share sheet draws it tiny, and the Play listing wants 512 pixels. A vector is re-drawn from its shapes at every one of those. A 96-pixel PNG stretched to 192 goes soft, and people can tell even when they cannot say why.

It is tiny. Dice Duel's entire icon — foreground, background colour, and both adaptive-icon files — is about 2.3 kB of text. Fifteen PNGs would be a couple of hundred kilobytes of your , for one picture.

You can build it on a phone. This matters more than the other two for you specifically. Making five sizes of a PNG needs an image editor, an export step, and somewhere to keep the original. A vector is a text file you can type in and change with one edit. Making the background green is one character. Making fifteen PNGs green is an afternoon.

That is why not one of the three apps in this course contains a single picture file.

Why mipmap and not drawable

The foreground lives in res/drawable/. The adaptive icon itself lives in res/mipmap-anydpi-v26/. Both are ; why two folders?

Because is treated as special. When an app is built into per-density downloads, unneeded densities get stripped out — and a launcher sometimes asks for an icon at a higher density than the phone itself uses, so that icons look right in a bigger grid. Anything in mipmap is kept regardless. It is one folder with one job: launcher icons.

So the rule is simply: ic_launcher.xml goes in mipmap; everything it points at can live in drawable.

anydpi-v26, and one bit of luck

The folder name is mipmap-anydpi-v26. Two stuck together:

  • anydpi — use this at any screen sharpness. A vector has no sharpness, so one copy serves every phone.
  • v26 — only on API level 26 and up. <adaptive-icon> did not exist before Android 8.0, so an older phone must not be handed this file.

Normally you would also ship a plain mipmap-hdpi/ic_launcher.png and friends, as the fallback for phones below API 26. All three apps in this course skip that entirely, and it is legitimate rather than lazy: minSdk = 26. The lowest Android version any of these apps will ever run on is exactly the version that arrived in. There is no older phone to fall back for.

That decision was made back in Part 2, and this is one of the places it pays.

The round icon

Look in the manifest and you will find two icon attributes, not one:

app/src/main/AndroidManifest.xmlxml
1android:icon="@mipmap/ic_launcher"
2android:roundIcon="@mipmap/ic_launcher_round"

is a leftover from the year adaptive icons launched: some launchers always draw a circle and wanted artwork designed for one. If you name it in the manifest, the file has to exist, or the build fails.

In Dice Duel, ic_launcher_round.xml is byte-for-byte the same adaptive icon. That is fine, and it is what most apps do now — an adaptive icon already handles a circular properly, so there is nothing to design differently. Ship both names, point them at the same two layers, move on.

Tip

<monochrome> costs you one extra line and reuses a file you already wrote. Add it. The reader of your icon might be someone whose entire home screen is themed to a photograph of their dog, and yours will be the only icon that ignores it.

Try it in Pocket Studio
  1. Open Pocket Studio, tap Projects, and open Dice Duel.
  2. Tap Editor and open app/src/main/res/values/ic_launcher_background.xml.
  3. Change the colour from #FF5B3FD6 to #FF0E7C6B — the teal already used for player two.
  4. Tap Build, then Run ▶.
  5. Go to your home screen and look at the Dice Duel icon. It is teal. You changed an app icon by editing seven characters.
  6. Now break the safe zone on purpose. Open app/src/main/res/drawable/ic_launcher_foreground.xml and change the group's android:rotation="-14" to android:scaleX="1.9" on its own line, keeping the pivot lines.
  7. Tap Run. Look at the home screen again: the die is now far too big and its sides are sliced off by the launcher's mask. That is what leaving the 66 circle looks like.
  8. Undo both changes — colour back to #FF5B3FD6, and android:rotation="-14" back in place of the scale line. Tap Run once more and check the icon is right again.
  9. Optional: long-press an empty part of your home screen, open your launcher's settings, and turn on themed icons if your phone offers them. Dice Duel joins in, because of <monochrome>.
Error Doctor5 common errors
AAPT: error: resource mipmap/ic_launcher not found.
MeansThe manifest names an icon that does not exist. Either the file is missing, or it is spelled differently, or it is in the wrong folder — for example res/drawable/ic_launcher.xml instead of res/mipmap-anydpi-v26/.
FixCheck the path and the spelling. The resource name is the filename without .xml, so mipmap/ic_launcher means a file called exactly ic_launcher.xml inside a folder whose name starts mipmap.
AAPT: error: resource mipmap/ic_launcher_round not found.
MeansYou created ic_launcher.xml but not ic_launcher_round.xml, and the manifest still names both. The two attributes are checked separately.
FixEither copy ic_launcher.xml to ic_launcher_round.xml in the same folder — which is exactly what all three apps here do — or delete the android:roundIcon line from the manifest.
AAPT: error: <adaptive-icon> elements require a sdk version of at least 26.
MeansThe adaptive icon is in a folder that older Android versions would also read: mipmap, mipmap-hdpi, or mipmap-anydpi with no version on the end. AAPT2 refuses, because it cannot promise the phone will understand the tag.
FixRename the folder to mipmap-anydpi-v26. The -v26 is not decoration — it is the promise that only Android 8.0 and newer will ever be handed this file.
AAPT: error: resource color/ic_launcher_background not found.
Means<background android:drawable="@color/ic_launcher_background" /> points at a colour that is not defined anywhere in res/values/.
FixCreate res/values/ic_launcher_background.xml with <resources><color name="ic_launcher_background">#FF5B3FD6</color></resources>. The name must match the reference character for character.
AAPT: error: not well-formed (invalid token).
MeansThe XML itself is broken before anything Android-specific is even looked at — usually a missing /> on a <path>, a stray <, or an unclosed <group>.
FixThe error line number is the place AAPT2 gave up, which is often just after the real mistake. Work upwards from it and check every tag either closes with </tag> or ends with />.
Recap
  • An is two layers — a background and a foreground — on a 108 by 108 sheet. The launcher presses its own into the pair.
  • The outer 18 units of every edge can be cut away. Keep anything meaningful inside the , which means drawing much smaller than feels natural.
  • A foreground is sharp at every size the system asks for, costs about 2 kB instead of fifteen files, and can be edited on the phone with no image editor.
  • Launcher icons go in , not drawable, so they survive density stripping. The folder is mipmap-anydpi-v26 because <adaptive-icon> needs Android 8.0.
  • Ship pointing at the same file, and add a layer so themed home screens include your app.
  • Next: the four faces of every screen — what your app shows while it is loading, when there is nothing to show, and when something has gone wrong.