-
Notifications
You must be signed in to change notification settings - Fork 1
Android Signing Setup
Use this guide when preparing OnTime for Google Play release builds.
- Google Play releases should use Play App Signing.
- The local team keeps an upload key and uses it to sign app bundles before uploading them to Play Console.
- Google Play uses the upload key to verify the upload, then signs distributed APKs with the app signing key.
- Do not commit keystores, passwords,
android/key.properties, or generated release artifacts.
The Android release owner for club.devkor.ontime owns the upload keystore
process. This role is responsible for:
- creating or confirming the current upload keystore;
- storing the keystore file and passwords in the team password manager or CI secret manager;
- limiting access to release maintainers;
- documenting recovery notes in the secure storage record;
- rotating or requesting a Play Console upload-key reset if the upload key is lost or exposed.
Never store keystore files or passwords in git, issue comments, pull requests, chat logs, screenshots, or build artifacts.
Create and store the keystore somewhere outside the repository:
mkdir -p ~/secure
keytool -genkeypair -v \
-keystore ~/secure/ontime-upload.jks \
-storetype JKS \
-keyalg RSA \
-keysize 2048 \
-validity 10000 \
-alias ontimeSave the keystore file and passwords in the team password manager or secret manager. Losing the upload key requires a Play Console upload-key reset.
Create android/key.properties locally:
storeFile=/absolute/path/to/ontime-upload.jks
storePassword=<keystore-password>
keyAlias=ontime
keyPassword=<key-password>android/key.properties is ignored by git and must stay local.
Alternatively, set environment variables:
export ANDROID_KEYSTORE_PATH=/absolute/path/to/ontime-upload.jks
export ANDROID_KEYSTORE_PASSWORD='<keystore-password>'
export ANDROID_KEY_ALIAS=ontime
export ANDROID_KEY_PASSWORD='<key-password>'The Gradle build also accepts the legacy ONTIME_ANDROID_KEYSTORE_PATH,
ONTIME_ANDROID_KEYSTORE_PASSWORD, ONTIME_ANDROID_KEY_ALIAS, and
ONTIME_ANDROID_KEY_PASSWORD variable names for compatibility.
For GitHub Actions deploys, base64-encode the upload keystore and store it as
the ANDROID_UPLOAD_KEYSTORE_B64 secret in the protected staging
environment used by the Android Play Internal Deploy workflow:
base64 -i ~/secure/ontime-upload.jks | pbcopyOn Linux, use:
base64 -w 0 ~/secure/ontime-upload.jksThe deploy workflow decodes this secret into $RUNNER_TEMP/ontime-upload.jks
and exports ANDROID_KEYSTORE_PATH to that temporary file. Do not create
android/key.properties in CI.
The protected environment must also provide:
ANDROID_KEYSTORE_PASSWORDANDROID_KEY_ALIASANDROID_KEY_PASSWORD
Google Play prefers Android App Bundles:
flutter build appbundle --release \
--build-name=<version name from pubspec.yaml> \
--build-number=<monotonic Android versionCode>For APK validation outside Play:
flutter build apk --releaseThe Gradle config intentionally fails release builds when signing secrets are
missing. The failure lists missing local or CI inputs, including
storeFile/ANDROID_KEYSTORE_PATH, storePassword/ANDROID_KEYSTORE_PASSWORD,
keyAlias/ANDROID_KEY_ALIAS, and keyPassword/ANDROID_KEY_PASSWORD. Debug
builds do not require release signing secrets.
- Create or open the app in Google Play Console.
- Create a release on an internal testing track first.
- Configure Play App Signing when prompted.
- Use Google-generated app signing key unless the team needs to share the same signing key across multiple stores or related apps.
- Upload the
.aabfrombuild/app/outputs/bundle/release/. - After Play App Signing is active, continue signing future uploads with the same local upload key.
- Record the Play app signing and upload key SHA-1/SHA-256 fingerprints using
docs/Android-Play-Signing-Fingerprints.md.
- If the app already has an upload key, use that existing key.
- If the upload key is lost but Play App Signing is enabled, request an upload key reset in Play Console.
- If Play App Signing is not enabled and the app signing key is lost, the app generally cannot be updated under the same package name.
Run these checks before handing a release build to QA or Play Console:
flutter analyze
flutter test
flutter build appbundle --release \
--build-name=<version name from pubspec.yaml> \
--build-number=<monotonic Android versionCode>Confirm that pubspec.yaml has the intended public version name. In GitHub
Actions deploys, Android versionCode comes from github.run_number; for any
manual Play upload, provide a build number greater than every previous Play
Console upload for club.devkor.ontime.