5

I have an android application that has the following product flavors:

productFlavors {
    local {

    }

    development {


    }

    production {

    }
}

then have the following at the bottom of my build.grade:

File crashlyticsProperties = new File("${project.projectDir.absolutePath}/fabric.properties")
android.applicationVariants.all { variant ->
    def variantSuffix = variant.name.capitalize()
    def generateResourcesTask = project.tasks.getByName("fabricGenerateResources${variantSuffix}")
    def generatePropertiesTask = task("fabricGenerateProperties${variantSuffix}") << {
        Properties properties = new Properties()
        properties.put("apiSecret", WHAT_GOES_HERE)
        properties.put("apiKey", WHAT_GOES_HERE)
        PropertiesUtils.injectPropertyInFile(crashlyticsProperties, properties, "")
    }
    generateResourcesTask.dependsOn generatePropertiesTask
}

I'm trying to set the api secret/key for crashlytics but I need to be able to set these depending on what product flavor I'm building.

properties.put("apiSecret", WHAT_GOES_HERE)
properties.put("apiKey", WHAT_GOES_HERE)

How can I set/get these variables?

Update #1

I've added the following to my build.gradle

productFlavors {
    local {
        buildConfigField "String", "CRASHLYTICS_API_SECRET", "1234"
        buildConfigField "String", "CRASHLYTICS_API_KEY", "1234"
    }

    development {
        buildConfigField "String", "CRASHLYTICS_API_SECRET", "1234"
        buildConfigField "String", "CRASHLYTICS_API_KEY", "1234"
    }

    production {
        buildConfigField "String", "CRASHLYTICS_API_SECRET", "1234"
        buildConfigField "String", "CRASHLYTICS_API_KEY", "1234"
    }
}

Then at the bottom of the build.gradle file I have:

File crashlyticsProperties = new File("${project.projectDir.absolutePath}/fabric.properties")
android.applicationVariants.all { variant ->
    def variantSuffix = variant.name.capitalize()
    def generateResourcesTask = project.tasks.getByName("fabricGenerateResources${variantSuffix}")
    def generatePropertiesTask = task("fabricGenerateProperties${variantSuffix}") << {
        Properties properties = new Properties()
        println "...copying apiSecret for ${variant.name}"
        properties.put("apiSecret", BuildConfig.CRASHLYTICS_API_SECRET)
        println "...copying apiKey for ${variant.name}"
        properties.put("apiKey", BuildConfig.CRASHLYTICS_API_KEY)
        PropertiesUtils.injectPropertyInFile(crashlyticsProperties, properties, "")
    }
    generateResourcesTask.dependsOn generatePropertiesTask
}

This however does not compile and gives me:

Error:(334, 1) Execution failed for task ':app:fabricGeneratePropertiesDevelopmentDebug'. Could not find property 'BuildConfig' on task ':app:fabricGeneratePropertiesDevelopmentDebug'.

Kyle Decot
  • 20,715
  • 39
  • 142
  • 263
  • https://stackoverflow.com/questions/26290067/crashlytics-not-finding-api-key-in-crashlytics-properties-at-runtime – Adeel Turk Mar 06 '18 at 14:34
  • I would not recommend using product flavors for that, since your base code between the different environments won't change that much, you should be using buildTypes. Flavors are better used when you want to have a demo version and a paid version for example, where you want to have different activities and so.. – emirua Mar 08 '18 at 23:50

4 Answers4

3

For this error:

Error:(334, 1) Execution failed for task ':app:fabricGeneratePropertiesDevelopmentDebug'. Could not find property 'BuildConfig' on task ':app:fabricGeneratePropertiesDevelopmentDebug'.

Use a different construction, eg:

variant.mergedFlavor.buildConfigFields["CRASHLYTICS_API_SECRET"].value

Of course this solution expects, that such BuildConfig field is defined. If you expect field would not exist, make sure to check if present first.

EDIT:

If you'd like a solution described in your question:

