Signing Your Android App

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.properties to 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.gradle to 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

  1. Secure Your Keystore
    • Keep the keystore file in a safe location and back it up.
    • Losing the keystore prevents updates to the app.
  2. Use Environment Variables for Passwords
    • Avoid hardcoding passwords in build.gradle.
  3. Use Long Validity Keys
    • Set key validity to at least 25–30 years to avoid future expiration issues.
  4. Test Signed Builds Thoroughly
    • Signed builds can behave differently than debug builds. Test all features before submission.
  5. 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 keytool is 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.gradle paths and alias names.
  • Use absolute paths if relative paths cause errors.

8. Advanced Tips

  1. Use Google Play App Signing
    • Google Play can manage the app signing key for you, adding an extra layer of security.
  2. Automate Signing in CI/CD
    • Use Codemagic, GitHub Actions, or Bitrise to automate signed build generation.
  3. Use ProGuard or R8
    • Enable code shrinking and obfuscation to reduce APK size and protect source code.
  4. Split APKs by ABI
    • Use --split-per-abi to generate smaller APKs for different device architectures.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *