Commit Graph

9 Commits

Author SHA1 Message Date
SoftwareApp f45e3b79ab docs: cover the tablet screenshot slots and settle app pricing
Two Console-facing subjects, both decided here instead of in the Console.

Tablet screenshots (7-inch and 10-inch)
--------------------------------------
Play keeps a separate screenshot slot per form factor and asks for at least four
screenshots on tablets, so the four phone captures did not cover them. Both sets are now
captured on AOSP Android 12 AVDs, over the same generated 22-photo demo library, and
normalised with FORM_FACTOR=tablet-7in|tablet-10in:

- 7-inch - Nexus 7 2013: 1200x1920 portrait, sw600dp, 320 dpi, four files
- 10-inch - Medium Tablet: 1600x2560 portrait, sw800dp, 320 dpi, four files

This machine has no /dev/kvm - the node cannot even be created, because mknod is refused
for the container as root - so the emulator ran in pure software emulation (-accel off
-no-window -gpu swiftshader_indirect): about 3 minutes to boot, 1-12 s per screenshot.
hide_error_dialogs was switched on and the animation scales off, because under TCG
SystemUI raises an ANR dialog that would otherwise sit in the frame; the 10-inch profile
boots landscape and its portrait rotation is 3, not 0. The scanning frame comes from a
screencap burst started before the tap, since 22 photos scan in seconds, and the tap
coordinates come from uiautomator dumps rather than guesswork.

The results screens are not staged: a finished scan auto-selects all but best, so "14
selected, 43.7 MB" is the default state. 2 duplicate groups, 16 of 22 photos, 43.7 MB
reclaimable, scanned in 39.7 s (7-inch) and 53.1 s (10-inch). Nothing except the demo
library was ever pushed to either AVD and it is deleted again afterwards, so no real
photo can appear in the tablet sets. Screenshots stay out of git, as before.

App pricing: a one-time paid app
--------------------------------
The one irreversible decision in this release. Play's rule: an app can go paid -> free,
but "once your app has been offered for free, the app can't be changed to paid" - a new
package name would be needed - so this had to be settled before the first upload, which
has not happened yet (versionCode 2).

Chosen over free with a Pro unlock because it is the only model that costs the app
nothing: no Billing dependency, no com.android.vending.BILLING permission, no Data
Safety answers, and the "no internet permission at all" claim survives untouched.
Checked rather than assumed: unpacking com.android.billingclient:billing:9.1.0 shows its
manifest declares only com.android.vending.BILLING and the billing service queries, so
in-app purchase would not have added INTERNET either. Billing 8+ is the current
requirement (latest 9.1.0) if that is ever revisited.

Price: base EUR 2.99 with a 14-day 50% launch sale at EUR 1.49. A EUR 1 base price was
considered and rejected: a sale can always be added, but a low anchor cannot be undone,
and a paid app's first transaction is its only transaction. Play's fee for a paid app's
initial purchase is 10% + 5% billing fee (~15%) for the first $1M/year of new-install
transactions in the EEA, so EUR 2.99 nets ~EUR 2.54 against ~EUR 0.85 at EUR 1. The sale
rules shape the launch: 1-14 days live, 30 days between one sale ending and the next
starting, and the app must be published before a sale can be created. The strikethrough
does appear in Germany, which is not one of the 12 EU states and the UK that hide it.

The listing copy had to stop saying "free": the short description is now "Find and remove
duplicate photos. Ad-free, works offline, no uploads." (69/80 chars) and the full
description gains one factual pay-once line plus a "sold through Google Play as a
one-time purchase" bullet (2,426/4,000). The price stays out of the title, icon and
developer name, because Play's metadata policy forbids price and promotional wording
there. PRIVACY.md gains a Purchases section - Google Play processes the payment, the app
has no payment code and no network access at all - and its date moves to 2026-10-14, so
the published copy needs re-pushing to Gitea.

No code changed, so the signed 1.0.1 .aab is untouched (sha256 f8e6a29a...). What is
left is Console work: a payments profile, the price and the launch sale on Products >
App pricing, and a promo-code copy to test the paid listing end to end.
2026-10-14 09:48:57 +02:00
SoftwareApp 49025a823a docs: correct the Play tags to the ones that exist in Play taxonomy 2026-10-14 07:46:38 +02:00
SoftwareApp c9382364fc docs: pin down the Play tag set and the ones to avoid 2026-10-14 07:41:47 +02:00
SoftwareApp 89ddf3bb1d docs: point the privacy-policy step at the published Gitea remote 2026-10-14 07:24:49 +02:00
SoftwareApp f17b40c608 docs: tick the two checklist items that were already satisfied
The permission-set audit and the large-library scan test were both done, just not recorded:
aapt2 badging on the release APK matches the documentation table exactly (no INTERNET), and
the scans ran over 5,363 and 5,385 photos. Spell out what actually remains in the ROADMAP
paperwork row too - the keystore and versionCode are in place, so the open items are the
first upload + Play App Signing enrolment, the hosted privacy policy (still no git remote),
Data safety, the photo/video and foreground-service declarations, the App content questions
and the listing itself.
2026-10-14 00:13:06 +02:00
SoftwareApp 5ec2589444 docs: answer Play's native-debug-symbols warning
Uploading the bundle shows "This App Bundle contains native code, and you've not uploaded
debug symbols". Record the answer next to the upload step so it is not re-investigated on
every release:

