Oore CI
Build and shipSign buildsAndroid signing

Add Android signing

Upload an Android keystore so Gradle signs the APK or App Bundle with it.

Add a keystore to one pipeline so Gradle signs the APKs or App Bundles that pipeline builds, and the runner verifies them.

What you need

  • Project developer, maintainer, instance admin, or instance owner access.
  • A working Android pipeline that produces an APK or App Bundle.
  • A .jks or .keystore file, its store password, key alias, and key password.

Warning — Keep an independent backup

Store the keystore and passwords outside Oore in a secure backup. Losing the application signing key can prevent future updates to an existing Android application.

1. Create a keystore if needed

If you do not already have an application signing key, create one with the JDK keytool:

keytool -genkeypair -v -keystore my-release-key.jks \
  -keyalg RSA -keysize 2048 -validity 10000 \
  -alias my-key-alias

Record the store password, alias, and key password when prompted.

2. Add the signing profile

  1. Open the project, then open the pipeline for editing.
  2. Under Signing > Android, turn on Enable release signing.
  3. Select the Release keystore (.jks) file.
  4. Enter Release key alias, Release store password, and Release key password.
  5. Select Save changes.

Use Enable debug signing only when that pipeline’s supported Flutter build command produces a debug artifact that needs a specific key. For automation, use the generated Update Android signing configuration operation.

3. Run a signed build

Trigger the pipeline with one Android variant. For a supported Flutter Android build command, the runner hands the keystore to Gradle for that command only, and Gradle signs the output. The android-sign step then checks each artifact, and signs again any that Gradle did not sign with this key. See Keep local Gradle signing alongside Oore for how it works and what a local key.properties setup needs.

Flavored apps

Signing works the same with --flavor. After each flutter build apk or flutter build appbundle command, the runner checks every .apk or .aab under build/app/outputs, including flavored output. Two things change:

  • Gradle writes a flavored App Bundle to a folder named after the flavor, such as build/app/outputs/bundle/prodRelease/app-prod-release.aab. Under Build > Artifacts, use a pattern that matches it, such as build/app/outputs/bundle/**/*.aab, instead of build/app/outputs/bundle/release/*.aab.
  • Every flavor in one run must use the same variant, such as release. To build several flavors, run one flutter build command per flavor, such as flutter build appbundle --release --flavor prod. Each command checks all the output of that kind under build/app/outputs, so every flavor is signed.

Verify the result

The build reaches succeeded, and its log includes an android-sign step that says Gradle signed the artifacts with the managed key. Download an APK and inspect its certificate:

apksigner verify --print-certs my-app-release.apk

For an App Bundle, use:

jarsigner -verify my-app-release.aab

The output includes jar verified. Do not add -strict. Upload keys are self-signed and App Bundles are not timestamped, which -strict reports as errors even for a correctly signed bundle.

Troubleshooting

The signing profile is rejected

Confirm the uploaded file, store password, key alias, and key password belong to the same keystore.

The build reports mixed Android variants

Use one debug or release variant per pipeline run. Do not mix debug and release Flutter build commands in the same run.

Repository Gradle code expects managed signing variables

Remove that dependency. The runner removes OORE_ANDROID_* variables from build commands. Gradle gets the keystore through its injected signing properties instead, with no Gradle code needed.

Next step

Keep local Gradle signing alongside Oore when the repository also signs release builds on developer machines.