Imported from aiya000/Android-OnlyScreenshot-StatusBarCenter-LongTap (
.claude/skills/release-build/SKILL.md). Install upstream withnpx skills add aiya000/Android-OnlyScreenshot-StatusBarCenter-LongTap --skill release-build. Copyright stays with the author.
release-build
Build the release APK. Gradle signs it itself, so there is no separate signing step.
Environment
-
gradle needs a JDK. There is no
javaonPATH; this machine keeps JDK 17 in mise:mise exec java@17.0.2 -- ./gradlew ... -
The SDK location comes from
local.properties(sdk.dir=$HOME/Android/Sdk), which is not tracked by git. Recreate it if it is missing -
Outside the sandbox
$TMPDIRis empty. Always give log files an absolute path inside the session scratchpad directory -
The Bash sandbox is disabled by default on this machine. If it is ever turned back on, gradle fails with
gradle-8.9-bin.zip.lck (Read-only file system)and needsdangerouslyDisableSandbox: true
Signing
The signing key is personal and deliberately lives outside this repository, so a checkout carries no
secret. app/build.gradle.kts reads four properties from ~/.gradle/gradle.properties:
AIYA000_STORE_FILE=<absolute path to the keystore>
AIYA000_STORE_PASSWORD=<password>
AIYA000_KEY_ALIAS=aiya000
AIYA000_KEY_PASSWORD=<the same password>
~/.gradle/gradle.propertiesis read by every gradle build this user runs, and nothing needs to be configured per project. The same reach is why no password belongs on a command line or in any repositoryAIYA000_STORE_FILEhas to be written out in full; gradle'sfile()does not expand~- The keystore itself is kept in a private repository, and the passwords are deliberately not stored
next to it -- they live only in the user's password manager and in
~/.gradle/gradle.properties. Ask the user where the keystore is rather than guessing - Where those properties are absent the build still succeeds and simply produces an unsigned APK. A release that is meant to be published must never be built that way
- Never put a password on a command line or into this repository.
keytoolhas no:envor:fileoption, so creating or changing a key is done by the user in their own terminal, not through Claude Code
Behavior
-
Run the build, logging to the scratchpad:
mise exec java@17.0.2 -- ./gradlew :app:assembleRelease -q > <scratchpad>/release-build.log 2>&1; echo "EXIT=$?" >> <scratchpad>/release-build.log -
Check the log for
^e:,error:,FAILEDand theEXIT=line -
Verify the signature -- this needs no password:
export JAVA_HOME="$(mise where java@17.0.2)" export PATH="$JAVA_HOME/bin:$PATH" "$HOME/Android/Sdk/build-tools/36.0.0/apksigner" verify -v --print-certs app/build/outputs/apk/release/app-release.apkExpected, and a mismatch means the wrong key was used:
- v3
true, v2false, v1false.minSdkis 30 and v3 covers API 28 and up, so gradle adds neither of the older schemes. This differs from TempoPad, whereminSdk26 still needs v2 Signer #1 certificate DN: CN=aiya000, O=aiya000, C=JPSigner #1 certificate SHA-256 digest: 9c5ed06732d180ca3aca8bcf611ad25c983b6bf89ddd56cc7e9fae7d57844991Signer #1 key size (bits): 4096
- v3
-
Report the APK path:
app/build/outputs/apk/release/app-release.apk
Notes
- Gradle zipaligns the APK as part of packaging. The old manual
zipalign+apksigner signsteps, and theapp-release-unsigned.apk/app-release-aligned.apk/app-release-signed.apkfiles they produced, are gone. Onlyapp-release.apkis built now, and it is the only file to publish - Before a release that is published, bump
versionCode(and usuallyversionName) inapp/build.gradle.kts. Android refuses to install an update whoseversionCodedid not increase isMinifyEnabledisfalse, so there is no R8 step andproguard-rules.prois effectively empty. Turn minification on only together with keep rules for the Compose runtime- Do not install automatically; that is the
release-installskill