Building and Signing - HmnDev-Tech/BLE-Droid GitHub Wiki

Building and Signing

Local build

./gradlew assembleDebug     # debug APK
./gradlew assembleRelease   # release APK (unsigned unless signing env is set)

Outputs:

  • app/build/outputs/apk/debug/app-debug.apk
  • app/build/outputs/apk/release/app-release.apk (signed) or app-release-unsigned.apk (no signing env)

Requirements: JDK 21, Android SDK with compileSdk 36.

Signing — one key for both variants

Both build types read the same keystore, so debug and release APKs come out with an identical signer certificate:

Env var Meaning
KEYSTORE_PATH Path to the .jks file. Absent → debug falls back to the default ~/.android/debug.keystore, release stays unsigned.
KEYSTORE_PASSWORD Keystore password
KEY_ALIAS Key alias
KEY_PASSWORD Key password

Example (PowerShell):

$env:KEYSTORE_PATH = "C:\secrets\bledroid.jks"
$env:KEYSTORE_PASSWORD = "..."
$env:KEY_ALIAS = "bledroid"
$env:KEY_PASSWORD = "..."
.\gradlew.bat assembleDebug assembleRelease

Same-signer check:

bt=$(ls "$ANDROID_HOME/build-tools" | sort -V | tail -n 1)
"$ANDROID_HOME/build-tools/$bt/apksigner" verify --print-certs app/build/outputs/apk/debug/app-debug.apk   | grep "SHA-256 digest"
"$ANDROID_HOME/build-tools/$bt/apksigner" verify --print-certs app/build/outputs/apk/release/app-release.apk | grep "SHA-256 digest"

Use apksigner, not keytool -printcert -jarfile: the APKs are signed with the v2 scheme only, which keytool cannot read. Both digests must be identical.

Never commit the keystore or passwords. The keystore lives in CI secrets only.

CI builds

Every push and PR to main/master runs build-apk.yml:

  1. Decodes the keystore from the KEYSTORE_B64 secret (generates a throwaway key with a warning if the secret is missing).
  2. Builds both assembleDebug and assembleRelease.
  3. Fails the job if debug and release are not signed with the same certificate.
  4. Uploads BleDroid-debug.apk, BleDroid-release.apk, SHA256SUMS as the BleDroid-APK artifact (kept 30 days).

Manual run: Actions → Build APK → Run workflow.

Required repository secrets

Secret Value
KEYSTORE_B64 base64 -w0 bledroid.jks (on Windows PowerShell: [Convert]::ToBase64String([IO.File]::ReadAllBytes("bledroid.jks")))
KEYSTORE_PASSWORD Keystore password
KEY_ALIAS Key alias
KEY_PASSWORD Key password

Without KEYSTORE_B64 every run signs with a fresh key: debug and release still match within a run, but APKs from different runs cannot be installed as updates of each other. Set the secrets once and the signature stays stable.

Verify an APK you downloaded

sha256sum -c SHA256SUMS
bt=$(ls "$ANDROID_HOME/build-tools" | sort -V | tail -n 1)
"$ANDROID_HOME/build-tools/$bt/apksigner" verify --print-certs BleDroid-release.apk | grep "SHA-256 digest"

Compare the certificate SHA-256 digest with the value printed by the Verify debug and release share one signer step of the workflow run.