Reputation: 11802
I'd like to save my keystore outside the project directory. I don't want to store filepaths inside the repository so I delegated the values to appropriate gradle variables in ~/.gradle/gradle.properties
I can't get gradle to accept an absolute path like:
/Users/username/.gradle/keystores/project/release.key
or
~/.gradle/keystores/project/release.key
I tried:
storeFile file(RELEASE_STORE_FILE)
and
storeFile new File(RELEASE_STORE_FILE)
none of them seems to work, however.
How can I pass an absolute path value to the keystore file through RELEASE_STORE_FILE
variable?
android {
signingConfigs {
release {
storeFile file(RELEASE_STORE_FILE)
storePassword RELEASE_STORE_PASS
keyAlias RELEASE_ALIAS
keyPassword RELEASE_KEY_PASS
}
}
}
and the ~/.gradle/gradle.properties
file:
RELEASE_STORE_FILE=/Users/username/.gradle/keystores/project/release.key
RELEASE_STORE_PASS=******
RELEASE_ALIAS=******
RELEASE_KEY_PASS=******
In short: I want to pass an absolute path value to gradle.
Upvotes: 11
Views: 14204
Reputation: 21
By chance I ended up implementing something similar to Mikhail Avdeev's answer, but in order to provide an example for Kotlin based buildscripts, too, here's my solution anyway:
Add id("com.sidneysimmons.gradle-plugin-external-properties") version "2.0.1" apply false
to your project-level build.gradle.kts (plugin source here)
For your module-level build.gradle.kts, use this:
import com.android.build.api.dsl.ApkSigningConfig
plugins {
// [... all your other plugins]
id("com.sidneysimmons.gradle-plugin-external-properties")
}
externalProperties {
propertiesFileResolver(file("signing.properties"))
}
android {
signingConfigs {
named("debug") {
if (checkExternalSigningConfig()) {
applyExternalSigningConfig()
} else {
// Use the default debug keystore if no configuration has been specified
defaultConfig.signingConfig
}
}
create("release") {
if (checkExternalSigningConfig()) {
applyExternalSigningConfig()
// automatically add the signingConfig to your
// build config if the configuration file is valid
android.buildTypes.getByName("release").signingConfig = this
}
}
}
}
fun ApkSigningConfig.checkExternalSigningConfig(): Boolean {
return props.exists("$name.keyStore") &&
file(props.get("$name.keyStore")).exists() &&
props.exists("$name.storePassword") &&
props.exists("$name.keyAlias") &&
props.exists("$name.keyPassword")
}
fun ApkSigningConfig.applyExternalSigningConfig() {
storeFile = file(props.get("$name.keyStore"))
storePassword = props.get("$name.storePassword")
keyAlias = props.get("$name.keyAlias")
keyPassword = props.get("$name.keyPassword")
}
Place a file called signing.properties
in your module directory (app
or whatever), where you can happily use absolute paths (Windows example in this case):
debug.keyStore=\\C:\\Path\\to\\keystore\\file
debug.storePassword=your_password
debug.keyAlias=your_keyAlias
debug.keyPassword=your_password
release.keyStore=\\C:\\Path\\to\\keystore\\file
release.storePassword=your_password
release.keyAlias=your_keyAlias
release.keyPassword=your_password
Upvotes: 0
Reputation: 2599
I use this on a Mac
signingConfigs { debug { storeFile file(System.env.HOME + '/.android/debug.keystore') storePassword 'android' keyAlias 'androiddebugkey' keyPassword 'android' } }
Upvotes: 1
Reputation: 1218
In my case (macOS) with my local_store.keystore
saved in Users/<username>
and the path to the keystore configured in the gradle.properties
file as:
RELEASE_STORE_FILE=Users/<username>/local_store.keystore
I was getting the following error:
> Keystore file
'/Users/<username>/Documents/MyProject/android/app/Users/<username>/local_store.keystore'
not found for signing config 'release'.
so the path set in the gradle.properties
was added to the relative path of the build.gradle
file (notice duplicated /Users/<username>
).
I fixed that by specifying the path to the keystore with a few ../
to point to the right location in the Users/<username>
folder.
This is how it should look in the gradle.properties
file:
RELEASE_STORE_FILE=../../../../../local_store.keystore
No modifications are required to the build.gradle
file.
Upvotes: 1
Reputation: 41
Found solution there: https://gist.github.com/gabrielemariotti/6856974
Briefly, you should parse file that contains path to keystore properly. Modify yours module's gradle with next lines. First, this is how to create signingConfigs based on keystore.properties file content:
signingConfigs
{
release
{
def Properties props = new Properties()
def propFile = new File('path/to/your/keystore.properties') //absolute path to keystore.properties
if (propFile.canRead())
{
props.load(new FileInputStream(propFile))
if (props != null && props.containsKey('STORE_FILE') && props.containsKey('STORE_PASSWORD') &&
props.containsKey('KEY_ALIAS') && props.containsKey('KEY_PASSWORD'))
{
android.signingConfigs.release.storeFile = file(props['STORE_FILE'])
android.signingConfigs.release.storePassword = props['STORE_PASSWORD']
android.signingConfigs.release.keyAlias = props['KEY_ALIAS']
android.signingConfigs.release.keyPassword = props['KEY_PASSWORD']
}
else
{
println 'keystore.properties found but some entries are missing'
android.buildTypes.release.signingConfig = null
}
}
else
{
println 'keystore.properties not found'
android.buildTypes.release.signingConfig = null
}
}
}
And then add signingConfig to yours release buildType:
buildTypes
{
...
release
{
...
signingConfig signingConfigs.release
}
}
Example of keystore.properties file for this solution:
STORE_FILE=absolute//path//to//store
STORE_PASSWORD=yourPass
KEY_PASSWORD=keysPass
KEY_ALIAS=aliasName
This has worked for me (Android Studio 3.0.1, Gradle 4.1, Windows 10).
Upvotes: 4
Reputation: 1413
I got around this by using a symlink
Create symlink keystore.lnk
in the app module
ln -s [path-to-keystore] keystore.lnk
Then use keystore.lnk
in gradle.properties
RELEASE_STORE_FILE=keystore.lnk (don't use quotes)
Now your gradle instructions will work.
Upvotes: 3
Reputation: 11802
I ended up using an interesting solution from this site.
The idea is to keep variables in a separate folder which is stored on a remote repository.
In ~/.gradle/gradle.properties
file you put:
Keys.repo=/Users/username/.signing
where Keys.repo
is the local path to your remote repository.
Later on in /Users/username/.signing/YourProjectName.properties
you have:
RELEASE_STORE_FILE=/YourProjectName/release.keystore //in fact it's a relative path
RELEASE_STORE_PASS=xxxxx
RELEASE_ALIAS=xxxxx
RELEASE_KEY_PASS=xxxxx
You need to store release.keystore
file in /Users/username/.signing/YourProjectName/release.keystore
path
The configuration is used in the following way:
android {
signingConfigs {
debug { /* no changes - usual config style */ }
release {
if (project.hasProperty("Keys.repo")) {
def projectPropsFile = file(project.property("Keys.repo") + "/YourProjectName.properties")
if (projectPropsFile.exists()) {
Properties props = new Properties()
props.load(new FileInputStream(projectPropsFile))
storeFile file(file(project.property("Keys.repo") + props['RELEASE_STORE_FILE']))
storePassword props['RELEASE_STORE_PASS']
keyAlias props['RELEASE_ALIAS']
keyPassword props['RELEASE_KEY_PASS']
}
} else {
println "======================================================="
println "[ERROR] - Please configure release-compilation environment - e.g. in ~/.signing directory"
println "======================================================="
}
}
}
}
Upvotes: 3