Real iPhone, Pixel and Galaxy frames around running MuMu Player windows — live on your desktop, for screen recordings and app demos. No injection, no root, no emulator changes: a tray app that attaches a frame to each emulator and teaches the emulator's Android about it.
Built to record ads for JustGains — the app in the screenshots — and released because there was nothing like it.
-
The frame belongs to the emulator, not to the top of the screen. It sits directly above its emulator in the window stack, so anything you place over the emulator — captions, an overlay, a second app — covers the frame too. Minimize, restore, move: the frame follows.
-
The MuMu window disappears. Title bar, toolbar, borders and window shadow are gone; only the phone's rounded screen is left. On a chroma-key desktop you get phone + key colour and nothing else.
-
Android knows about the frame. A stock emulator lays itself out as a plain rectangle, so the clock slides under the rounded corners and app headers sit beneath the Dynamic Island. One click gives the emulator the frame's real display cutout, status-bar height and corner radius, so apps get the same safe-area insets as on the physical phone.
-
Pixel-perfect screenshots. The Save tile at the top of the bezel menu takes the shot inside Android and composites it into the frame at native resolution (1520 × 3068 for a 17 Pro Max), whatever is covering the emulator window. Copy puts the same PNG, transparent corners included, straight on the clipboard for Figma, Photoshop, Slack or a chat window.
-
145 frames from the open device-frames-media set — iPhone 6s to 17 Pro Max, iPhone Air, Pixel 8/9, Galaxy S21, iPads, Apple Watch — downloaded on first run.
-
iOS-style status bar (optional). Hides Android's clock and icons and draws an iPhone status bar in their place: bold time, cellular bars, Wi-Fi and battery, centred on the island and switching between black and white with whatever the app asks for. It is click-through, so the notification shade still works, and framed screenshots include it.
- Download
MuMuDeviceFrames-win-x64.zipfrom Releases, unzip anywhere, runMuMuDeviceFrames.exe. It lives in the tray. (Self-contained; nothing else to install.) - Say yes to the frame download (~35 MB, once).
- Start a MuMu emulator. It gets the frame that best fits its picture — with MuMu's default phone resolution that is an iPhone 16 Pro / 17 Pro.
For the Android matching (status bar/cutout) the tool needs the Android SDK build tools and a Java runtime; see below.
| Action | Result |
|---|---|
| Drag the bezel | Moves the emulator (its title bar is hidden, so the bezel is the handle) |
| Right-click the bezel | Menu for that emulator: Copy / Save / Reload / Dev gear tiles, then frame, Android display, minimize |
| Double-click the bezel | Peek: brings MuMu's title bar and toolbar back without dropping the frame; again to hide |
Ctrl+Alt+F |
All frames off / on (off = emulators look exactly like stock MuMu) |
Ctrl+Alt+R |
Reload the Expo app in the active or last active emulator |
Ctrl+Alt+G |
Show or hide Expo's floating gear in that emulator |
| Tray icon | Same menus for every emulator, default frame, frame download, Start with Windows, exit |
The Expo actions are also in each emulator's bezel and tray menus. They work when an Expo development app is in front
inside that emulator. With several emulators open, click the one you want before using a hotkey. External hotkey tools
can run MuMuDeviceFrames.exe --expo-reload or MuMuDeviceFrames.exe --expo-gear while the tray app is running. Add an
emulator name, such as --expo-reload JG-2, to target one directly.
Frame menus mark each model Exact fit / Near fit for that emulator's picture. A frame whose screen aspect is within 1.5 % of the emulator's is stretched to fit exactly (invisible); anything further off keeps its proportions and crops the picture under the bezel — or use Android display ▸ Set resolution to W×H, which writes the frame's exact screen resolution into MuMu's settings (density scaled so the app layout keeps its size) and restarts that emulator.
Landscape: when MuMu rotates its window, the frame rotates with it (phone top to the left).
Match Android status bar and cutout to frame (per emulator) measures the island, notch or camera hole and the
corner size from the frame's own mask.png and installs them into the emulator as a display cutout, status-bar height,
corner radius and status-bar side padding. It follows frame changes automatically (rebuilds in a few seconds), survives
emulator restarts, and unticking it uninstalls everything. StatusBarPaddingFactor in the config moves the clock and
icons further in or out.
iOS-style status bar in the tray menu (or IosStatusBar in the config) applies to every emulator as it
starts; the bezel menu can override it for one emulator. It turns on the cutout matching above by itself, empties
Android's status bar through SystemUI's icon blocklist (settings put secure icon_blacklist …) and the SystemUI overlay
(no notification icons, overflow dot or clock — Android 15's clock ignores the blocklist), then draws
the iPhone bar in a click-through window over the picture. Light/dark follows the foreground app's
LIGHT_STATUS_BARS request, polled once a second. StatusBarClock sets the time (auto, 24h, or fixed text such as
9:41); StatusBarFont picks the font (SF Pro if installed, otherwise Segoe UI Semibold). Works best together with the
cutout matching above. Unticking it, exiting, or --restore gives Android its own status bar back.
How this works without root: MuMu's Android images are signed with the public AOSP platform test key, and Android
lets an overlay signed like its target override any of the target's resources. The tool generates two tiny
resource-overlay APKs (com.justsuperhuman.deviceframes.cutout → android, ….systemui → com.android.systemui),
signs them with that key (tools/aosp-platform-key) and enables them over adb.
Requirements: Android SDK build-tools (aapt2, zipalign, apksigner) and a platform android.jar, found through
ANDROID_HOME or the AndroidSdk config entry, plus Java for apksigner. Android Studio's SDK Manager installs all of
it. To remove by hand: adb uninstall com.justsuperhuman.deviceframes.systemui and …deviceframes.cutout.
%APPDATA%\MuMuDeviceFrames\config.json (tray ▸ Open config folder, then Reload frames and config). Frame choices
and the Android-matching switch are stored per emulator name. log.txt is next to it.
| Key | Default | |
|---|---|---|
FramesRoot |
%APPDATA%\MuMuDeviceFrames\frames |
Frame set folder. A device-frames-output folder next to the exe is used if present. |
DefaultFrame |
null (best aspect match) |
"Category/Model/Variant", e.g. "Apple iPhone/17 Pro Max/Cosmic Orange" |
ClipToScreen |
true |
Hide the MuMu window around the picture |
Overlap |
1 |
Pixels the bezel overlaps the picture, so its anti-aliased edge blends with app content |
BezelInteractive |
true |
false makes the frame fully click-through |
Hotkey |
Ctrl+Alt+F |
|
ExpoReloadHotkey |
Ctrl+Alt+R |
Reload the Expo app in the active or last active emulator; empty string disables it. |
ExpoGearHotkey |
Ctrl+Alt+G |
Show or hide Expo's floating gear there; empty string disables it. |
LastActiveEmulator |
null |
Last emulator used for Expo hotkeys when another app is in front. Updated automatically. |
StatusBarPaddingFactor |
0.5 |
Status-bar side padding as a fraction of the frame's corner size |
IosStatusBar |
false |
iOS-style status bar on every emulator (per-emulator overrides live under Instances) |
StatusBarClock |
auto |
Time on the iOS-style bar: auto, 24h, or fixed text like 9:41 |
StatusBarFont |
null |
Font for that time (SF Pro if installed, else Segoe UI Semibold) |
AndroidSdk |
null (ANDROID_HOME) |
SDK folder for the overlays |
ProcessNames |
MuMuNxDevice, MuMuPlayer, NemuPlayer |
Emulator executables to attach to |
Command line: --exit (quit the running instance cleanly) · --expo-reload [emulator] / --expo-gear [emulator] (Expo actions; omit the name to use the running tray app) · --startup on|off (start with Windows) · --restore (un-clip all emulator windows; only needed if
the app was killed — starting it again does the same) · --download [folder] (fetch the frame set) ·
--screenshot <emulator> <out.png> [frame] [transparent|checker|#RRGGBB] (framed screenshot at native resolution) ·
--snapshot <emulator> <out.png> [frame|-] [background] (composite of the window and the frame, for checking
alignment) · --render <frame> <w> <h> <out.png> · --cutout-spec <frame> <w> <h> <dpi>.
Three window-manager features, all from outside the MuMu process:
- Owned layered window. Each frame is a per-pixel-alpha window (
UpdateLayeredWindow) whose owner is the emulator's top-level window. Windows keeps an owned window immediately above its owner and minimizes, restores and destroys it with the owner — that is the "attached but not topmost" behaviour, done by the window manager itself. Transparent pixels are click-through; only the bezel takes mouse input, and dragging it moves both windows in oneDeferWindowPosbatch. - Window region.
SetWindowRgnon the emulator, built from the frame'smask.png, hides everything but the screen. The region is grown 2 px so its hard edge lies under the opaque bezel, and the bezel overlaps the picture by 1 px so the anti-aliased inner edge always blends with app pixels, never with the desktop. - DWM attributes. A region alone leaves DWM painting the window's shadow and 1 px border around the unclipped
rectangle.
DWMWA_NCRENDERING_POLICY = DISABLED+DWMWA_BORDER_COLOR = NONEremove that; the theming layer then installs a region of its own, which is why ours is verified and re-applied.
Tracking uses SetWinEventHook per emulator process plus a 1.5 s scan for new emulators. Frames are resampled once per
picture size with a separable Lanczos-3 filter in premultiplied alpha, with the screen hole's edges snapped to whole
pixels; about 70 ms, cached and shared between emulators of the same size. Everything is reverted on exit.
Why not a Windhawk mod or a DLL in MuMu: injected code can only draw inside MuMu's window, and the bezel lives outside it. A second window is needed either way — and with one, nothing has to run inside the emulator process.
- OBS Window Capture of the emulator won't include the frame (it is a separate window). Use display or region capture.
- In landscape Android keeps its normal status bar and moves the cutout to the side, as a real phone does; only the portrait status-bar height is overridden.
- Frame variants with baked-in shadows take mouse input on the shadow too (any pixel with alpha).
- Windows only; MuMu Player 12 (
MuMuNxDevice.exe) is what it was written against. Older MuMu builds are matched by process name and the samenemuwinrender surface, untested.
dotnet publish -c Release -r win-x64 --self-contained -p:PublishSingleFile=true -o publish
.NET 10 SDK. Source is in src/; tools/make-icon.ps1 regenerates the icon. Releases are built by
GitHub Actions on v* tags.
- Frame images: device-frames-media by Jonny Jackson. They are downloaded from that project at first run, not bundled here.
- Written for JustGains, the workout and nutrition app in the screenshots.
MIT — see LICENSE.


