Sign and publish to Google Play¶
Android installs only signed apps. Debug builds are signed automatically; a release build needs your own key. On this page, you create a key, produce a signed APK (Android Package) or AAB (Android App Bundle), and upload the AAB to Google Play.
Before you begin¶
- Configure your Android app and confirm that
kivyforge doctor -p androidreports no failures. - Have a JDK, which provides
keytool.
Note
Debug builds need none of this. kivyforge build --debug and
kivyforge run use the standard Android debug keystore.
Choose a signing model¶
- Self-managed signing
- You hold the only key. If you lose it, you can never publish an update to the same app.
- Play App Signing
- You sign the AAB with an upload key. Google holds the app signing key and signs what it delivers to devices. If you lose the upload key, Google can reset it.
kivyforge does the same thing in both models: it signs the release artifact with the key you give it.
Create a keystore and package¶
-
Create a keystore:
keytool -genkeypair -v -keystore release.keystore -alias upload -keyalg RSA -keysize 4096 -validity 10000 -storetype PKCS12-validity 10000(about 27 years) keeps the key valid for the life of the app. Keep the keystore out of your public repository. -
Set the passwords as environment variables. Never put them in
pyproject.toml.$env:KIVYFORGE_KEYSTORE_PASSWORD = "STORE_PASSWORD" $env:KIVYFORGE_KEY_PASSWORD = "KEY_PASSWORD"export KIVYFORGE_KEYSTORE_PASSWORD=STORE_PASSWORD export KIVYFORGE_KEY_PASSWORD=KEY_PASSWORDReplace
STORE_PASSWORDandKEY_PASSWORDwith the passwords you chose inkeytool. IfKIVYFORGE_KEY_PASSWORDis unset, the keystore password is used for the key. To read the passwords from other variables, setstore_password_envandkey_password_envin the signing table. -
Declare the signing table:
[tool.kivy.android.signing] keystore = "release.keystore" key_alias = "upload"keystoreis relative to your project or absolute. Instead of the table, you can pass--keystoreand--key-aliastokivyforge package, which suits CI jobs that write the keystore from a secret. If you editpyproject.toml, runkivyforge lock -p androidagain. -
Check the signing setup:
kivyforge doctor -p androidWhen the signing table is declared,
doctorconfirms that the keystore exists, the password variable is set, and the alias is in the keystore. -
Package a signed artifact:
kivyforge package -p android -f aabUse
-f aabfor Google Play and-f apk(the default) to install the app directly. Add--abi arm64_v8aor--abi x86_64to package a single ABI.
Before it signs anything, package checks the signing setup, runs a curated set
of Android Lint checks, and applies a manifest policy to the merged release
manifest. A finding in either blocks the release.
Verify¶
package prints the path of the artifact it produced:
- APK:
<app>-android/app/build/outputs/apk/release/app-release.apk - AAB:
<app>-android/app/build/outputs/bundle/release/app-release.aab
<app> is your [project].name. With --json, the same path is in
data.artifacts.
Publish to Google Play¶
Uploading happens in the Play Console, outside kivyforge:
- Enroll the app in Play App Signing (App integrity > App signing).
- Upload the AAB to a release track.
- Sign every later upload with the same upload key.
Back up your key
With self-managed signing, a lost key cannot be recovered. Store the keystore and its passwords in a secure secret store.
What's next¶
- Supported Android versions: keep
target_sdkcurrent for Google Play. - Drive kivyforge from CI or an agent.
- Signing prerequisites for every platform.