Search code examples
androidgradleandroid-manifestandroid-build-typeandroid-build-flavors

abstraction of Gradle Flavor variable to


Recently, I figured out how to do Manifest Mergers with placeholders. I implemented it in my app, and for the most part, I am really happy with the results - Gradle-only solution to modify App name based on Build Variant

Before, you would have to create a new sparse String Resource with just one string that had the attribute you wanted changed over different resources like with flavors and build types. Personally, I don't think that method is really clean. Simple and easy, yes, but not clean.

From that I created the following that works. However, I don't like duplicate code, and everyone of my Flavors will have duplicate code. Is this something is can be abstracted out? Possibly be able to put it in the defaultConfig?

For example, in the code below, is there some way I can move the manifestPlaceholders code that exists in every Flavor, and abstract it to the defaultConfig somehow so I can just define it once?

android {
    ...
    ext {
        APP_NAME = "App Name"
        HUB_NAME = "Hub"
    }

    defaultConfig {
        ...
    }

    productFlavors {
        entity_1 {
            versionNameSuffix ' - Entity_1'
            applicationIdSuffix 'entity_1'
            manifestPlaceholders = [ applicationLabel: APP_NAME + versionNameSuffix ]
        }
        entity_2 {
            versionNameSuffix ' - Entity_2'
            applicationIdSuffix 'entity_2'
            manifestPlaceholders = [ applicationLabel: APP_NAME + versionNameSuffix ]
        }

        ...

        entity_n {
            versionNameSuffix ' - Entity_n'
            applicationIdSuffix 'entity_n'
            manifestPlaceholders = [ applicationLabel: APP_NAME + versionNameSuffix ]
        }
        hub {
            versionNameSuffix ' - Hub'
            applicationIdSuffix 'hub'
            manifestPlaceholders = [ applicationLabel: HUB_NAME ]
        }
    }

    buildTypes {
        release {
            ...
        }
    }

    applicationVariants.all { variant ->

        if (variant.buildType.name != "release") return

        if (variant.flavorName != "hub") {
            variant.mergedFlavor.manifestPlaceholders = [applicationLabel: APP_NAME]
        } 
    }

By the way, the above code would give me applicationLabels of the following. I use these to determine the Name of the app on my home screen.

Desired

Flavor     Debug App Name             Release App Name
--------   --------------             ----------------
entity_1   App Name - Entity_1_name   App Name
entity_2   App Name - Entity_2_name   App Name
...        ...                        ...
entity_n   App Name - Entity_n_name   App Name
hub        Hub                        Hub

Solution

  • What is wanted can easily be done.

    The current implementation in the question was trying to create the most specific names first, and then REMOVING the information that was not needed in specific flavors.

    With the opposite idea of thought, I needed to create the most general names first, and then ADD the information that is needed in specific flavors.

    android {
        ...
        ext {
            APP_NAME = "App Name"
            HUB_NAME = "Hub"
        }
    
        defaultConfig {
            ...
            manifestPlaceholders = [ applicationLabel: APP_NAME ]
        }
    
        productFlavors {
            entity_1 {
                versionNameSuffix ' - Entity_1'
                applicationIdSuffix 'entity_1'
            }
            entity_2 {
                versionNameSuffix ' - Entity_2'
                applicationIdSuffix 'entity_2'
            }
    
            .
            .
            .
    
            entity_n {
                versionNameSuffix ' - Entity_n'
                applicationIdSuffix 'entity_n'
            }
    
            hub {
                versionNameSuffix ' - Hub'
                applicationIdSuffix 'hub'
                manifestPlaceholders = [ applicationLabel: HUB_NAME ]
            }
        }
    
        buildTypes {
            release {
                ...
            }
        }
    
    // BEFORE the applicationVariants.all { ... } code runs, this is what all the applicationLabel look like. We are close, but need to ADD to them...
    
    //     Flavor     Debug App Name             Release App Name
    //    --------   --------------             ----------------
    //    entity_1   App Name                   App Name
    //    entity_2   App Name                   App Name
    //    ...        ...                        ...
    //    entity_n   App Name                   App Name
    //    hub        Hub                        Hub
    
        applicationVariants.all { variant ->
    
            // Don't modify the release build or the hub flavor. They are good already.
            if (variant.buildType.name == "release" || variant.flavorName == "hub") return
            variant.mergedFlavor.manifestPlaceholders = [applicationLabel: APP_NAME + variant.mergedFlavor.versionNameSuffix]
        }
    
    // AFTER the applicationVariants.all { ... } code runs, this is what all the applicationLabel look like. We are done!
    
    //     Flavor     Debug App Name             Release App Name
    //    --------   --------------             ----------------
    //    entity_1   App Name - Entity_1_name   App Name
    //    entity_2   App Name - Entity_2_name   App Name
    //    ...        ...                        ...
    //    entity_n   App Name - Entity_n_name   App Name
    //    hub        Hub                        Hub