- the bundle's only native code is libandroidx.graphics.path.so (4 ABIs, ~37 KB), which
  arrives transitively through androidx.compose.ui:ui-graphics ->
  androidx.graphics:graphics-path:1.0.1; this project builds no native code at all,
- ndk.debugSymbolLevel = "FULL" was tried and emits nothing for such a project (no
  native-debug-symbols output, nothing added to the bundle), and
- the published AAR ships stripped libs only (symtab=0, no .debug_* sections, no symbol
  entries at all), so there is no symbol file in existence to upload.

The warning is advisory and does not block review or rollout. Kotlin/Java stack traces are
already deobfuscated from the R8 mapping that rides inside the bundle, so the only thing
lost is symbolication of frames inside that Compose helper library.
2026-10-14 00:09:55 +02:00
SoftwareApp 55101886cb docs: finish the Console pre-flight and retire the screenshot blocker
Everything the Play forms ask for that can be settled from the working copy, settled:

- PRIVACY.md now carries the real contact address (softwareapp.hb@gmail.com), so the
  policy publishes as-is. Hosting is the one step left that cannot be done from here,
  because the repo has no git remote: step 5 of the checklist spells out the push +
  GitHub Pages route and the URL it yields.
- Checklist: the screenshot item is done (four captures, 1080x2160, over the demo
  library, no permission banner), the keystore and versionCode are recorded as already
  in place - including the upload key's SHA-256 for the Play App Signing enrolment - and
  the App access / Ads / remaining App content declarations are written down. The
  first-upload release-notes question is answered too: versionCode is already 2, so
  1.0.1 takes the *initial release* block, not the 1.0.1 one.
- The build facts were verified against the artefacts rather than the source: the
  release APK reports versionCode=2, versionName=1.0.1, targetSdk=36 and exactly the
  documented permission set, with no INTERNET in what actually ships.
- ROADMAP: the re-shoot row is struck out with the numbers that closed it, M10 no longer
  claims the captures predate the demo library, and the demo library's removal is
  recorded (MediaStore 5,386 -> 5,364; pruneTo drops the stale index rows next scan).

The staged state and the system confirmation dialog are documented as deliberately not
captured: staging clears the demo group, which would put real photos back in frame.
2026-10-13 23:59:15 +02:00
SoftwareApp 3581ffc6bb Add a generated demo photo library for store screenshots
The results screenshot is a screenshot *of a photo library*, so the committed
capture showed the developer's own photos. tools/make-demo-photos.py draws the
library instead: 22 procedural scenes (sunset, mountains, beach, conifers in
haze, dunes, city skyline, night sky, bokeh) with grain and a vignette, so there
are no people, no third-party content and nothing to license.

The duplicate structure is deliberate, because a folder of unrelated pictures
demonstrates nothing:

- headline group: one scene re-saved at falling quality and size until its
  reclaimable size reaches --target-mb (45 MB). Results are ranked by
  reclaimable bytes, so this group has to out-rank whatever is already on the
  device or a real photo is the first thing back in frame.
- exact pair: two byte-identical files, for the SHA-256 path.
- singles: the other scenes, once each, so the library looks lived-in.

Verified with the app's own engine on the desktop before pushing anything:
22 images -> 2 groups (PERCEPTUAL 14 copies, EXACT 2 copies) with the six
singles left alone. Regeneration is byte-identical, the output path resolves
from __file__ so it runs from any cwd, and nothing is written outside the repo.

demo-photos/ is git-ignored, like fixtures/ and store-assets/raw-screenshots/.
STORE_LISTING.md documents the library, why the headline group has a target
size, the MediaProvider scan_file recipe and the cleanup step; ROADMAP, README
and the release checklist point at it.
2026-10-13 23:34:12 +02:00
Hadrian Burkhardt 4706e2669c Initial commit: Foto Dup Finder 1.0.1
An Android duplicate-photo finder. Pure-Kotlin core (SHA-256 + dHash hashing, exact and
perceptual union-find grouping, three sensitivity presets) with MediaStore access, a
persistent SQLite hash index and a tiered ScanEngine behind a Jetpack Compose UI.
No INTERNET permission, no ads, no analytics, no account.

Ships versionCode 2 / versionName 1.0.1, carrying the scan-stall hardening (BoundedCall
breaker) and verified against a 5,363-photo device library. 80 JVM unit tests, lint clean.

Release paperwork is in docs/ (Play checklist, store listing, edge-case testing), the
upload-ready Play graphics and screenshots in store-assets/, and the generators for those
assets in tools/.
2026-10-13 23:13:39 +02:00