In Part 1, you created a Play Console account, which you will soon use to deploy your app to the Play Store. However, the Play Console requires that you upload a release app bundle for distribution.
The official documentation is a thorough primary reference for how to create a release app bundle. However, it assumes some knowledge that newer app developers may lack and several steps are unnecessary for many apps. So, this guide is a simplified version of the official one, with a few extra tips, concept explanations, context and references.
In other words, this guide is most suitable for developers publishing their first app. However, if your app is large (>64K methods), if you use Platform Views, if you have multiple build flavours, or if you plan to publish someplace other than the Play Store, you should refer to the official documentation instead.
It's important to give credit where due, so the parts of this guide that are copied straight from the official documentation are marked with <From Docs></From Docs>
Step 1 - Make Launch Icons
To create your launch icon, the official documentation suggests using flutter_launcher_icons or creating them manually.
Many developers prefer a third process, described here.
Step 2 - Create a Keystore and Upload Key
If you already have a keystore and upload key, skip to Step 3.
Your app bundle should be signed with an "upload key" before it is uploaded to the Play Console. From there, Google can use "Play App Signing" (recommended) to sign the app before it is released to the Play Store. Read here for more information on the signing process.
To create your keystore and upload key, follow the instructions below from the docs.
<From Docs>
On Mac/Linux, use the following command:
keytool -genkey -v -keystore ~/upload-keystore.jks -keyalg RSA -keysize 2048 -validity 10000 -alias upload
On Windows, use the following command:
keytool -genkey -v -keystore %userprofile%\upload-keystore.jks -storetype JKS -keyalg RSA -keysize 2048 -validity 10000 -alias upload
</From Docs>
After creating your keystore and upload key, note down the name and location of your newly created keystore. If you copied straight from the above, your file will be named upload-keystore.jks
and in your home folder.
Finally, note down the passwords you just created for your keystore file and key (preferably in the password manager of your choice). This information is needed in the Step 3.
A final note on app signing:
If you find the concept of app signing confusing, you are not alone! Many developers -- even experienced ones -- have not encountered the concept until they try to publish an app for the first time. You can still publish your app by following this guide, without understanding the details.
However, if you are new to or confused by the concept, I strongly recommend taking the time to learn a little more about public key cryptography generally and Android app signing specifically. This deeper understanding is useful multiple times:
now, when signing your Android app for the Play Store
later, when signing your iOS app for the App Store (a different, more complicated process)
finally, when you configure your apps for CI/CD with AppCircle
Step 3 - Connect your Keystore and Key to the App
To reference the newly created keystore and key in your app project, create a file called key.properties
at <project_root>/android/key.properties
and add the following:
<From Docs>
storePassword=<password from previous step>
keyPassword=<password from previous step>
keyAlias=upload
storeFile=<location of the key store file, such as /Users/<user name>/upload-keystore.jks>
</From Docs>
This file includes the key and keystore's password in plain text! If you are using git, go double-check your .gitignore
file and make sure it includes key.properties
. If you are not using git, take appropriate steps to protect the key.properties
file.
Step 4 - Configure Signing of your Release build in Gradle
In Flutter, there are 3 types of builds - Debug, Profile and Release. If you have been developing your Flutter app with the command flutter run
or pressing a Play button (without any extra configuration in your IDE) until now, you have been creating Debug builds. To publish an app to the Play Store, you must create a Release build signed with the upload key we created in the previous steps.
The Debug and Release build types differ in a few important ways:
Release builds are optimized for smaller size and faster execution
It's not possible to debug or hot reload Release builds (this is why you develop with a Debug build)
Release builds can be signed, which you must do before uploading your app bundle to the Play Store
In Android, by default, there are Debug and Release type builds (although you can configure others, such as staging or beta). The build configurations for the different build types of an Android app are defined in the build.gradle
file.
When you are finally ready to create Release build of your Flutter app for upload to the Play Console, the instructions for building and signing the app are defined in the build.gradle
file found in the <project root>/android/app/build.gradle
folder (not the one in the <project root>/android/build.gradle
).
So, let's add the app signing instructions to your app build.gradle
file now by following the instructions in the official docs.
<From Docs>
Add the keystore information from your properties file before the
android
block:def keystoreProperties = new Properties() def keystorePropertiesFile = rootProject.file('key.properties') if (keystorePropertiesFile.exists()) { keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) } android { ... }
Load the key.properties
file into the keystoreProperties
object.
Find the
buildTypes
block:buildTypes { release { // TODO: Add your own signing config for the release build. // Signing with the debug keys for now, // so `flutter run --release` works. signingConfig signingConfigs.debug } }
And replace it with the following signing configuration info:
signingConfigs { release { keyAlias keystoreProperties['keyAlias'] keyPassword keystoreProperties['keyPassword'] storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null storePassword keystoreProperties['storePassword'] } } buildTypes { release { signingConfig signingConfigs.release } }
Release builds of your app will now be signed automatically.
Note: You may need to run flutter clean
after changing the gradle file. This prevents cached builds from affecting the signing process.
</From Docs>
Step 5 - Update the Android Manifest and Gradle files
5a - Choosing an App Id
To upload an Android app to the Play Console, it must have a unique app id. If you created your Flutter project using Android Studio, you may already have an appropriate app id.
However, when you make a new Flutter project with flutter create
or a different IDE, the default com.example.<app_name>
is used. The com.example
namespace is restricted and you cannot upload an app to the Play Console with it.
So, now it is time to update your app id to something else. The app id name follows Java/Kotlin package naming conventions, with a few added rules. Here are the app id naming rules to keep in mind:
it must have at least 2 segments (the segments are the strings separated by dots)
Valid characters for the segments: [a-zA-Z0-9_]
Each segment must start with a letter
If you have a website, it is common to use that namespace. For example, I use dev.aerial.<app_name>
. Read more about Android app ids here.
IMPORTANT! After you have uploaded your app to the Play Console, you cannot change the app id. If you do, it will be treated as a new, separate app.
5b - Gradle Update
After deciding on your app id, you can return to same the build.gradle
file you edited in Step 4 (<project root>/android/app/build.gradle
). Look for the defaultConfig
block (inside the android
block) and modify the applicationId
parameter with the name you have chosen.
5c - Android Manifest Update - App ID
Now open up the Android manifest file found at <project root>/android/app/src/main/AndroidManifest.xml
If this is the first Flutter app you are publishing to the Play Store, you may not have encountered it before. For now, you should know that the Android Manifest is used to:
Declare system permissions (eg., access photos or access the internet)
Declare the app components. Your Flutter app will (likely) only need the one main Activity declared there by default.
It also has more advanced functionality which can read about here.
So, open up the Android Manifest file and search for the android:label
field inside the <application>
block. Edit the value there to reflect the name of your app. This string is displayed with your launch icon on Android devices.
5d - Android Manifest Update - Internet permission
Finally, if your app uses the internet, you need to add an internet permission to your main activity. It is included by default in the debug manifest (found at <project root>/android/app/src/debug/AndroidManifest.xml
) used in debug builds. So, you may not have noticed it was missing if you were only using debug builds until now.
To add internet to your release build, add the following line inside the <manifest>
block:
<uses-permission android:name="android.permission.INTERNET"/>
The top of your manifest file should now look something like this (with your own android:label
and package
string)
5e - Extra credit - Android package name
The next step is not strictly necessary, but I recommend it for completeness:
In the <manifest>
block (top of the file), look for the package
field. Update this to match the app id you defined earlier in the build.gradle
file. The default value is com.example.<app name>
If curious, you can read more about Android package name vs. Application id here.
Step 6 - Create a signed Release build
You are finally ready to create a release build! Open a terminal, cd into your project root and run the following command:
flutter build appbundle
This will create an .aab file (app bundle) in the following location:
<project root>/build/app/outputs/bundle/release/app.aab
app.aab
is the file you will eventually upload to the Play Console for release to the Play Store. Read Part 3 (coming soon) to learn about how you use the Play Console to publish your app to the Play Store.