Introduction / Purpose
Signing is a mandatory step for any Android application that is planned for distribution. The Android system uses a digital signature for:
- Author identification: Ensure that app updates come from the same developer.
- Access control: Allow the app to access protected features or code of other apps with the same signature.
- Updates: Without matching signatures, a new version of the app cannot be installed over the old one.
Google Play categorically requires that all uploaded APKs and AABs be signed with your own release key. This guide will walk you through the entire process: from creating a keystore to obtaining a file ready for upload.
Requirements / Preparation
Before starting, ensure you have installed and configured:
- Android Studio (any latest stable version, e.g., Flamingo or newer).
- Android SDK and JDK (which comes with Android Studio or is installed separately, version 11+).
- Access to the command line (
terminalorcmd). - Administrator privileges (may be required on some systems to access certain paths).
- A ready release build of your project (debugged, with correct
versionCodeandversionNameinbuild.gradle).
Step 1: Creating a Keystore
A keystore (.jks or .keystore) is a file containing your private key and certificate. It needs to be created once and stored in a secure location (with a backup!).
Method A: Through Android Studio (recommended for beginners)
- In the menu, select Build → Generate Signed Bundle / APK...
- In the dialog, select APK or Android App Bundle (AAB) and click Next.
- In the Key store path section, click Create new....
- Fill in the fields:
- Key store path: Specify the path and filename (e.g.,
~/my-release-key.jks). - Password: Come up with and enter a strong password (remember it!).
- Key alias: Come up with a name for your key (e.g.,
my_app_key). - Key password: You can use the same password as for the keystore (recommended) or a different one.
- Validity (years): Specify the validity period (e.g., 25 years or more, so the certificate doesn't expire before the app's end of life).
- Certificate fields: Fill in with your real data (First and Last Name, Organizational Unit, Organization, City, State, Country Code). This won't be visible to users but is formally required.
- Key store path: Specify the path and filename (e.g.,
- Click OK, then Next.
Method B: Through the command line (keytool)
The keytool utility is part of the JDK.
keytool -genkeypair -v \
-keystore ~/my-release-key.jks \
-keyalg RSA -keysize 2048 \
-validity 10000 \
-alias my_app_key
-keystore: Path to the file being created.-keyalg: Algorithm (RSA standard).-keysize: Key size (2048 or 4096 bits).-validity: Validity period in days (10000 ~ 27 years).-alias: Key alias.
You will be prompted to enter passwords and certificate data.
💡 Tip: Never add the
my-release-key.jksfile to version control (.gitignore). Store it in a secure location outside the project.
Step 2: Configuring signingConfigs in Gradle
Open the module-level build.gradle file (usually app/build.gradle).
Inside the android { ... } block, add a signingConfigs block and a release configuration:
android {
// ... other settings (compileSdk, defaultConfig, etc.)
signingConfigs {
release {
// Path to the keystore file. Use an absolute path or variable.
storeFile file('../my-release-key.jks') // Example: file in the project's parent folder
storePassword 'your_keystore_password' // Keystore password
keyAlias 'my_app_key' // Your key alias
keyPassword 'your_key_password' // Key password (may be the same)
}
}
buildTypes {
release {
// ... other release settings (minifyEnabled, proguard, etc.)
signingConfig signingConfigs.release // <-- THIS LINE IS CRITICALLY IMPORTANT
}
debug {
// Debug builds are usually signed automatically with the debug key.
signingConfig signingConfigs.debug
}
}
}
⚠️ Important: Never commit passwords in plain text to the repository! For production builds, use Gradle properties or environment variables:
- In
~/.gradle/gradle.properties(globally) orproject/gradle.properties(locally) add:MY_KEYSTORE_PASSWORD=super_secret_pass MY_KEY_PASSWORD=super_secret_pass- In
build.gradlesubstitute:storePassword System.getenv("MY_KEYSTORE_PASSWORD") ?: project.property('MY_KEYSTORE_PASSWORD') keyPassword System.getenv("MY_KEY_PASSWORD") ?: project.property('MY_KEY_PASSWORD')
Step 3: Generating the Release Artifact (APK/AAB)
After configuring signingConfigs, you can create signed files.
Method A: Through Android Studio (GUI)
- Build → Generate Signed Bundle / APK...
- Select APK or AAB.
- On the Key store path step, select Choose existing... and specify your
my-release-key.jks. Enter the passwords. - Select release in Build Variant (if not already selected).
- Click Finish. The built file will be in
app/release/(orapp/build/outputs/bundle/release/for AAB).
Method B: Through the command line (Gradle Wrapper)
In the project root, run:
# For APK
./gradlew assembleRelease
# For AAB (Android App Bundle)
./gradlew bundleRelease
The built files are located in:
- APK:
app/build/outputs/apk/release/app-release.apk - AAB:
app/build/outputs/bundle/release/app-release.aab
Step 4: Verifying the Signature (optional but recommended)
Ensure that the file is actually signed with your key.
For APK (using jarsigner from JDK):
jarsigner -verify -verbose -certs app/build/outputs/apk/release/app-release.apk
In the output, look for the line jar verified. and information about your alias (my_app_key).
For AAB (using apksigner from Android SDK Build-Tools):
# On Windows: apksigner.bat
$ANDROID_HOME/build-tools/<version>/apksigner verify --verbose app/build/outputs/bundle/release/app-release.aab
Verifying the Result
- File exists: Ensure that
app-release.apkorapp-release.aabis in the specified folder. - Signature is valid: Successful execution of the verification command from Step 4.
- File size: The release APK/AAB will be significantly smaller than the debug one (due to compression and lack of debug information).
- Publication in Google Play Console: Upload the generated AAB (preferred) or APK. Google Play's validation system should accept the file without signature-related errors.
⚠️ Critically important: The same keystore and alias must be used for all future updates of this app. If you lose them or forget the passwords — updates via Google Play will become impossible.
Possible Issues
Error: Keystore was tampered with, or password was incorrect
- Cause: Incorrect keystore password or corrupted file.
- Solution: Check the password. Ensure you are using the correct
.jksfile. If the password is lost, the keystore becomes useless.
Error: Execution failed for task ':app:validateSigningRelease'. > Keystore file not found for signing config 'release'
- Cause: An incorrect path to
storeFileis specified inbuild.gradle. - Solution: Check the path. It's better to use an absolute path or
file('../relative/path.jks'). Ensure the file exists.
Build error: Failed to sign the APK
- Cause: Often related to algorithm incompatibility (old keystore with SHA1) or an error in
gradle.properties. - Solution: Ensure all 4 parameters (
storeFile,storePassword,keyAlias,keyPassword) are specified insigningConfigs. Check that passwords containing special characters are properly escaped ingradle.properties.
Cannot install release APK on device (error INSTALL_PARSE_FAILED_NO_CERTIFICATES)
- Cause: The APK file was not signed, or the signature is invalid.
- Solution: Rebuild the artifact, ensuring that
signingConfigis applied to thereleasebuild type. Verify the signature with thejarsigner -verifycommand.
::in-article-ad::
Final Recommendations
- Backup: Make several copies of the
.jksfile and store passwords in a reliable password manager (e.g., KeePass, Bitwarden). Keep copies in different physical locations. - Certificate information: Keep a document with your certificate data (alias, DN, expiration date, SHA-1 fingerprint). This will be needed for some services (e.g., Google API setup).
- Increasing
versionCode: Before each new publication on Google Play, always increment the integerversionCodein thedefaultConfigof yourbuild.gradle. Without this, Play Console will reject the upload. - Testing: Install the generated release APK on a physical device before uploading to Play Console to ensure everything works correctly (including in-app licenses, deep links, etc.).
By following this guide, you will obtain a properly signed artifact ready for publication on any marketplace, including Google Play.