Play Store Signing Key Generator
Fill in your app details and get the exact keytool command, key.properties file and Gradle signing config for a Flutter or Android release build.
Certificate identity — optional
These go into the certificate. Nobody sees them on the store listing and none of them can be changed later, so a company name you will still recognise in ten years is enough. Leave them blank and keytool asks for each one at the prompt instead.
- 01
Generate the key
Run this from anywhere. It writes the keystore to ~/keys/ — deliberately outside the project, so it can never be committed by accident. keytool will prompt for your name and organisation interactively, then for a password twice. Fill in the identity fields above to skip the prompts.
mkdir -p ~/keys keytool -genkeypair -v \ -keystore ~/keys/upload-keystore.jks \ -storetype PKCS12 \ -keyalg RSA -keysize 2048 \ -validity 9855 \ -alias upload - 02
Keep it out of git
.gitignore · android/.gitignoreThe keystore lives outside the repo, but the properties file holding its password does not. Add these before the first commit — a password in git history stays there after you delete the line.
key.properties *.jks *.keystore *.p12 - 03
Point Gradle at the key
android/key.propertiesPasswords stay in this file, and this file stays out of git. It sits next to android/app, not at the Flutter project root. Use an absolute path for storeFile — a relative one resolves differently depending on which directory Gradle was invoked from.
storePassword=<the password you just set> keyPassword=<the same password> keyAlias=upload storeFile=/Users/you/keys/upload-keystore.jks - 04
Wire the signing config
android/app/build.gradle.ktsThe two imports have to sit at the very top of the file, above the plugins block — Kotlin DSL rejects an import anywhere else. The exists() guard is what lets the project still build on a machine that has no key, which is what you want for CI that only runs tests.
import java.util.Properties val keystoreProperties = Properties() val keystorePropertiesFile = rootProject.file("key.properties") if (keystorePropertiesFile.exists()) { keystorePropertiesFile.inputStream().use { keystoreProperties.load(it) } } android { signingConfigs { create("release") { keyAlias = keystoreProperties["keyAlias"] as String keyPassword = keystoreProperties["keyPassword"] as String storeFile = file(keystoreProperties["storeFile"] as String) storePassword = keystoreProperties["storePassword"] as String } } buildTypes { release { signingConfig = signingConfigs.getByName("release") } } } - 05
Build the bundle you upload
Play requires an .aab, not an .apk. The file lands at build/app/outputs/bundle/release/app-release.aab. If it builds but Play rejects it as debug-signed, the signingConfig line inside buildTypes is missing — Gradle falls back to the debug key silently rather than failing.
flutter build appbundle --release - 06
Read the fingerprints back
SHA-1 and SHA-256 from this keystore are what Firebase, Google Sign-In and Android App Links need. Register the upload key's fingerprint now, then add the one Play generates after your first release — with Play App Signing there are two, and only registering one is why sign-in works in debug and fails in production.
keytool -list -v -keystore ~/keys/upload-keystore.jks -alias upload
Back the key up before you publish, not after
Losing the upload key is recoverable — Google can reset it if you have Play App Signing enabled, which is the default for new apps. Losing the app signing key on an older app that opted out is not: no update can ever be published to those installs again. Copy the keystore and its password to somewhere that survives a dead laptop, and do it now rather than at the first update. Renaming the project the key belongs to is a separate checklist, and the walkthrough for a bought template covers both together.
Other free tools
Firebase & Maps Cost Calculator
Estimate what a delivery or marketplace app costs per month — Firestore reads and writes, map loads and Routes calls, at current list prices.
Package ID Renamer
Paste a new bundle id and get the exact files, lines and Gradle values to change in a Flutter or Android project.
AdMob Test ID Cheatsheet
Copy-paste Google test unit ids for banner, interstitial, rewarded and native, for both platforms.