Automatic app signing with Gradle when using git
It's amazing how many convoluted ways there are for doing this. Here is my own way, where I try to adhere to Googles own recommendation. However, their explanation is not fully clear, so I will describe the procedure for Linux in detail.
Description:
The default Google instructions for automatically signing an app
during the build, without keeping the passwords and signature files
in your app development (GIT) path, is rather obscure. Here are the
clarified step-by-step instructions how to do so.
Initial assumptions:
You have an app called "MyApp" in a directory given by the following path:
$HOME/projects/mydev/MyApp
. However, the MyApp directory is used and
controlled with GIT.
Problem
We obviously don't want to have our signature or password files anywhere in
the GIT controlled directory, even if we are very able to use .gitignore
etc, it is still too risky and easy to make a mistake. So we want our keystore and signature files outside.
Solution
We need to do three (3) things:
- Create a password file to be used by Android Studio
- Create signature key file
- Edit the module
build.gradle
file to use (1) and (2).
For this example we name the two files:
keystore.properties
MyApp-release-key.jks
We can put both of these files here:
cd $HOME/projects/mydev/
(1) Create the keystore password file
The first file contain the clear text passwords used in; and paths to the release-key file in (2). Start with filling this out, as it will make a copy paste operation easier for the next step.
cd $HOME/projects/mydev/
Edit keystore.properties
so that it's content is:
storePassword=myStorePassword
keyPassword=mykeyPassword
keyAlias=myKeyAlias
storeFile=myStoreFileLocation
The only tricky part here, is the myStoreFileLocation
. This is the path as seen from the module build.gradle
file during the build. This usually means a path similar and relative to: $HOME/projects/mydev/MyApp/app/build.gradle
. So in order to point to the MyApp-release-key.jks
file, what we need to put here is:
../../../MyApp-release-key.jks
Here, we also chose the "myapp" alias for the key. Then the final file should look:
storePassword=myStorePassword
keyPassword=mykeyPassword
keyAlias=myapp
storeFile=../../../MyApp-release-key.jks
(2) Create the signature file
The second file is automatically generated when you create the signature key.
If you have no other apps and this is your only keystore, then create the file with:
cd $HOME/projects/mydev/
keytool -genkeypair -v -keystore MyApp-release-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias myapp
This will ask you for two passwords and a bunch of info. (Same stuff as in Android Studio.) Now copy/paste your previously chosen passwords.
(3) Edit your module gradle.build
file to use the above
The following parts need to be present in your app/module's Gradle build file. First, add the following lines outside and before your android {}
block.
//def keystorePropertiesFile = rootProject.file("$HOME/.android/keystore.properties")
def keystorePropertiesFile = rootProject.file("../../keystore.properties")
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
Then, inside the android {}
block, add:
android {
...
defaultConfig { ... }
signingConfigs {
release {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile file(keystoreProperties['storeFile'])
storePassword keystoreProperties['storePassword']
}
}
// Tell Gradle to sign your APK
buildTypes {
release {
signingConfig signingConfigs.release
...
}
}
}
Now from shell, you can re-build your app with:
cd $HOME/projects/mydev/MyApp/app/
./gradlew clean build
This should generate a properly signed app that can be used in Google Play.
UPDATE: 2019-04-02
More recent versions of keytool
and something is telling you that you should use a PKCS12 based keyfile instead of the original/default as I use above. They then go on telling you you should convert to the new open PKCS12 format. However, it seem that the Android development tools are not quite ready for this yet, because if you do, you will get the following weird errors:
com.android.ide.common.signing.KeytoolException:
Failed to read key
XXX from store "F:\XXX\XXX.jks": Get Key failed: Given final block not
properly padded. Such issues can arise if a bad key is used during
decryption.
So don't use a converted key!