1

Per an Android Gradle build environment:

I currently read my Version Code and Version Name from a local version.properties file via a "readVersions" gradle task. I am in the process of adding flavors to my app. These flavors would need different versions. So I was thinking of putting two different version.properties files inside of flavor specific directories (e.g. one/version.properties, two/version.properties) next to the flavor specific "res" and "src" directories.

I have a readVersions task:

task readVersions() {
    def Properties versionProps = new Properties()
    def versionPropsFile = file('version.properties')
    if (versionPropsFile.exists())
        versionProps.load(new FileInputStream(versionPropsFile))
    def v_code = (versionProps['VERSION_CODE'] ?: "0").toInteger()
    def v_name = versionProps['VERSION_NAME']

    // Set
    versionCode v_code
    versionName v_name
}

project.afterEvaluate {
    preBuild.dependsOn readVersions
}

I would like to have a new readVersions task that incorporates the flavor so that I can use it in accessing the "version.properties" file within the "flavor" directory.

I have tried:

android.productFlavors.all{ flavor ->
    task ("${flavor.name}_readVersions")<<{
    def versionPropsFile = file(flavor.name+'/version.properties')
...

But then I don't know how to get only the active flavor's task to run during the "preBuild" step.

Conceptually I want this:

project.afterEvaluate {
    preBuild.dependsOn ${active_flavor}_readVersions
}

To those who recommend reorganizing and finding simpler solutions. My build process currently has other dependencies on these version.properties files. I could just define the version code and version name in two places (e.g. inside the "flavor" as well as within a flavor's version.properties file, but I really want DRY configs)

FishStix
  • 4,994
  • 9
  • 38
  • 53
  • There is no "active flavor". Your `build.gradle` file does not build your app. Your `build.gradle` file builds an object model of *how* to build your app. Builds work off of the object model. You need to `dependsOn` for both flavors, where appropriate flavor-specific tasks depend on your custom flavor-specific tasks. – CommonsWare Apr 01 '16 at 21:17
  • Yes, I understand this. That's why I tried to emphasize that portion within my "conceptually" descriptor. Do you understand what I'm trying to do? Do you know how to build an object model that achieves what I'm trying to do? I can try to define my aim further if not. – FishStix Apr 01 '16 at 21:19
  • I am hesitant to create a bunch of custom "dependsOn" for flavors, where appropriate flavor-specific tasks depend on your custom flavor-specific tasks. What if I end up with 10 or 20 flavors? I just want to grab the local versionCode/Name from the ${flavor.name}/version.properties file. Do I really need 20 custom tasks to achieve this? – FishStix Apr 01 '16 at 21:23
  • "Do I really need 20 custom tasks to achieve this?" -- yes. You don't necessarily need 20 hand-generated custom tasks to achieve this, though. You seem to be on the right track with `productFlavors.all`, though I think that may need to be `buildVariants.all`. But then you start talking about "active flavor's task" and go off the rails. In your loop, get the flavor-specific task that you want to say depends upon this newly-generated task. I do something along these lines in [this `build.gradle` file](https://github.com/commonsguy/cwac-provider/blob/master/provider/build.gradle). – CommonsWare Apr 01 '16 at 21:32
  • Now, my case is somewhat simpler, in that I am just configuring an instance of a task based off the `Jar` task, not crafting something out of whole cloth. That's why I am posting comments, as I don't have a complete answer for you. Perhaps the solution is for you to be defining a "generic" task that handles an arbitrary flavor, then in the loop set up flavor-specific instances of that generic task and set up the `dependsOn`. – CommonsWare Apr 01 '16 at 21:34

1 Answers1

0

I split my "readVersions" task into "readVersionName" and "readVersionCode"

def getVersionName(flavor) {
    return getVersion(flavor, "VERSION_NAME", false)
}
def getVersionCode(flavor) {
    return getVersion(flavor, "VERSION_CODE", true)
}
def getVersion(flavor, type, intRequired) {
    // READ
    def Properties versionProps = new Properties()
    def versionPropsFile = file("${flavor}/version.properties")
    if (versionPropsFile.exists())
        versionProps.load(new FileInputStream(versionPropsFile))
    def value = versionProps["${type}"]
    return intRequired ? value.toInteger() : value
}

Then I run them inside each flavor's definition:

productFlavors {
    one {
        versionName getVersionName("one")
        versionCode getVersionCode("one")
    }
    two {
        versionName getVersionName("two")
        versionCode getVersionCode("two")
    }

One thing to note, my previous attempt was trying to incorporate the versionName and versionCode setting into dependencies on the preBuild task. It seems like by this time in the process, 'versionName' can no longer be set properly. My tasks were not setting it from the correct flavor, which is why I came up with another solution, but reading it after setting it was always 'null'.

Thank you CommonsWare for the comments and suggestions.

FishStix
  • 4,994
  • 9
  • 38
  • 53