From b43718aca8d402eeb0eaee21091c7bef729af1f4 Mon Sep 17 00:00:00 2001 From: Hadrian Burkhardt Date: Tue, 13 Oct 2026 23:46:07 +0200 Subject: [PATCH] docs: record the store screenshot re-shoot over the demo library The three captures no longer show the "Photo access needed" banner, and the results screen is a picture of the generated demo library instead of the developer's own. Both caveats in the file are closed, so replace them with a short note on how the set was actually taken: - 01-empty: the grant went through the app's own "Grant access" button, so checkSelfPermission is genuinely satisfied. This one needed no tap at all: results and the selection live in ScannerViewModel and only the hash index is persisted, so force-stop + relaunch returns to the empty state with the grant still in place. - 02-scanning / 03-results: shot after tapping Scan over the demo library. The headline group is 43.1 MB reclaimable, which out-ranks the biggest group already on the device (39.8 MB), so the first group in frame is generated. - 04-options is new: the Options DropdownMenu with the three sensitivity presets (it is not a bottom sheet) and the trash-vs-permanent toggle. The tick marks and the "37 selected" bar are the screen's default state, not a staged tap -- a finished scan auto-selects all but best. MIUI still refuses pm grant and synthetic taps (INJECT_EVENTS), so Grant access and Scan remain the two taps a human has to make; the two screens still missing (the staged state and the system consent dialog) are captured by watching for UI text changes instead, rather than by timing a scripted tap. --- docs/STORE_LISTING.md | 69 +++++++++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 28 deletions(-) diff --git a/docs/STORE_LISTING.md b/docs/STORE_LISTING.md index 57bb75b..3bf1bec 100644 --- a/docs/STORE_LISTING.md +++ b/docs/STORE_LISTING.md @@ -26,7 +26,7 @@ python3 tools/make-demo-photos.py # synthetic photo library -> demo-photos/ (gi |---|---|---|---| | App icon | 512×512, 32-bit PNG with alpha, ≤ 1 MB | `store-assets/icon-512.png` — 512×512, RGBA, 6 KB | `tools/store-assets/icon.svg`, mirrored from `app/src/main/res/drawable/ic_launcher_background.xml` + `ic_launcher_foreground.xml` (paths and group transforms are identical, so the store icon *is* the launcher icon) | | Feature graphic | 1024×500, JPEG or 24-bit PNG without alpha | `store-assets/feature-graphic-1024x500.png` — 1024×500, RGB | `tools/store-assets/feature-graphic.svg` | -| Phone screenshots | JPEG or 24-bit PNG without alpha, shorter side ≥ 320 px, longer side ≤ 3840 px, **longer side ≤ 2× shorter side** | `store-assets/screenshots/0{1,2,3}-*.png` — 1080×2160, RGB | `tools/make-store-screenshots.sh`, from raw `adb exec-out screencap` captures in `store-assets/raw-screenshots/` | +| Phone screenshots | JPEG or 24-bit PNG without alpha, shorter side ≥ 320 px, longer side ≤ 3840 px, **longer side ≤ 2× shorter side** | `store-assets/screenshots/0{1,2,3,4}-*.png` — 1080×2160, RGB | `tools/make-store-screenshots.sh`, from raw `adb exec-out screencap` captures in `store-assets/raw-screenshots/` | Two details worth keeping in mind: @@ -44,27 +44,37 @@ Captured on the test device (1080×2400, Android 12 / MIUI), cropped to 1080×21 | File | Screen | |---|---| -| `01-empty.png` | Intro / empty state before the first scan | -| `02-scanning.png` | Scanning progress — *“Looking for visually similar photos…”* 5341 / 5363 | -| `03-results.png` | Results — 15 duplicate groups, 39.8 MB reclaimable, `BEST` badge, selection bar | +| `01-empty.png` | Intro / empty state before the first scan — access already granted, so there is no banner and *Start scan* is enabled | +| `02-scanning.png` | Scanning progress — *“Looking for visually similar photos…”* 5353 / 5385, live *Cancel* | +| `03-results.png` | Results over the demo library — 17 duplicate groups, 54 of 5385 photos, 83.5 MB reclaimable, the generated 14-copy group first, `BEST` badge, selection bar | +| `04-options.png` | Options menu (`DropdownMenu` off the top bar) — the three sensitivity presets with the ✓ on the active *Balanced (recommended)*, and the trash-vs-permanent toggle | -⚠️ **Both caveats below are outstanding for the three captures currently in -`store-assets/screenshots/`.** One re-shoot fixes both. +The tick marks and the *37 selected · 83.5 MB* bar in `03-results.png` are not a staged tap: a +finished scan auto-selects *all but best* across every group (`ScannerViewModel.autoSelection`), +so that **is** the screen's default state. -1. All three still show the *“Photo access needed”* banner. The test device (Xiaomi M2101K7AG - / MIUI) refuses `pm grant`, `install -g` and synthetic taps, so the runtime permission was - never actually granted there — the scan was driven with a debug-only - `MANAGE_EXTERNAL_STORAGE` app-op. That app-op gets the scan through MediaStore but does - **not** satisfy the app's own `checkSelfPermission`, which is why the banner — and the - disabled *Start scan* — are genuinely in frame. **Re-shoot on a clean install after tapping - “Grant access”**: that also closes the one remaining device-only verification gap. +The two earlier caveats are closed. The current captures were re-shot through the app's own +permission flow and over the generated demo library: - Enabling *USB debugging (Security settings)* in the MIUI developer options turns synthetic - taps and `pm grant` back on. That is what would let the capture run from a script instead of - by hand. -2. `03-results.png` currently shows real photos from the test library. They are the developer's - own, so nothing is licensed against us, but the library is not ours to publish. The next - capture must be taken over the generated demo library below. +1. **No *“Photo access needed”* banner.** The runtime grant went through the app's *Grant access* + button, so `checkSelfPermission` is genuinely satisfied. The test device (Xiaomi M2101K7AG / + MIUI) still refuses `pm grant`, `install -g` and synthetic taps (`SecurityException: + Injecting to another application requires INJECT_EVENTS`), so *Grant access* and *Scan* are + the two taps a human has to make. Enabling *USB debugging (Security settings)* in the MIUI + developer options is what would make the whole capture run scriptable. +2. **No real photos in frame.** `03-results.png` was shot over the demo library below, and its + headline group (43.1 MB reclaimable) outranks the biggest group already on the device + (39.8 MB), so the first thing on screen is a generated sunset instead of somebody's library. + +Only *Scan* needed a tap in the end. `01-empty.png` did not: scan results and the selection live +in `ScannerViewModel` (only the hash index is persisted), so force-stopping and relaunching the app +returns to the empty state with the grant still in place: + +```bash +adb shell am force-stop de.softwareapp_hb.fotodup.finder.debug +adb shell am start -n de.softwareapp_hb.fotodup.finder.debug/de.softwareapp_hb.fotodup.finder.MainActivity +adb exec-out screencap -p > store-assets/raw-screenshots/01-empty.png +``` ### Demo library: generated photos, so none of anyone's real ones are published @@ -94,9 +104,10 @@ Two non-obvious details, both load-bearing: - **Why the headline group has a target size.** Results are ranked by reclaimable bytes, so the first group on screen is the largest one. A demo group smaller than anything already on the - device would be pushed below the fold and a real photo would be back in frame. 45 MB clears - the test device's own 39.8 MB with room to spare; raise `--target-mb` if you capture on a - library whose biggest group is larger. + device would be pushed below the fold and a real photo would be back in frame. The default + `--target-mb 45` yields a headline group of **43.1 MB reclaimable**, which clears the test + device's own 39.8 MB with room to spare; raise `--target-mb` if you capture on a library whose + biggest group is larger. - **`scan_file` on the folder, not on the volume.** It indexes just that path (API 30+) instead of forcing a MediaStore-wide rescan on a 5,000-photo device. It does recurse into the folder, and re-running it after the folder is deleted drops those rows again — both verified on the @@ -121,13 +132,15 @@ adb shell rm -rf /sdcard/DCIM/foto-dup-demo adb shell content call --uri content://media --method scan_file --arg /sdcard/DCIM/foto-dup-demo ``` -Screens still worth capturing once a device grants access through the real flow (the capture run -needs two taps on the phone — *Grant access*, then *Scan* — which is the one thing the MIUI test -device will not accept from a script): +Two more screens are worth adding to the set. Each needs a tap, and MIUI only accepts taps from a +human, so they are captured by hand — a loop that takes a `uiautomator dump` and screencaps whenever +the UI **text** changes is enough, so the capture never depends on tap timing. That is how +`04-options.png` was taken, and it catches the menu, the staging and a system dialog in one pass: -- the **Options** sheet with the three sensitivity presets, -- the staged state (*“All duplicates are ready to go”*) after selecting duplicates, -- Android's **confirmation dialog** for moving photos to the trash. +- the staged state (*“All duplicates are ready to go”*) after *Remove all selected*. Nothing is + deleted at that point and no dialog appears yet — the rows simply leave the list. +- Android's **confirmation dialog** for the whole batch, which *Apply* launches. Dismissing it is + non-destructive: the staging is kept, and *Apply* can be tapped again. ## Store listing copy