Debug APK vs Release APK
-
Debug APK — Used for development and testing only. It is not signed with your release key, runs slower, and cannot be published to the Google Play Store.
-
Release APK / App Bundle — Signed with your private keystore, optimized for production, and required for publishing to the Google Play Store. This is what you generate in the steps below.
ℹ Important — Signing Configuration Required
The package does not include a release signing configuration. The android/app/build.gradle.kts file has no signingConfig set for the release build type. You must complete Steps 1–4 below and configure your own keystore before running flutter build apk --release or publishing to the Google Play Store.
⚠ Security Warning
- Never share your keystore file (
key.jks) or passwords with anyone.
- Never commit
key.jks or key.properties to Git or any public repository.
- If you lose your keystore file, you will not be able to publish future updates to the same app on the Play Store. Keep a secure backup in multiple locations.
Step 1: Create the keys/ Folder
-
In your Flutter project root, create a folder named keys if it does not already exist. This folder will hold your keystore file.
-
Your project structure should look like this:
your_project/
android/
ios/
lib/
keys/ <-- create this folder
key.jks <-- keystore file will be placed here
Step 2: Generate a Keystore with keytool
-
A keystore is a file that holds the private key used to sign your app. Android requires every release APK to be signed before it can be installed or published.
-
Open a terminal at your project root and run:
keytool -genkey -v -keystore keys/key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias key
-
You will be prompted to fill in the following information:
Enter keystore password: (choose a strong password)
Re-enter new password: (confirm password)
What is your first and last name?
What is the name of your organizational unit?
What is the name of your organization?
What is the name of your City or Locality?
What is the name of your State or Province?
What is the two-letter country code for this unit? (e.g. US, BD)
Enter key password for <key>: (choose a key password, can be same as keystore password)
-
After completing the prompts, the file keys/key.jks will be generated. Note down both passwords — you will need them in the next step.
Step 3: Create android/key.properties
-
This file tells the Android build system where your keystore is and what passwords to use. It must be placed inside the
android/ folder (not inside android/app/).
-
Create the file android/key.properties with the following exact content — replace the placeholder values with the passwords you set in Step 2:
storePassword=your_store_password
keyPassword=your_key_password
keyAlias=key
storeFile=keys/key.jks
-
Add both files to your
.gitignore to prevent them from being committed to version control:
# Add these lines to your .gitignore
keys/
android/key.properties
Step 4: Configure signingConfigs in android/app/build.gradle.kts
-
This step wires the keystore into the Android build process so that every release build is automatically signed.
-
Open android/app/build.gradle and add the following block at the very top of the file, before the
android {} block:
import java.util.Properties
import java.io.FileInputStream
val keystorePropertiesFile = rootProject.file("key.properties")
val keystoreProperties = Properties()
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(FileInputStream(keystorePropertiesFile))
}
-
Then, inside the
android { } block, add the signingConfigs section and update buildTypes as shown below:
android {
...
signingConfigs {
create("release") {
keyAlias = keystoreProperties["keyAlias"] as String
keyPassword = keystoreProperties["keyPassword"] as String
storeFile = keystoreProperties["storeFile"]?.let { file(it) }
storePassword = keystoreProperties["storePassword"] as String
}
}
buildTypes {
release {
signingConfig = signingConfigs.getByName("release")
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
}
Step 5: Build the Release APK or App Bundle
-
Run one of the following commands from your project root depending on what you need:
# Generate a signed Release APK
flutter build apk --release
# Generate an App Bundle for Google Play Store upload (recommended)
flutter build appbundle --release
-
Signed Release APK output location:
build/app/outputs/flutter-apk/app-release.apk
-
App Bundle output location:
build/app/outputs/bundle/release/app-release.aab
-
Google Play Store requires an .aab (App Bundle) for new app submissions. Use .apk for direct device installation or beta distribution.
Troubleshooting
-
Error: "No such file or directory: keys/key.jks" — The
keys/ folder does not exist. Create it manually at your project root before running the keytool command.
-
Error: "keytool is not recognized" — Java JDK is not installed or not added to your system PATH. Install the JDK and ensure it is accessible from your terminal.
-
Error: "Keystore file not found for signing config 'release'" — Check that the
storeFile path in key.properties exactly matches the location of your key.jks file, and that key.properties is inside the android/ folder.
-
Error: "Invalid keystore format" — The keystore file may be corrupted. Delete it and regenerate using the keytool command in Step 2.