Write the release notes, the permission answers, and the video
verify / gate (push) Has been cancelled
verify / release (push) Has been cancelled

Play asks three separate things before a file manager may keep All files
access: the What's new copy, a justification for why SAF and MediaStore cannot
carry it, and a short video of the permission in use. Writing them exposed two
stale claims and one privacy problem, so those are fixed here rather than
repeated.

- docs/RELEASE_NOTES.md holds the Console field at 450/500 characters, measured,
  and the longer announcement. The first release's copy leads with the claim no
  competitor makes (no ads, no INTERNET permission) and then proves the app is
  still a file manager.

- docs/PLAY_RELEASE_CHECKLIST.md section 5 holds the declaration answer at
  490/500 characters. It argues from what the Storage Access Framework and
  MediaStore cannot do - one picked tree, no volume enumeration or whole-device
  hierarchy, no arbitrary non-media files - and never from performance, which
  Google's wording rejects. Both APIs are named as already used where they can
  be, so the argument is not that they are useless.

- docs/PERMISSION_VIDEO.md and store-assets/video hold a 19.7 s captioned video
  recorded on the release build. The home-screen segment is cut because its
  library counts are the owner's real totals; the published copy resumes on the
  internal-storage listing. Also recorded: the emulator captures one frame in
  three seconds, and only appops set --uid ... deny brings the prompt back after
  Settings has granted the app-op.

- README and ROADMAP caught up with the build: the status stopped at M15, and
  the trash limitation still said there was no Empty trash and that expiry
  waited for the next delete, both changed in M19.

Verified: ./tools/verify.sh green, the code map current, the Play field measured
at 450 characters and the form answer at 490, and the video decoded as H.264
1080x2400, 19.666 s, no audio, with frames checked at the cut and the end state.
This commit is contained in:
2026-10-18 13:59:50 +02:00
parent f4ca5f22ae
commit 9b8a32fbd6
10 changed files with 400 additions and 26 deletions
+146
View File
@@ -0,0 +1,146 @@
# Release notes
The copy a buyer reads *before* installing, as opposed to [CHANGELOG](../CHANGELOG.md), which is the
reasoning for whoever maintains the app. Two lengths live here:
- **Play Console → What's new** — plain text, **500 characters per language**, no Markdown and no
bullets (Play renders neither), measured rather than estimated.
- **The longer announcement** — for a website, a forum post or a GitHub release, where the limit is
the reader's patience rather than a Console field.
The source of truth for *what* changed is the changelog, and the source of truth for *what the app
claims* is the [README](../README.md) and [STORE_LISTING](STORE_LISTING.md). This file only chooses
which of those facts a new user should hear first.
## Writing the next one
1. **Version.** `versionName` and `versionCode` are in `app/build.gradle.kts`; the latter must be
higher than every previous upload. The first release is `1.0.0` / `1`.
2. **Changelog first.** Move the entries out of `## [Unreleased]` into a
`## [1.0.0] - YYYY-MM-DD` heading, so this file and the changelog cannot describe different
builds.
3. **Then the Play field.** Say what a user can now do that they could not before — never what the
code did. A first release describes the app instead of a diff.
4. **Measure it.** Play counts characters, line breaks included:
```bash
python3 -c "print(len(open('/tmp/whats-new.txt').read().strip()))"
```
5. **Quote nothing that a device has not shown.** A limitation belongs in the announcement only if
it is already in the README's *Known limitations*; if it is not, the README is what needs fixing.
---
## 1.0.0 — first release
### Play Console → What's new (500 characters max)
```
Plain Files is here: a file manager with no ads, no account and no internet permission, so nothing leaves your device.
Browse internal storage, SD cards and USB drives. Copy, move, rename and delete files; undo a delete, rename or move; search everywhere; find duplicates; unpack ZIP, TAR, GZ, BZ2, XZ and 7z; star the folders you use; and read images, video, PDFs and text inside the app.
One purchase, every feature. No tracking, no subscription.
```
**Measured: 450 characters** (including the two blank lines between paragraphs). The remaining
headroom is deliberate: it leaves room for a sentence about a fix without rewriting the whole field.
Why this shape: the first two sentences are the claim no competitor in the survey makes — no ads and
**no `INTERNET` permission** — and the middle one is the proof that it is still a file manager. The
verbs are the ones people use ("copy, move, rename, delete"), not the app's internal names. Nothing
here is a superlative, an emoji, or the word *free*: the app is paid, and a headline implying
otherwise is both misleading and against Play's editorial policy.
### The longer announcement
> Plain Files 1.0.0 is available for Android 8.0 and later. One purchase, no subscription, no ads,
> and no way for the app to send anything off the device — because it does not hold the network
> permission at all.
#### What it does
**Browsing.** Internal storage, SD cards and USB drives side by side. List or grid, sorted by
name — `file2` before `file10` — size, date or type; hidden files on request; breadcrumbs; and a
search that either stays in the folder you are in or looks everywhere through an on-device index
which says how current its answer is.
**Moving files around.** Copy, move, rename and delete one item or many. **Copy to…** and **Move
to…** open a folder picker — volumes first, then one level at a time — and start the transfer into
that folder without taking you out of the one you are standing in. A finished copy says
*Copied to folder* and offers **Show**. A name that already exists asks what Paste asks instead of
overwriting, and a batch that cannot succeed is refused as a whole rather than performed until it
hits the problem. The rows an operation produced carry a dot until you next open that folder, so
"what did that 4 GB copy do?" has an answer even when the destination was elsewhere.
**Undo, and a trash that explains itself.** A delete is a move into a hidden `.plainfiles-trash`
folder on the same volume, kept for **24 hours**; the Trash screen states that window, offers
**Empty trash** behind one question, and sweeps expired batches when you open it. Rename and move
offer undo as well.
**Renaming a batch.** Select several files and Rename opens a pattern rather than the single-file
dialog: one name, the number to start at, and a live preview of the names it will produce. The
numbering **continues the folder's own series** — `Holiday (1)` and `Holiday (2)` already there make
the next batch start at 3 — because a batch rename that always starts at 1 is useless the second
time it is used. A name in the way blocks the batch and is named as it is typed.
**Finding things.** The duplicate finder compares size, then the head of every candidate, then the
survivors in full — never a name or a date. The storage-usage view measures every folder and ranks
it largest first, so the folder eating the card is the one at the top.
**Looking at files.** Image, text, PDF, media and archive viewers, and an APK's own details read
without installing it. Thumbnails show the picture, and a **video shows a frame of itself** rather
than a film icon. An archive can be read without extracting it first, with entry names checked
against zip-slip.
**Archives.** Create ZIP; extract ZIP, TAR, TAR.GZ, TAR.BZ2, TAR.XZ, GZ, BZ2, XZ and 7z. When
compressing, you choose the name and whether to compress at all: for copying a collection to a
computer, storing the files as they are takes one pass and is still an ordinary archive.
**Working with other apps.** Plain Files can receive a share from anywhere and appear in another
app's file chooser. Neither costs a permission.
**Tablets and large windows.** At expanded width the screen splits into two panes: the folder list
on the left, and the contents — or a preview and the details — of the folder or file you pick on the
right.
**Shortcuts.** Long-press the app icon for **Images**, **Recent** and **Trash**.
#### What it deliberately does not do
- **No cloud storage, network shares, FTP/SFTP/WebDAV or web server.** Every one of those needs
`INTERNET`, which is the single permission this app refuses to hold. That is the product, not a
gap in the schedule.
- **RAR is not supported**, because it needs native code this app does not ship — and it says so
rather than failing with a strange error. 7z can be read but not created.
- **Extraction does not restore timestamps or permissions**, and archive passwords are not
supported.
- **Cancelling happens between entries**, so one very large file finishes before a stop is honoured.
- **English is the only language so far.** Every string is in `strings.xml`, so a translation is a
file rather than a refactor.
- **Android TV is specified but not shipped.** Its acceptance needs a TV device pass this machine
cannot provide, and a half-tested TV build reviews worse than none.
- **A library is not restored across process death.** Images or Recent returns to the root screen
after Android kills the process, because a library has no path to persist.
#### Privacy, in one paragraph
The app declares no `INTERNET` permission, contains no advertising or analytics SDK, and has no
account or sign-in. It keeps three things on the device — an index of files for search, an index of
staged deletes for the trash, and the list of starred folders — and none of them leaves it. The
permission set and why "All files access" is the one sensitive declaration are in the
[store listing](STORE_LISTING.md); the policy text is [PRIVACY.md](../PRIVACY.md).
#### Price
**€4.49**, with a **€2.29 launch price for the first 14 days**. One purchase, every feature; no
subscription and nothing to buy inside the app. There is no Billing client in the build — the price
lives on the listing — which is part of how "nothing leaves the device" stays true of the shipped
artefact rather than only of the source.
#### What comes next
Android TV is specified and waits for a device; the post-1.0 queue and the deliberate deferrals are
in [ROADMAP](ROADMAP.md). What will not change is the permission set: features arrive without a new
permission, or they do not arrive.