Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is ist possible to have custom source files per build variant in Android Gradle?

Tags:

android

gradle

Our application has a free and a paid version. We also make branded-versions, which means that the application vary in two dimensions.

Four versions could be:

  • The App, Nike ed. free
  • The APP, Nike ed. paid
  • The App, Adidas ed. paid
  • The App, Adidas ed. free

My solution now is to have two build-types, paid and free:

  buildTypes {
        paid {
            packageNameSuffix ".paid"
        }

        free {
            packageNameSuffix ".free"
        }
    }

And two build flavors:

productFlavors{
    nike{
        packageName "com.example.theapp.nike"
    }

    adidas{
        packageName "com.example.theapp.adidas"
    }

}

Every free-version of the app make us of a content-provider, a content provider which is specific per flavor-build type combination. The problem is that I don't understand where to put a source file based on build variant. Source files put into /src/nike or /src/free will be picked up depending on build type or flavor. But how about source files that are depending on the build variant (the combination of type and flavor)?

like image 674
lorgartzor Avatar asked Jun 26 '13 09:06

lorgartzor


People also ask

How many build Gradle file is there in one Android project?

gradle files in an Android Studio project?

How many types of Gradle build files do we have in Android?

Each module has its own build file, so every Android Studio project contains two kinds of Gradle build files.

How would you specify in your build Gradle file?

You can do this by adding extra properties to the ext block in the top-level build.gradle file. // of properties you can define. // You can also create properties to specify versions for dependencies.

What is build variant in Android?

Build variants are the result of Gradle using a specific set of rules to combine settings, code, and resources configured in your build types and product flavors. Although you do not configure build variants directly, you do configure the build types and product flavors that form them.


2 Answers

You can create a new folder under src for every build or flavor that you have. i.e: 'free', 'paid', 'nike', 'adidas'.

The files that you put in any of these folders gets picked up when building depending on the type and build both.

According to Gradle Plugin User Guide on Android Tools Project Site:

Similar to Build Types, Product Flavors also contribute code and resources through their own sourceSets.

and

The following rules are used when dealing with all the sourcesets used to build a single APK:

  • All source code (src/*/java) are used together as multiple folders generating a single output.
  • Manifests are all merged together into a single manifest. This allows Product Flavors to have different components and/or permissions, similarly to Build Types.
  • All resources (Android res and assets) are used using overlay priority where the Build Type overrides the Product Flavor, which overrides the main sourceSet.
  • Each Build Variant generates its own R class (or other generated source code) from the resources. Nothing is shared between variants.

meaning that your java files for the buildType "free" will overwrite the ones for your flavors "nike" if they have the same name.

But if you're adding something to a manifest, according to the second point in the list above the final manifest will be a merge of all of the manifests.

If you need more customization you can put your files in your build variant's folder "src/freeNike/".

like image 141
maclir Avatar answered Oct 19 '22 04:10

maclir


I had similar problem with build types overriding flavors due to the overlay rules.

I ended up redirecting the build type source sets into different folders depending on which flavor was built.

android.applicationVariants.all { variant ->
    switch (variant.name) {
        case "FreeNike":
            variant.mergeResources.doFirst {
                android.sourceSets.free.setRoot("src/freeNike")
            }
            break;
        case "FreeAdidas":
            variant.mergeResources.doFirst {
                android.sourceSets.free.setRoot("src/freeAdidas")
            }
            break;
        case "PaidNike":
            variant.mergeResources.doFirst {
                android.sourceSets.paid.setRoot("src/paidNike")
            }
            break;
        case "PaidAdidas":
            variant.mergeResources.doFirst {
                android.sourceSets.paid.setRoot("src/paidAdidas")
            }
            break;
    }
}

You are of course free to use a different folder structure. See example here: Folder naming convention for gradle build variants

like image 21
ddante Avatar answered Oct 19 '22 03:10

ddante