buildConfigField for multiple BuildTypes / Variants (Flavor)

2,992 views
Skip to first unread message

Daniele Segato

unread,
Nov 12, 2014, 7:14:33 AM11/12/14
to adt...@googlegroups.com
Hi,

I posted a feature request a while ago here:

which describe what I'd like to have.

Since it had no reply I'm now writing here to know if there is some way to achieve a similar result.

Is there a way to write something like this:

buildConfigField "String", "MY_VAR_NAME", getMyVarValue(getCurrentFlavor());

specifically I need the getCurrentFlavor() method so that my function getMyVarValue can do all the switches needed.

any way to achieve this?

how  do you handle that situation?


Thank you,
Daniele

Daniele Segato

unread,
Nov 14, 2014, 3:40:41 AM11/14/14
to adt...@googlegroups.com
I can't believe there's no interest in this function.

Avram Lyon

unread,
Nov 14, 2014, 4:22:36 AM11/14/14
to adt...@googlegroups.com
The flavor names are already put in the BuildConfig by the Android plugin itself, so you generally wouldn't need that.

Avram Lyon
Android wrangler | Scopely, Inc.

Refer The Smartest Person You Know And Pocket $7,000! 


--
You received this message because you are subscribed to the Google Groups "adt-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to adt-dev+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Daniele Segato

unread,
Nov 14, 2014, 4:42:38 AM11/14/14
to adt...@googlegroups.com
That's not the same.

I know I can do the switch Java side but it's a completely different thing.

If I use that to set API Keys etc. I don't want ALL OF THEM to be in the Java file. That will be compiled and packaged with the APK.

I want to set it in the build file and have only 1 of the value in the APK. The one needed by that APK.

Avram Lyon

unread,
Nov 14, 2014, 10:58:45 AM11/14/14
to adt...@googlegroups.com
On Fri, Nov 14, 2014 at 1:42 AM, Daniele Segato <daniele...@gmail.com> wrote:
That's not the same.

I know I can do the switch Java side but it's a completely different thing.

If I use that to set API Keys etc. I don't want ALL OF THEM to be in the Java file. That will be compiled and packaged with the APK.

I want to set it in the build file and have only 1 of the value in the APK. The one needed by that APK.

In that case you can provide flavor-specific Constants.java files in the flavor-specific source sets. So long as you ensure that every flavor combination has such a file present, it'll work. Such an approach won't support merging of constant definitions, of course.

Bryan Herbst

unread,
Nov 14, 2014, 10:59:42 AM11/14/14
to adt...@googlegroups.com
I previously avoided calling buildConfigField multiple times is by hooking into applicationVariants.all like so:
applicationVariants.all { variant ->
    variant.buildType.buildConfigField "String", "NAME", "VALUE"
}

Unfortunately as of version 0.14 of the Gradle plugin variant.buildType is read-only, so this no longer works.

The "correct" solution is to use variant.mergedFlavor.buildConfigField. However, that API doesn't exist yet. Progress for this feature is being tracked in issue 67416.

Daniele Segato

unread,
Nov 14, 2014, 11:31:39 AM11/14/14
to adt...@googlegroups.com
Sure.

Which spread the code everywhere and I have to remember to change  it in every point if I need to.
I also miss the chance to provide a default value.

I appreciate you are helping me, but what I really need is more flexibility on the gradle side so that I can provide all my setting there, in a single place, easily work with default cases, ....

Daniele Segato

unread,
Nov 14, 2014, 11:32:33 AM11/14/14
to adt...@googlegroups.com
Hi Bryan,

thanks for the tip, I'm already following that bug.

I was hoping for some kind of workaround gradle side in the meanwhile or some feedback by a googler :)

Xavier Ducrohet

unread,
Nov 14, 2014, 12:56:23 PM11/14/14
to adt...@googlegroups.com
Doing

applicationVariants.all { variant ->
    variant.buildType.buildConfigField "String", "NAME", "VALUE"
}

is a bad idea. Build types (and flavor objects) are global objects that are shared with all the variants. What you were doing affected all variants. This is why we moved to make the objects read-only. Basically once we start building the variants we shouldn't allow touching these items as it can have unintended consequences.


