Skip to content

android: build the shape a store takes, and target 36 - #1

Open
NoxToxCipher wants to merge 3 commits into
mainfrom
claude/crescent-readiness-a3rkds
Open

android: build the shape a store takes, and target 36#1
NoxToxCipher wants to merge 3 commits into
mainfrom
claude/crescent-readiness-a3rkds

Conversation

@NoxToxCipher

Copy link
Copy Markdown
Owner

Everything on the Accrescent path that does not need the domain first.

Target SDK 36, and the two things that follow

A store sets this floor, not us: Accrescent follows Google Play's target API policy, and from 31 August 2026 a new submission must target 36. Neither consequence is left to be found on a handset.

16 KB memory pages. An app targeting 35 or above has to load its native library on devices whose page size is 16 KB. The .so is linked with max-page-size=16384, the archive is aligned with zipalign -P 16 (which is why build-tools moves to 36.0.0), the manifest declares extractNativeLibs="false" so the library is mapped in place rather than unpacked, and the result is checked rather than assumed.

Edge to edge. Android 15 lays every app out under the status and navigation bars and ignores the theme colours for them, which would have put the header behind the clock. The activity reads the window insets and pads by them. No support library.

build-bundle.sh

A store takes an APK set from bundletool, not an APK. This links the resources in proto form, assembles the bundle module by hand, and has bundletool split and sign it. Still no Gradle: a bundle is a zip in a documented layout plus one tool invocation.

Before it claims success it verifies every APK in the set for 16 KB alignment and a valid signature, the set against the 128 MiB ceiling, and reports any that still carry a build timestamp. It refuses the debug key and checks bundletool's version against the published floor.

Both builds take the release key from the environment and let the tools ask for the passphrase, so it need not sit in a shell history. Version, SDK levels and the ABI list move into config.sh so the two builds cannot disagree about what they built.

zip-time.py was only half doing its job

Flattening the DOS timestamps leaves Info-ZIP's 0x5455 extra field (and NTFS 0x000A) holding the same clock to the second, and unzip -l shows those in preference. An archive could read as clean while still carrying the build time, and with it the builder's UTC offset. Both are zeroed now, and --check reports what a signed archive cannot have patched.

The listing icon

Generated from the launcher drawable on the adaptive icon's own background, so the icon in a store cannot drift from the icon on the phone. Full bleed, since a launcher and a store each apply their own shape.

What is verified, and what is not

zip-time.py was run against Info-ZIP, zip -X and jar archives: byte length preserved, integrity intact, idempotent, no clock left in either field. The icon was rendered and inspected. The build scripts pass bash -n but have not been run against a real SDK, so the first run on the build machine is the test. armeabi-v7a remains untested on 32-bit hardware.

Still blocked

The app ID. Accrescent verifies a domain matching it, so org.crake.metascrub requires crake.org, and the ID is permanent once published. The name settles before the first upload. android/README.md carries the full state, including what Google's September 2026 developer verification means for a pseudonymous release.

🤖 Generated with Claude Code

https://claude.ai/code/session_01VKf7mRc9hJhG2xhvLKGH8n


Generated by Claude Code

claude added 3 commits August 17, 2026 10:07
Everything on the Accrescent path that does not need the domain first.

Target SDK 36. A store sets this floor, not us: Accrescent follows Google
Play's target API policy, and from 31 August 2026 a new submission must
target 36. Two things follow, and neither is left to be discovered on a
handset.

The first is 16 KB memory pages. An app targeting 35 or above has to load
its native library on devices whose page size is 16 KB, so the .so is
linked with max-page-size=16384, the archive is aligned with `zipalign
-P 16` (which is why build-tools moves to 36.0.0), the manifest asks for
the library to be mapped in place rather than unpacked, and the result is
checked rather than assumed.

The second is edge to edge. Android 15 lays every app out under the
status and navigation bars and ignores the theme colours for them, which
would have put the header behind the clock. The activity now reads the
window insets and pads by them, with no support library.

build-bundle.sh is new: a store takes an APK set from bundletool, not an
APK, so this links the resources in proto form, assembles the bundle
module by hand and has bundletool split and sign it. Still no Gradle. It
refuses the debug key, checks bundletool's version against the published
floor, and before claiming success verifies every APK in the set for
16 KB alignment and a valid signature, the set against the 128 MiB
ceiling, and reports any that still carry a build timestamp.

Both builds take the release key from the environment and let the tools
ask for the passphrase, so it need not sit in a shell history. Version,
SDK levels and the ABI list move into config.sh so the two builds cannot
disagree about what they built.

zip-time.py was only half doing its job. Flattening the DOS timestamps
leaves Info-ZIP's 0x5455 extra field (and NTFS 0x000A) holding the same
clock to the second, and `unzip -l` shows those in preference, so an
archive could read as clean while still carrying the build time and the
builder's UTC offset. Both are zeroed now, and --check reports what a
signed archive cannot have patched.

Still blocked on the app ID: the store verifies a domain matching it, and
org.crake.metascrub means crake.org. That is permanent once published, so
the name settles before the first upload. README carries the full state.
A listing needs a 512x512 PNG, the one piece of app art that cannot stay a
vector. Drawing it separately would leave two copies of the mark that
nobody notices have drifted until the store icon stops matching the icon
on the phone, so it is rendered from the drawable the launcher already
uses, on the adaptive icon's own background colour.

Full bleed, not masked: a launcher applies its own shape and so does a
store, and an icon that arrives pre-rounded gets rounded twice.
Kept in the repository rather than typed into a web form once, so it can
be read like anything else and so the next store gets the same words.

The listing says what the app refuses to claim, not only what it does:
the three results and what each one means, video and audio being named
but not cleaned, and the three things it cannot do at all. A store
listing is the first place a tool like this can overstate itself, and it
is the one place nobody would check.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants