M10: store assets - Plain Files naming, generated icon/feature graphic, listing copy
This commit is contained in:
+1
-1
@@ -19,7 +19,7 @@ Legend: ✅ done · 🚧 in progress · ⏳ not started · 💡 candidate (propo
|
||||
| M7 | On-device validation & hardening | ✅ | Run on a real **Xiaomi M2101K7AG** (Android 12 / MIUI V140) — see [EDGE_CASE_TESTING](EDGE_CASE_TESTING.md). Verified on hardware: the first-run permission prompt, granting "All files access" while the app is alive (picked up on resume), browsing real storage, the text editor's read **and** write path (independently checked with `adb shell cat`), the storage-usage screen, landscape layout, and **graceful degradation when access is revoked mid-use**. Found and fixed two real defects: misleading first-run copy ("Full access was declined" on a device where nothing had been declined), and a usage screen that stayed blank for **~45–60 s** on a 55 GB volume — now one listing per directory instead of a `stat` per node, with rows streamed out as they are measured. **142 JVM tests** |
|
||||
| M8 | Localisation groundwork | ✅ | Every user-visible string is in `res/values/strings.xml` with real `<plurals>`, and `text/TextRes.kt` maps **both** `OperationKind` and `FileKind` onto resources so the screen, the notification and the details sheet cannot drift. The audit found a genuine miss: the details sheet rendered `FileKind.name`, i.e. untranslatable English — now a resource. `isPseudoLocalesEnabled = true` on the debug build makes "did every string come from resources?" mechanically checkable; verified `en-rXA` is present in the debug APK and the flag is debug-only. Byte units and the timestamp pattern are deliberately unlocalised, and the README says why. **142 JVM tests** |
|
||||
| M9 | Monetisation | ✅ | **Decided: one-time paid — €4.49 base with a 14-day launch price of €2.29**, both set in the Play Console (*Products › App pricing*), so there is **no Billing client, no `com.android.vending.BILLING` permission and no purchase code**. Rationale, market anchors and Console steps: [MONETISATION](MONETISATION.md). Verified against the release APK: zero billing and zero `INTERNET` references. **The price must be set before the first upload** — Play allows paid → free but never free → paid |
|
||||
| M10 | Store assets | ⏳ | icon/feature-graphic generators, per-form-factor screenshots, [STORE_LISTING](STORE_LISTING.md); display name confirmed |
|
||||
| M10 | Store assets | 🚧 | Name decided: **Plain Files** (one string; `applicationId` already locked). `tools/make-store-assets.sh` renders the 512×512 **RGBA** icon and the 1024×500 **RGB** feature graphic from the app's own vectors, so the store icon *is* the launcher icon; `tools/make-store-screenshots.sh` normalises `adb` captures to Play's 2:1 cap per form factor (phone crop default 93/130 px, tablets 0). [STORE_LISTING](STORE_LISTING.md) carries length-checked copy (name 11/30, short 67/80, full 1881/4000), the permissions paragraph the `MANAGE_EXTERNAL_STORAGE` declaration requires, and the graphics table. The feature graphic's copy was verified to survive Play's centre-square crop by cropping the rendered PNG. **Outstanding: screenshots** — the tooling and directories are in place but no captures exist yet |
|
||||
|
||||
## Key decisions
|
||||
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
# Play Store listing (M10)
|
||||
|
||||
Ready-to-paste copy for the *Main store listing* page, plus the graphics that go with it.
|
||||
Every graphic is generated from the app's own vectors, so a rebrand is a re-run rather than
|
||||
a redraw.
|
||||
|
||||
See [PLAY_RELEASE_CHECKLIST](PLAY_RELEASE_CHECKLIST.md) § 6 for where this fits in the
|
||||
release.
|
||||
|
||||
## App name
|
||||
|
||||
**Plain Files**
|
||||
|
||||
Deliberately not "File Manager": dozens of apps are literally called that, and a distinctive
|
||||
name is what makes a listing findable and rememberable. It is one string
|
||||
(`app_name` in `values/strings.xml`); the `applicationId` is separate and already locked.
|
||||
|
||||
## Graphics
|
||||
|
||||
```bash
|
||||
./tools/make-store-assets.sh # icon + feature graphic -> store-assets/
|
||||
./tools/make-store-screenshots.sh # phone -> screenshots/phone/
|
||||
FORM_FACTOR=tablet-7in ./tools/make-store-screenshots.sh
|
||||
FORM_FACTOR=tablet-10in ./tools/make-store-screenshots.sh
|
||||
```
|
||||
|
||||
| Asset | Play's spec | Result | Source |
|
||||
|---|---|---|---|
|
||||
| App icon | 512×512, 32-bit PNG with alpha, ≤ 1 MB | `store-assets/icon-512.png` — 512×512, **RGBA**, ~5 KB | `tools/store-assets/icon.svg`, mirroring `ic_launcher_background.xml` + `ic_launcher_foreground.xml`. Background, paths and opacities are identical, so **the store icon is the launcher icon** rather than a lookalike that drifts. |
|
||||
| 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 | no alpha, shorter side ≥ 320, longer side ≤ 3840, **longer side ≤ 2× shorter** | `store-assets/screenshots/phone/` (1080×2160) | `tools/make-store-screenshots.sh`, from `adb` captures in `store-assets/raw-screenshots/phone/` |
|
||||
|
||||
Two details worth keeping:
|
||||
|
||||
- **The icon is full bleed.** The background rect covers all 108 dp, so every pixel is
|
||||
opaque and Play's mask can crop to any shape without showing a gap.
|
||||
- **A phone at its native 1080×2400 is 2.22:1 and is therefore rejected.** The normaliser
|
||||
crops the status and navigation bars and then clamps to 1080×2160 — system chrome only,
|
||||
never app content. Tablets are already inside the 2:1 cap, so their crop defaults to 0.
|
||||
|
||||
### The feature graphic's safe area
|
||||
|
||||
Play crops the feature graphic to a **centre square** for some placements, so all of the copy
|
||||
sits inside **x 262…762** and the motif — which does not survive — is decoration. Verified by
|
||||
actually cropping the rendered PNG rather than by trusting the arithmetic:
|
||||
|
||||
```bash
|
||||
magick store-assets/feature-graphic-1024x500.png -gravity Center -crop 500x500+0+0 +repage /tmp/square.png
|
||||
```
|
||||
|
||||
## Short description (80 characters max)
|
||||
|
||||
```
|
||||
Browse, organise and manage your files. Ad-free, offline, pay once.
|
||||
```
|
||||
|
||||
## Full description (4000 characters max)
|
||||
|
||||
```
|
||||
Plain Files is a straightforward file manager for Android — no ads, no account, no
|
||||
subscription, and no network access at all. You buy it once and it is yours.
|
||||
|
||||
BROWSE ANYTHING
|
||||
• Internal storage, SD cards and USB drives, side by side
|
||||
• List or grid view, with sorting by name, size, date or type
|
||||
• Breadcrumb navigation and an in-folder search
|
||||
• Hidden files on request
|
||||
|
||||
MANAGE YOUR FILES
|
||||
• Copy, move, rename and delete, one item or many at once
|
||||
• Create folders and edit text files in the built-in editor
|
||||
• See the details of anything: size, type, location, modified date
|
||||
• Open a file in any app, or share it
|
||||
|
||||
FIND OUT WHERE THE SPACE WENT
|
||||
• A storage-usage view that measures every folder and ranks it largest first
|
||||
• Spot the folder that is actually eating your storage, then act on it
|
||||
|
||||
ARCHIVES
|
||||
• Create ZIP archives, and extract ZIP, TAR, TAR.GZ, GZ, BZ2 and XZ
|
||||
• RAR and 7z are not supported — they need native code this app does not ship, and it says
|
||||
so rather than failing with a strange error
|
||||
|
||||
PRIVATE BY DEFAULT
|
||||
• No INTERNET permission. The app cannot send your data anywhere, because it has no way to.
|
||||
• No analytics, no advertising SDKs, no third-party trackers
|
||||
• No account, no sign-in, nothing to remember
|
||||
• Your files stay on your device, always
|
||||
|
||||
SOLD ONCE
|
||||
• One purchase, every feature, no ads and nothing to buy inside the app
|
||||
• No subscription
|
||||
|
||||
PERMISSIONS, EXPLAINED
|
||||
Plain Files asks for "All files access" because that is what browsing and managing files
|
||||
anywhere on a device requires — the app's core purpose. Google Play only grants this
|
||||
permission to app types that genuinely need it, and a file manager is one of them. If you
|
||||
would rather not grant it, the app still works: it can browse a folder you pick yourself
|
||||
through Android's own folder picker, and it remembers that choice.
|
||||
|
||||
Read the privacy policy: https://example.invalid/plain-files/privacy
|
||||
```
|
||||
|
||||
> Replace the privacy-policy URL with the real public URL before publishing — a repository
|
||||
> file is not acceptable to Play. [PRIVACY.md](../PRIVACY.md) is the source text.
|
||||
|
||||
### Why the permission sentence matters
|
||||
|
||||
Play requires that an app's **core functionality be prominently documented and promoted in
|
||||
the app's description** when it declares `MANAGE_EXTERNAL_STORAGE`. The "PERMISSIONS,
|
||||
EXPLAINED" section is not marketing copy — it is the evidence the Permissions Declaration
|
||||
Form asks for.
|
||||
|
||||
## Still to do before publishing
|
||||
|
||||
- **Screenshots.** `tools/make-store-screenshots.sh` is written and the raw-screenshot
|
||||
directories are in place, but no captures have been taken yet, so
|
||||
`store-assets/screenshots/` is empty. Capture against a **synthetic** library — never a
|
||||
real one, since published screenshots would expose real file names.
|
||||
- **Tablet screenshots.** Play has a 7-inch and a 10-inch slot, each wanting 4+.
|
||||
Reference in New Issue
Block a user