As for "I can't believe there's no interest in this function." we just are busy with higher priority items right now. We triaged the bug and we'll get to it eventually.

We also accept contributions, though we should figure out a design ahead of time as there are some details about how variants are created from both build type and flavor and how properties are handled when they exist in both the build type and the flavor (which is what https://code.google.com/p/android/issues/detail?id=64094 has to handle)
--
Xavier Ducrohet
Android SDK Tech Lead
Google Inc.
http://developer.android.com | http://tools.android.com

Please do not send me questions directly. Thanks!

Daniele Segato

unread,
Nov 15, 2014, 1:47:02 AM11/15/14
to adt...@googlegroups.com
Hi Xavier,

thank you for your reply.

I wasn't addressing you guys when I said "I can't believe there's no interest in this function." I was referring to the fact that no one was replying my post. :)

I understand there are more urgent thing but I was hoping in some kind of workaround to achieve what I need while waiting for an official feature implementation.


but felt like this kind of discussion was OT in the bug report.


It is good news that now I can override values in the build type. Can I also override them in variants from the default?
It would be good to be able to SELECTIVELY override, meaning that the build type should know the variant being build and be able to adapt.

This is something missing completely, I figure it should work as android values:

flavor-buildtype

free-debug
free-release
pay-debug
pay-release

to address the specific combination both in the build file and in the directory structure...

but I'm drifting away from my original request that was just: how do I obtain the "current" flavor to assign buildConfig and resConfig values in the gradle build file?

Thanks.
Daniele

Mark Murphy

unread,
Nov 15, 2014, 7:23:03 AM11/15/14
to adt...@googlegroups.com
On Sat, Nov 15, 2014, at 01:47, Daniele Segato wrote:
> but I'm drifting away from my original request that was just: how do I
> obtain the "current" flavor to assign buildConfig and resConfig values in
> the gradle build file?

There is no "current flavor", outside of your own iteration over build
variants, as has been previously discussed in this thread.

--
Mark Murphy (a Commons Guy)
http://commonsware.com | http://github.com/commonsguy
http://commonsware.com/blog | http://twitter.com/commonsguy

_The Busy Coder's Guide to Android Development_ Version 6.1: Wear?
There!

Daniele Segato

unread,
Nov 15, 2014, 12:34:09 PM11/15/14
to adt...@googlegroups.com
Meaning theres no way to do what I want yet?

Mark Murphy

unread,
Nov 15, 2014, 12:49:18 PM11/15/14
to adt...@googlegroups.com
On Sat, Nov 15, 2014, at 12:34, Daniele Segato wrote:
> Meaning theres no way to do what I want yet?

If by "what I want" you mean "obtain the 'current' flavor", then no,
there is no way to do what you want, other than by iterating yourself
over build variants.

The only time there is a "current" anything is inside a task. Tasks are
things executed when we actually do the build. Stuff like productFlavors
{} and buildTypes{} are more along the lines of data structures, where
any Groovy code is executed when the script is read in.

Now, you can certainly define your own tasks, and those tasks can be
specific per build variant. You can set up those tasks to depend upon
some other task, and (presumably) you can configure other built-in tasks
to depend upon yours. Whether you can affect buildConfigField this way
and accomplish your aims, I cannot say. And how well this will hold up
over time, as Gradle for Android evolves, I cannot say.

Daniele Segato

unread,
Nov 15, 2014, 1:15:16 PM11/15/14
to adt...@googlegroups.com
Thank you Mark.

What I want is just a way to define buildField values more flexible choosing the value by flavor / build type.

I want to be able to set those values differently for every combination of flavor and build type, possibly setting a default if I do not want to override.

The reason I want this are 3:
1. having to set those value over and over again for each variant is tedious and create lot of boilerplate code
2. it is not straightforward to me how defaultConfig, variant config and build type config relate with each other, if I set the same variable as build config in all of them which is applied? the variant one? the build one?
3. I don't know how to have 4 different value for the combo free+debug, free+release, pay+debug, pay+release (to simplify I just used 2 variant and 2 build types as an example)

Your message helped me understand better how gradle works, I still didn't get it very well.
Now I understand all those setting are in evaluated in a phase that do not yet have anything to do with the actual compile of a single variant. And the code they contains is executed regardless of which variant I build.
But I still don't have any idea on how to solve the 3 things I wrote about above.

Thanks,
Daniele

Xavier Ducrohet

unread,
Nov 15, 2014, 4:23:01 PM11/15/14
to adt...@googlegroups.com
1. I'n not sure how a single buildConfigField is boiler plate.

2. the priority order if explained in the guide and applies to everything (resources, manifest overlays)
It's Build Type > Flavors > default Config.

So if you set the same buildConfigField in all 3, the build type will win, always

3. This is not currently supported. You cannot have per-variant values. We take a combination of build type, flavors, defaultconfig and take the highest priority one. It's something we want to fix but no ETA.


--
You received this message because you are subscribed to the Google Groups "adt-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to adt-dev+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Daniele Segato

unread,
Nov 16, 2014, 4:32:40 AM11/16/14
to adt...@googlegroups.com


On Saturday, November 15, 2014 10:23:01 PM UTC+1, Xavier Ducrohet wrote:
1. I'n not sure how a single buildConfigField is boiler plate.

It's not the single buildConfigField a boilerplate.

When you have many parameter to inject, with different values per variants you end up with many buildConfigField.

Each have the same data type and key. Meaning you duplicate your key on multiple properties and your values spread across the build file in different places. If you edit something you have to remember to edit everywhere.
 

2. the priority order if explained in the guide and applies to everything (resources, manifest overlays)
It's Build Type > Flavors > default Config.

So if you set the same buildConfigField in all 3, the build type will win, always

oh, I see. sorry I missed this in the guide. Thanks.
 

3. This is not currently supported. You cannot have per-variant values. We take a combination of build type, flavors, defaultconfig and take the highest priority one. It's something we want to fix but no ETA.

That's the main issue.
At least now I know it is not possible yet.

Thank you very much for your replies and time.
Daniele
 


On Sat, Nov 15, 2014 at 10:15 AM, Daniele Segato <daniele...@gmail.com> wrote:
Thank you Mark.

What I want is just a way to define buildField values more flexible choosing the value by flavor / build type.

I want to be able to set those values differently for every combination of flavor and build type, possibly setting a default if I do not want to override.

The reason I want this are 3:
1. having to set those value over and over again for each variant is tedious and create lot of boilerplate code
2. it is not straightforward to me how defaultConfig, variant config and build type config relate with each other, if I set the same variable as build config in all of them which is applied? the variant one? the build one?
3. I don't know how to have 4 different value for the combo free+debug, free+release, pay+debug, pay+release (to simplify I just used 2 variant and 2 build types as an example)

Your message helped me understand better how gradle works, I still didn't get it very well.
Now I understand all those setting are in evaluated in a phase that do not yet have anything to do with the actual compile of a single variant. And the code they contains is executed regardless of which variant I build.
But I still don't have any idea on how to solve the 3 things I wrote about above.

Thanks,
Daniele


Xavier Ducrohet

unread,
Nov 16, 2014, 1:58:11 PM11/16/14
to adt...@googlegroups.com
On Sun, Nov 16, 2014 at 1:32 AM, Daniele Segato <daniele...@gmail.com> wrote:


On Saturday, November 15, 2014 10:23:01 PM UTC+1, Xavier Ducrohet wrote:
1. I'n not sure how a single buildConfigField is boiler plate.

It's not the single buildConfigField a boilerplate.

When you have many parameter to inject, with different values per variants you end up with many buildConfigField.

Each have the same data type and key. Meaning you duplicate your key on multiple properties and your values spread across the build file in different places. If you edit something you have to remember to edit everywhere.

You can create local variables in your build script and uses this to synchronize the type and name of the resources.
It's not as pretty, or object-oriented I suppose, as what you describe in https://code.google.com/p/android/issues/detail?id=73396 but it's good enough for 1.0
 

2. the priority order if explained in the guide and applies to everything (resources, manifest overlays)
It's Build Type > Flavors > default Config.

So if you set the same buildConfigField in all 3, the build type will win, always

oh, I see. sorry I missed this in the guide. Thanks.
 

3. This is not currently supported. You cannot have per-variant values. We take a combination of build type, flavors, defaultconfig and take the highest priority one. It's something we want to fix but no ETA.

That's the main issue.
At least now I know it is not possible yet.

Thank you very much for your replies and time.
Daniele

It'll be possible in the next version of the plugin to add per-variant buildConfig and resValues:

android.applicationVariants.all { variant ->
   variant.buildConfigField "type", "name", "value"
   variant.resValue "type", "name", "value"

These ones will obviously have a higher priority than the ones set from the build type/product flavor/default config.
 


On Sat, Nov 15, 2014 at 10:15 AM, Daniele Segato <daniele...@gmail.com> wrote:
Thank you Mark.

What I want is just a way to define buildField values more flexible choosing the value by flavor / build type.

I want to be able to set those values differently for every combination of flavor and build type, possibly setting a default if I do not want to override.

The reason I want this are 3:
1. having to set those value over and over again for each variant is tedious and create lot of boilerplate code
2. it is not straightforward to me how defaultConfig, variant config and build type config relate with each other, if I set the same variable as build config in all of them which is applied? the variant one? the build one?
3. I don't know how to have 4 different value for the combo free+debug, free+release, pay+debug, pay+release (to simplify I just used 2 variant and 2 build types as an example)

Your message helped me understand better how gradle works, I still didn't get it very well.
Now I understand all those setting are in evaluated in a phase that do not yet have anything to do with the actual compile of a single variant. And the code they contains is executed regardless of which variant I build.
But I still don't have any idea on how to solve the 3 things I wrote about above.

Thanks,
Daniele


--
Xavier Ducrohet
Android SDK Tech Lead
Google Inc.
http://developer.android.com | http://tools.android.com

Please do not send me questions directly. Thanks!

--
You received this message because you are subscribed to the Google Groups "adt-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to adt-dev+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Daniele Segato

unread,
Nov 16, 2014, 2:49:37 PM11/16/14
to adt...@googlegroups.com
Replies inline..

On Sun, Nov 16, 2014 at 7:57 PM, Xavier Ducrohet <x...@android.com> wrote:


On Sun, Nov 16, 2014 at 1:32 AM, Daniele Segato <daniele...@gmail.com> wrote:


On Saturday, November 15, 2014 10:23:01 PM UTC+1, Xavier Ducrohet wrote:
1. I'n not sure how a single buildConfigField is boiler plate.

It's not the single buildConfigField a boilerplate.

When you have many parameter to inject, with different values per variants you end up with many buildConfigField.

Each have the same data type and key. Meaning you duplicate your key on multiple properties and your values spread across the build file in different places. If you edit something you have to remember to edit everywhere.

You can create local variables in your build script and uses this to synchronize the type and name of the resources.
It's not as pretty, or object-oriented I suppose, as what you describe in https://code.google.com/p/android/issues/detail?id=73396 but it's good enough for 1.0

Yes that's what I'm doing currently.

 

3. This is not currently supported. You cannot have per-variant values. We take a combination of build type, flavors, defaultconfig and take the highest priority one. It's something we want to fix but no ETA.

That's the main issue.
At least now I know it is not possible yet.

Thank you very much for your replies and time.
Daniele

It'll be possible in the next version of the plugin to add per-variant buildConfig and resValues:

android.applicationVariants.all { variant ->
   variant.buildConfigField "type", "name", "value"
   variant.resValue "type", "name", "value"


am I right in thinking  I'll be able to do something like this?

android.applicationVariants.all { variant ->
   // option A
   variant.buildConfigField "type", "name", getMyValue(variant)
   variant.resValue "type", "name", getMyResValue(variant)

   // option B
   if (myCheckOnVariant(variant)) {
      variant.buildConfigField "type", "name", "value"
      " variant.resValue "type", "name", "value"
   } else if (...) {
      ...
   } else {
      ...
   }

defining my function that take the variant as parameter and do their stuff accordingly

This would be great.
Thanks again have a nice day/evening ;) 
 

Xavier Ducrohet

unread,
Nov 16, 2014, 3:48:48 PM11/16/14
to adt...@googlegroups.com
Yes you can do this.

--
You received this message because you are subscribed to the Google Groups "adt-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to adt-dev+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages