Using Build Flavors - Structuring source folders and build.gradle correctly

daniel_c05 picture daniel_c05 · May 24, 2013 · Viewed 88.5k times · Source

Please note: Answer edited after Xavier's Answer

I am trying to use different Build Flavors for one same Application project in Android Studio. However, I seem to be having a terrible time configuring it to work appropriately.

Steps:

  1. Create a new Android Studio Project, named 'Test'.
  2. Open build.gradle* and added the following lines:

    productFlavors {
    flavor1 {
        packageName 'com.android.studio.test.flavor1'
        }
    flavor2 {
        packageName 'com.android.studio.test.flavor2'
        }
    }
    
  3. After restarting Android Studio, I now see 4 build variants under the Build Variants section. Meaning we were succesful on seting up the product flavors so far. **
  4. Created a new Source folder for flavor1; however, I am not sure if I'm doing it the right way. Here's how I did it:

    • Keep in mind that my Package name for this project is: com.foo.test
    • Right click on the src folder, for flavor1, I actually created the individual folders in the explorer, in a way that the structure is src/flavor1/java/com/foo/test/MainActivity.java.
    • The above worked well, since the 'java' folder is in blue, meaning the IDE knows its an active source directory. Also, the package was automatically created. Despite of this, I am getting a warning for duplicate class found. See screenshot here.
    • For flavor2, I tried creating the package manually, but 'src' folder for flavor2 seems not be in blue, and therefore the options are different when right clicked, and 'New Package' is not available for me to use. See image here.
    • Note that for flavor1, I also created a 'res' directory, which does turn blue, but despite of that, doesn't offer the ability to create either an Android Resource file, or Andorid resource directory, in case I wanted to use different resoruces for different flavors.

Am I doing something wrong? Or am I missing something? Let me know if you need more info.

*My Project seems to have two build.gradle files. One located on the root of the project folder (\GradleTest), this one is empty. The second one located on the root of a subfolder of \GradleTest, also labeled 'GradleTest' (GradleTest-GradleTest), this is the one that already had code when opened; therefore, that is the one I edited.

** I checked gradle settings and apparently Use auto-import was already enabled. Despite of this, making changes to the build.gradle file doesn't automatically update the build variants. Note: I also tried using Build - Rebuild Project, and/or Build - Make Project, no-go. I still have to close the project, and re-open for changes to take effect.

Answer

Xavier Ducrohet picture Xavier Ducrohet · May 25, 2013

If you got in the Studio preferences, under the Gradle section, you can enable auto-import for your project (we'll enable this by default later). This will let Studio re-import your build.gradle whenever you edit it.

Creating flavors doesn't mean you're going to use custom code for them so we don't create the folders. You do need to create them yourself.

If you look at my IO talk you'll see how we mix in together values from the flavors and build type to create the variant.

For the Java source:

src/main/java
src/flavor1/java
src/debug/java

are all 3 used to create a single output. This means they can't define the same class.

If you want to have a different version of the same class in the two flavor you'll need to create it in both flavors.

src/flavor1/java/com/foo/A.java
src/flavor2/java/com/foo/A.java

And then your code in src/main/java can do

import com.foo.A

depending on the flavor selected, the right version of com.foo.A is used.

This also means both version of A must have the same API (at least when it comes to the API used by classes in src/main/java/...

Edit to match revised question

Additionally, it's important to put the same A class only in source folders that are mutually exclusive. In this case src/flavor1/java and src/flavor2/java are never selected together, but main and flavor1 are.

If you want to provide a different version of an activity in different flavor do not put it in src/main/java.

Do note that if you had 3 flavors and only wanted a custom one for flavor1, while flavor2 and flavor3 shared the same activity you could create a common source folders for those two other activities. You have total flexibility in creating new source folders and configuring the source set to use them.

On to your other points:

It's normal that the 2nd flavor source folder is not blue. You need to switch to the 2nd flavor to enable it, and then you'll be able to create packages and classes inside. Until then, Studio doesn't consider it to be a source folder. We'll hopefully improve this in the future to make the IDE aware of those unactive source folders.

I think it's also normal that you can't create resource files in the res folder. The menu system hasn't been updated to deal with all these extra resource folders. This will come later.