Steps to generate an APK and ABB signed in Release mode in Flutter using VSC
- Andrés Cruz
In this post we will see several tips, steps and considerations that you should take into account when you want to generate the production release of your application in Flutter using Visual Studio Code; the Android app/apk that we are going to generate will be signed, which is required by Google to be able to upload your app to the Google Play Store.
You can also take these steps into account if you use Android Studio.
Finally, we are going to use Windows to carry out these steps; This is the official documentation from the Flutter team:
https://docs.flutter.dev/deployment/android
To generate a signed APK in Release mode for a Flutter application on Android using Visual Studio Code (VSC), you must follow these steps:
1 Generate the Key (Keystore):
- Open a terminal in VSC.
- Run the following command to generate a key (keystore) using keytool (you can do this from any location on your system):
keytool -genkey -v -keystore release-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias key-alias
- Follow the instructions to configure the key (password, name, etc.); It is a form like the following that you must fill out with basic information; From the previous command, you can customize the location of the release-key.jks as well as the key-alias.
C:\Users\andre\flutter
.\keytool.exe -genkey -v -keystore my-release-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias key-alias
Introduzca la contraseña del almacén de claves:
Volver a escribir la contraseña nueva:
¿Cuáles son su nombre y su apellido?
[Unknown]: Tu Nombre
¿Cuál es el nombre de su unidad de organización?
[Unknown]: TuEmpresa
¿Cuál es el nombre de su organización?
[Unknown]: TuEmpresa
¿Cuál es el nombre de su ciudad o localidad?
[Unknown]: TuCiudad
¿Cuál es el nombre de su estado o provincia?
[Unknown]: TuEstado
¿Cuál es el código de país de dos letras de la unidad?
[Unknown]: (EJ VE)
¿Es correcto CN=andres cruz, OU=desarrollolibre, O=desarrollolibre, L=caracas, ST=distrito capital, C=VE?
[no]: si
If you have problems with the keytool command, we already discussed it in the next section.
2 Create the key.properties file:
- In the android folder of your Flutter project, create a file called key.properties.
- Add the following information to the file:
storePassword=your_keystore_password keyPassword=your_key_password keyAlias=my-key-alias storeFile=release-key.jks
3 Modify the build.gradle file:
- Open the android/app/build.gradle file.
- Add the following configuration, those with the + symbol are the ones you should add
+ def keystoreProperties = new Properties() + def keystorePropertiesFile = rootProject.file('key.properties') + if (keystorePropertiesFile.exists()) { + keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) + } + android { ... } + signingConfigs { + release { + keyAlias keystoreProperties['keyAlias'] + keyPassword keystoreProperties['keyPassword'] + storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null + storePassword keystoreProperties['storePassword'] + } + } 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 + signingConfig signingConfigs.release } }
In summary, we are adding at the code level that the compiler will use what parameters are based on the previously generated keystore to generate our signed app.
4 Generate the signed APK:
Finally, we execute the command to generate the signed app in apk format:
flutter build apk
- Or in abb:
flutter build appbundle
- The signed APK file (app-release.apk) will be generated in the build/app/outputs/apk folder of your Flutter project and this is the one you must upload to Google Play. Before uploading, I recommend that you install the apk on a physical device, for that, you copy it to the Android device and follow the installation steps.
- Do not share the keystore file (release-key.jks) publicly. Store it safely.
Ready! You now have a signed APK in Release mode for your Flutter app on Android.
Problems generating the signed apk
Of course, there are many things that can go wrong when generating your signed application, and this is what we will cover next; If when executing the command it gives an error like the following:
You must add the reference to the installer to your system path or simply move to the keystore location; for this, we must first locate where the .exe is located, for that, we can use the flutter command:
flutter doctor -v
And we look for something like:
cd 'C:\Program Files\Android\Android Studio\jbr\bin\\'
C:\Program Files\Android\Android Studio\jbr\bin\java
Android toolchain - develop for Android devices (Android SDK version 34.0.0)
• Android SDK at C:\Users\andre\AppData\Local\Android\sdk
• Platform android-34, build-tools 34.0.0
• Java binary at: C:\Program Files\Android\Android Studio\jbr\bin\java
• Java version OpenJDK Runtime Environment (build 17.0.10+0--11572160)
• All Android licenses accepted.
Where it tells us where Java is:
C:\Program Files\Android\Android Studio\jbr\bin\java
Now, we move the terminal to that location without including the java folder (you can add this same address to the path of your system if you wish):
cd C:\Program Files\Android\Android Studio\jbr\bin
And we execute:
keytool -genkey -v -keystore release-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias key-alias
It probably tells you that it's just writing:
error de herramienta de claves: java.io.FileNotFoundException: my-release-key.jks (Acceso denegado)
java.io.FileNotFoundException: my-release-key.jks (Acceso denegado)
at java.base/java.io.FileOutputStream.open0(Native Method)
at java.base/java.io.FileOutputStream.open(FileOutputStream.java:293)
at java.base/java.io.FileOutputStream.<init>(FileOutputStream.java:235)
at java.base/java.io.FileOutputStream.<init>(FileOutputStream.java:123)
at java.base/sun.security.tools.keytool.Main.doCommands(Main.java:1375)
at java.base/sun.security.tools.keytool.Main.run(Main.java:423)
at java.base/sun.security.tools.keytool.Main.main(Main.java:416)
So, you put a different location to generate the release-key.jks, for example:
keytool -genkey -v -keystore C:\Users\andres\release-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias key-alias
And now, it should successfully generate the file in the specified location.
The next step is to generate the signed apk. Before that, you should update the namespace of your app, since it cannot say example as part of the name. To do this, you can use the following package:
https://pub.dev/packages/change_app_package_name
There are many errors that can occur if you do not set the parameters correctly in Android Studio, such as when you run the project on Android it ends up in a loop or when generating the signed apk, for example, it indicates that you made a mistake when defining the alias:
e: C:/Users/andre/.gradle/caches/transforms-3/c1e3cec58f97b65c118bb2f68fab94a8/transformed/jetified-core-ktx-1.10.1/jars/classes.jar!/META-INF/core-ktx_release.kotlin_module: Module was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.8.0, expected version is 1.6.0.
e: C:/Users/andre/.gradle/caches/transforms-3/a3842a17fe7307c5bcdac869078c73a0/transformed/core-1.10.1/jars/classes.jar!/META-INF/core_release.kotlin_module: Module was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.8.0, expected version is 1.6.0.
e: C:/Users/andre/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib/1.8.22/636bf8b320e7627482771bbac9ed7246773c02bd/kotlin-stdlib-1.8.22.jar!/META-INF/kotlin-stdlib-jdk7.kotlin_module: Module was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.8.0, expected version is 1.6.0.
e: C:/Users/andre/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib/1.8.22/636bf8b320e7627482771bbac9ed7246773c02bd/kotlin-stdlib-1.8.22.jar!/META-INF/kotlin-stdlib.kotlin_module: Module was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.8.0, expected version is 1.6.0.
e: C:/Users/andre/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib/1.8.22/636bf8b320e7627482771bbac9ed7246773c02bd/kotlin-stdlib-1.8.22.jar!/META-INF/kotlin-stdlib-jdk8.kotlin_module: Module was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.8.0, expected version is 1.6.0.
e: C:/Users/andre/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-common/1.8.22/1a8e3601703ae14bb58757ea6b2d8e8e5935a586/kotlin-stdlib-common-1.8.22.jar!/META-INF/kotlin-stdlib-common.kotlin_module: Module was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.8.0, expected version is 1.6.0.
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':app:packageRelease'.
> A failure occurred while executing com.android.build.gradle.tasks.PackageAndroidArtifact$IncrementalSplitterRunnable
> com.android.ide.common.signing.KeytoolException: Failed to read key upload from store "C:\Users\andre\flutter\release-key-flutter.jks": No key with alias 'upload' found in keystore C:\Users\andre\flutter\release-key-flutter.jks
* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 11s
Running Gradle task 'assembleRelease'... 12,5s
That is to say:
key.properties
storePassword=your_keystore_password
keyPassword=your_key_password
keyAlias=my-key-alias
storeFile=release-key.jks
Which obviously must correspond to the alias specified when generating the keystore.
Another common error is if the app requires an internet connection to work, in AndroidManifest.xml, you must leave the permissions:
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
Since when you open it, you would see that all the data that was brought from the internet would not load.
Finally, the app will be generated in your project:
C:\Users\andre\OneDrive\Escritorio\proyectos\flutter\desarrollolibre\build\app\outputs\flutter-apk
Develop with Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter