We were unable to load Disqus. If you are a moderator please see our troubleshooting guide.
Thank you.
This works fine, but what if I have 2 apps set inside the gradle file, each with a different package name and each needs to use a different key-alias?
I asked it here and I thought it works fine, but it actually produced me APK files that use debug variant instead of release variant:
https://stackoverflow.com/a...
Hi please can you help me on how to fix this error? the build.gradle is below
Gradle sync failed: You should define KEYSTORE_PASSWORD, KEYSTORE_ALIAS and KEY_PASSWORD in gradle.properties.groovy.lang.MissingPropertyException: Could not get unknown property 'KEYSTORE_PASSWORD' for SigningConfig_Decorated{name=release, storeFile=C:\Users\user\Downloads\umar\shopping\app\openshopKeystore.jks, storePassword=null, keyAlias=null, keyPassword=null, storeType=C:\Users\user\Downloads\umar\shopping\app\openshopKeystore.jks, v1SigningEnabled=true, v2SigningEnabled=true} of type com.android.build.gradle.internal.dsl.SigningConfig.
Thanks for this post! One thing I don't understand - why do we need:
if(project.hasProperty("MyProject.signing")
&& new File(project.property("MyProject.signing") + ".gradle").exists()) {
In my opinion it is better to remove the condition and let the gradle raise error when there is no property or file.
this is a late response but for anything who comes across this later...
it's a good idea if your project is git synced for 2 scenarios:
1. someone gains unauthorized access to the git project. You don't want them being able to mess with your app in the play store
2. only certain people on the team are allowed to generate the final signed apks for the play store.
Hi Tim, thanks for the tutorial. I have a question about fetching file via https, would it be possible? Sorry, if this question comes as a silly question. I have been on android studio for a little while now but just start to learn all of this last night, so I am really new to all these concepts.
Hi KB, do you mean fetching config files (with e.g. passwords and such) from the internet? You can extract and apply parts of the build file via apply from: 'foo'. "foo" doesn't have to be a local path, you could also apply files via HTTP as follows:
apply from: 'https://example.com/repository/base.gradle
But this comes fro the cost of your build not working anymore without a network connection. There is a Gradle caching plugin out there, that allows using HTTP and have a working cache.
In general: The build.gradle file is "just" a Groovy script executed. So you can use any Groovy magic you want to do in it what you want. And since Groovy is a near superset of Java (and you are not familiar with Groovy enough) you can use whatever Java you want in it :-)
Thanks Tim, I think I get it. Just for my curiosity, why do the creators of groovy make it very flexible? I feel if a mistake makes to the program, it will be hard to debug. Also Is there any tool do you use to debug groovy (gradle in this case)? Really appreciate for your help and advice.
I think you mean the creators of Gradle made it very flexible (since Groovy is just a programming language, and as flexible as a programming language usually is). For Gradle: it's always the trade-off in any build system between configuration vs. coding.
Maven for example is pure configuration, but that has the drawback of you require a plugin (in worst case write it yourself) for any simple task, that is not part of the core configuration. In Gradle if it's just small you can just write the stuff as Groovy code inside your build script, and if you need it more often or it gets larger just exclude it in a plugin when needed. E.g. we began reading out the version number of our software from Git tags, and just wrote the 5-10 lines of code needed for this into the build.gradle. Once we used it in several project, we just extracted it into a plugin: gradle-git-version and now it's a one liner to include it in any new project. So it's always the balance between flexibility vs. static configuration. Both have their advantages and disadvantages.
Since Groovy just runs in the JVM, you can actually use the regular debugging options there. If you use the Gradle wrapper script - and you should do so - you will find DEFAULT_JVM_OPTS="" in one of the first lines, where you can add the Java debugging options and attach any debugger. You should e.g. be able to use IntelliJ IDEA debugger, to attach to this (and it also prints you out the parameters you need to add there). I've never actually tried to debug a Groovy script, so this is more a "should work" than "does work".
Thanks Tim for your explanation.
Hello Tim,
I am reading apk version code from properties file and increment it on every build. But I want to to inc it only on time of signing. Can yo please help me in that? Following is my code:
android {
compileSdkVersion 23
buildToolsVersion "23.0.3"
def versionPropsFile = file('version.properties')
if (versionPropsFile.canRead()) {
def Properties versionProps = new Properties()
versionProps.load(new FileInputStream(versionPropsFile))
def code = versionProps['build.version'].toInteger() + 1
versionProps['build.version']=code.toString()
versionProps.store(versionPropsFile.newWriter(), null)
defaultConfig {
applicationId "com.test"
multiDexEnabled true
versionCode code
versionName versionProps['product.version']
minSdkVersion 18
targetSdkVersion 23
}
}
else {
throw new GradleException("Could not read version.properties!")
}
......
}
Hi, you would need to do the read out all the time. Just move the increasing of the version number to a separate block, that will only be executed when signing. (How to execute code only when a specific task is executed, you can see here: https://www.timroes.de/2014.... So in pseudo code it might look like that:
def readVersion = {
// what you already did to read it out
return version
}
android {
defaultConfig {
versionCode readVersion()
}
}
// To check whether a specific task will be executed, we need to wait for the taskGraph to be ready
gradle.taskGraph.whenReady { taskGraph ->
if(taskGraph.hasTask(':app:assembleRelease')) {
// If the assembleRelease task is executed (or use some task else you require)
// Do here the increasing of the version number and write it back to file
project.android.defaultConfig.versionCode newVersionCode
}
}
When I generate sign apk it never comes in if(taskGraph.hasTask(':app:assembleRelease'))
Is your task really called like that? Perhaps your submodule isn't named app ? You can use `./gradlew tasks` to list all tasks.
Thank you, Solved. http://stackoverflow.com/qu...
In Windows I'm using Android Studio, for me MyProject.properties is in "C:\Users\Username\.gradle\myproject.properties". How do I give this? If I give with single/double quotes it gives me error unable to find properties for MyProject. As you have mentioned instead of / if I try to use \\ it gives me error Unexpected Symbol. How to resolve this?
Hey there, hope you see this, or at least anyone else in this situation.
For Windows, you still use Windows paths - but you actually want to prepend the folder paths with '/'.
So, for the path given above, it should read:
"C:/\Users/\Username/\.gradle/\myproject.properties"
Hi Tim,
As far as I understood, you keep the important data, like password or keystores, in your own machine. But what if your are working in Circle Integration environment, building the project in a Virtual Machine in a server ? You will need to keep your data there in the Virtual Machine as well.
And if you are using a third party continuous integration server, what would be the most secure way to keep your important files safe.
Thanks.
Hei,
yeah the solution only shows how to work with this kind of stuff on a local developer machine.
For usage of keys on CI servers I haven't found the perfect solution yet for me.
You could just upload and store the key on the jenkins machine (or vm) and reference it there.
If you mean with third party CI server, a server owned by someone else, I doubt that there is a really secure way, since
you need to upload the key at some time to the server.
I am common to use own jenkins instances. If these are provisioned by any common tool (puppet and such) you can use this
to also place the keys on them. But you will still need to store them somewhere where the provision tools can reach them.
As mentioned, nothing of these solutions made me really happy, and unfortunately I haven't build up any ideas about 3rd part
build servers, that could be of any help in that situation.
Please feel free to share any solutions you will find or work on with the world.
Cheers
Tim
It is possible to take any existing Android Studio gradle project and build/sign it from the command line without editing any files. This makes it very nice for storing your project in version control while keeping your keys and passwords separate from your build.gradle file:
./gradlew assembleRelease -Pandroid.injected.signing.store.file=$KEYFILE -Pandroid.injected.signing.store.password=$STORE_PASSWORD -Pandroid.injected.signing.key.alias=$KEY_ALIAS -Pandroid.injected.signing.key.password=$KEY_PASSWORD
Worked a treat. Took a while to get it to work, though. The problem I was having was thinking that the project name had to be the same as the .properties file and getting all the naming of properties and files right so it's referencing everything correctly. Figured it out now. I went for option 3 in the end after trying to make option 1 work.
Can you specify that the DSL line needs to go inside the android {...} part of the gradle file, not at the end?
Also, if you're on Windows, use double backslashes \\ instead of a forward slash '/' for the path.
I am not sure what you mean by DSL line :-) But if you meant the missing android { } around the signingConfig block, I added that and added a sentence about the windows pathes in the top.
Hey,
I'm getting this exception on build in myproject.gradle:
" Invalid variable name. Must start with a letter but was: “MyProject
. At [4:36] @ line 4, column 36.
storeFile file(project.property(“MyProject.signing”) + “.keystore”)
Pretty confused. Any ideas?
Thanks!
What about proguard. Do you use that in your gradle configs?
I haven't tested ProGuard yet with Gradle, but ProGuard itself has a explanation in their docs on how to integrate it with Gradle: http://proguard.sourceforge...
What about the keyAlias and keyPassword values? How should those be set in myproject.properties?
I guess you are talking about the 3rd option, where you store plain text files in a properties file? In that case you can just write:
keyAlias=myKeyAlias
keyPassword=password
in your myproject.properties file, and load them via the Properties object (as shown in the last code snippet).
You don't want to include the quotes in the gradle.properties file as it will use them in the path, which will cause the file to be not found. At least that's what happened to me with OS X.
Thanks. I changed it.
And how do you use this configs to generate apk ? If i do "Build-> Generate Signed apk" from menu, i guess it will ask to enter keystore file and password manually. Does this valid for ./gradlew assembleRelease command ??