File crashlyticsProperties = new File("${project.projectDir.absolutePath}/fabric.properties")
android.applicationVariants.all { variant ->
    def variantSuffix = variant.name.capitalize()
    def generateResourcesTask = project.tasks.getByName("fabricGenerateResources${variantSuffix}")
    def generatePropertiesTask = task("fabricGenerateProperties${variantSuffix}") << {
        Properties properties = new Properties()
        println "...copying apiSecret for ${variant.name}"
        properties.put("apiSecret", variant.mergedFlavor.buildConfigFields.get("CRASHLYTICS_API_SECRET").value)
        println "...copying apiKey for ${variant.name}"
        properties.put("apiKey", variant.mergedFlavor.buildConfigFields.get("CRASHLYTICS_API_KEY").value)
        PropertiesUtils.injectPropertyInFile(crashlyticsProperties, properties, "")
    }
    generateResourcesTask.dependsOn generatePropertiesTask
}
R. Zagórski
  • 20,020
  • 5
  • 65
  • 90
  • This is exactly what I was looking for! Thank you for your help. Can I ask how you knew that `variant` had a `mergedFlavor` method on it? Can you point me to the documentation? – Kyle Decot Mar 13 '18 at 20:53
  • Of course, [documentation](https://google.github.io/android-gradle-dsl/current) is under the link – R. Zagórski Mar 14 '18 at 19:03
1

you can have different buildConfigFields for every flavour where you can declare mutiple strings variables and seperate keys for each flavour easily

Like :

local { buildConfigField "String", "KEY", '"abcKey' } 
development { buildConfigField "String", "KEY", '"xyzKey' } 

and use these variables in your java files as follows

properties.put("apiSecret", BuildConfig.KEY)
Adeel Turk
  • 897
  • 8
  • 23
  • This gives me > Error:(334, 1) Execution failed for task ':app:fabricGeneratePropertiesDevelopmentDebug'. > Could not find property 'BuildConfig' on task ':app:fabricGeneratePropertiesDevelopmentDebug'. – Kyle Decot Mar 06 '18 at 14:20
  • could you please add your whole gradle file or at least the code in android tag only – Adeel Turk Mar 06 '18 at 14:26
  • search for BuildConfig.java file in your source and let me know if that file have these keys in there? – Adeel Turk Mar 06 '18 at 14:33
  • I do have that file and the values for crashlytics are there but I think the problem from the error is that I don't have access to `BuildConfig` in that scope. – Kyle Decot Mar 06 '18 at 14:44
1

Easy:

applicationVariants.all { variant ->
    variant.outputs.all { output -> 
        def flavor = variant.productFlavors[0].name.capitalize()

        if (flavor == "Local") {
             buildConfigField "string", "CRASHLYTICS_API_SECRET", "1234"
             buildConfigField "string", "CRASHLYTICS_API_KEY", "5678"
        }

        if (flavor == "Development") {
             buildConfigField "string", "CRASHLYTICS_API_SECRET", "1234"
             buildConfigField "string", "CRASHLYTICS_API_KEY", "5678"
        }

        if (flavor == "Production") {
            buildConfigField "string", "CRASHLYTICS_API_SECRET", "1234"
            buildConfigField "string", "CRASHLYTICS_API_KEY", "5678"
        }
    }
}

Place it under your productFlavors block. You can use it later with BuildConfig.CRASHLYTICS_API_SECRET in your code.

moictab
  • 959
  • 6
  • 27
0

The reason you are getting that error is that BuildConfig is a Java class, not a Gradle class. BuildConfig can only be used from within your other Java classes.

There is however a much easier way of getting a file that has different contents depending on the Gradle flavor.

Consider the usual project structure:

/app
    /src
        /main
            /java
            /res
            /assets
            ...

If you wanted a different "fabric.properties" file per Gradle flavor, you can create a folder for each Gradle flavor under /src (folder name must be same as Gradle flavor name) and save the files within them, like so:

/app
    /src
       /main
            /java
            /res
            /assets
            ...
       /local
           /fabric.properties
       /development
           /fabric.properties
       /production
           /fabric.properties

This works without having to change anything or write any Gradle scripts.

For more details on source sets, read https://developer.android.com/studio/build/build-variants.html#sourcesets

Ovidiu
  • 8,204
  • 34
  • 45