Introduction
Signing an Android app is a critical step in the release process. It ensures authenticity, integrity, and verifies that the app originates from a trusted source. Unsigned apps cannot be published on the Google Play Store, and users may see warnings when installing them.
In Flutter, signing an Android app involves generating a keystore, configuring the signing in Gradle, and building a release APK or AAB with the signing applied. This article provides a comprehensive guide to signing Android apps, covering the concepts, step-by-step instructions, best practices, and troubleshooting tips.
1. Understanding App Signing
1.1 What is App Signing?
App signing uses a cryptographic key to digitally sign an APK or AAB. The signature ensures:
- Authenticity: Confirms the app is from the developer it claims to be.
- Integrity: Detects if the APK/AAB has been tampered with after signing.
Every update to the app must be signed with the same key, ensuring users can seamlessly update without reinstalling.
1.2 Types of Keys
- Debug Key: Automatically generated by Flutter/Android Studio for testing and development.
- Release Key: A private key you generate for publishing on the Play Store. This key must be securely stored and backed up.
2. Generate a Keystore
The first step in signing your app is generating a release keystore.
2.1 Generate Keystore Command
Use the keytool command (part of Java JDK) in your terminal:
keytool -genkey -v -keystore release-key.jks -alias your-alias -keyalg RSA -keysize 2048 -validity 10000
2.2 Parameters Explained
- -keystore release-key.jks: File name for the keystore.
- -alias your-alias: Identifier for your key.
- -keyalg RSA: Cryptographic algorithm used.
- -keysize 2048: Key length in bits.
- -validity 10000: Number of days the key is valid (~27 years).
2.3 Keystore Details
During generation, you’ll be prompted to provide:
- Keystore password
- Key password (can be the same as keystore password)
- Your full name, organization, and location
Store the keystore securely. Losing it means you cannot release app updates.
3. Configure Signing in build.gradle
After generating the keystore, you must configure your Flutter Android project to use it.
3.1 Location of build.gradle
- Edit the file:
android/app/build.gradle
3.2 Add Signing Config
Add a signingConfigs block inside the android section:
android {
...
signingConfigs {
release {
keyAlias 'your-alias'
keyPassword 'your-key-password'
storeFile file('release-key.jks')
storePassword 'your-keystore-password'
}
}
buildTypes {
release {
signingConfig signingConfigs.release
minifyEnabled false
shrinkResources false
// Use proguard if needed
// proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
3.3 Best Practices
- Do not hardcode passwords: Use
gradle.propertiesto keep passwords secure. - Example
gradle.properties(local only, do not commit to version control):
MY_KEYSTORE_PASSWORD=your-keystore-password
MY_KEY_PASSWORD=your-key-password
MY_KEY_ALIAS=your-alias
- Modify
build.gradleto reference properties:
signingConfigs {
release {
keyAlias project.MY_KEY_ALIAS
keyPassword project.MY_KEY_PASSWORD
storeFile file('release-key.jks')
storePassword project.MY_KEYSTORE_PASSWORD
}
}
4. Build Release APK or AAB
After signing configuration, generate a signed release build.
4.1 Build Release APK
flutter build apk --release
- The APK is generated in
build/app/outputs/flutter-apk/app-release.apk. - Verify the signature using:
jarsigner -verify -verbose -certs build/app/outputs/flutter-apk/app-release.apk
4.2 Build Release AAB
Google Play Store recommends App Bundle (AAB) for optimized delivery.
flutter build appbundle --release
- The AAB is located in
build/app/outputs/bundle/release/app-release.aab. - Upload this file to the Google Play Console.
5. Verify App Signing
Before publishing, verify that the app is properly signed:
5.1 Check Signature
apksigner verify build/app/outputs/flutter-apk/app-release.apk
- If signed correctly, you will see:
Verifies
Verified using v1 scheme (JAR signing): true
Verified using v2 scheme (APK Signature Scheme v2): true
5.2 Test Installation
- Install the APK on a device using:
adb install build/app/outputs/flutter-apk/app-release.apk
- Ensure the app installs without warnings and functions correctly.
6. Best Practices for App Signing
- Secure Your Keystore
- Keep the keystore file in a safe location and back it up.
- Losing the keystore prevents updates to the app.
- Use Environment Variables for Passwords
- Avoid hardcoding passwords in
build.gradle.
- Avoid hardcoding passwords in
- Use Long Validity Keys
- Set key validity to at least 25–30 years to avoid future expiration issues.
- Test Signed Builds Thoroughly
- Signed builds can behave differently than debug builds. Test all features before submission.
- Follow Play Store Guidelines
- Ensure the app meets all Google Play signing and upload requirements.
7. Common Issues and Troubleshooting
7.1 Keytool Not Found
- Ensure Java JDK is installed and
keytoolis in your PATH.
7.2 Incorrect Passwords
- Verify that the keystore and key passwords are correct.
7.3 Play Store Upload Rejection
- Ensure the AAB/APK is signed with the same key for updates.
- Do not mix debug and release keys.
7.4 Missing Signing Config
- Double-check
build.gradlepaths and alias names. - Use absolute paths if relative paths cause errors.
8. Advanced Tips
- Use Google Play App Signing
- Google Play can manage the app signing key for you, adding an extra layer of security.
- Automate Signing in CI/CD
- Use Codemagic, GitHub Actions, or Bitrise to automate signed build generation.
- Use ProGuard or R8
- Enable code shrinking and obfuscation to reduce APK size and protect source code.
- Split APKs by ABI
- Use
--split-per-abito generate smaller APKs for different device architectures.
- Use
Leave a Reply