Code Path per Flavor in Android Gradle

5.3k views Asked by At

I have 2 buildTypes (debug, release) and 2 productFlavors (product1, product2). I want to define a buildConfigField for each buildType and productFlavors. The buildConfigField is the url the app to download data from the server, and it changes for each productFlavor and buildTypes.

Now, I have:

buildTypes {
    debug {
        debuggable true
    }
    release {
        debuggable false
    }
}
productFlavors {
    product1 {
        buildConfigField STRING, "URL_BASE",  '"https://api1.release.com"'

    }
    product2 {
        buildConfigField STRING, "URL_BASE", '"https://api2.release.com"'

    }
}

But I want something like this:

buildTypes {
    debug {
        debuggable true
    }
    release {
        debuggable false
    }
}
productFlavors {
    product1 {
        debug {
            buildConfigField STRING, "URL_BASE",  '"https://api1.debug.com"'
        }
        release {
            buildConfigField STRING, "URL_BASE",  '"https://api1.release.com"'
    }
    product2 {
        debug {
            buildConfigField STRING, "URL_BASE", '"https://api2.debug.com"'
            }
        release {
            buildConfigField STRING, "URL_BASE", '"https://api2.release.com"'
        }
    }
}

How I can achieve this?

Update:

Each URL_BASE has a different pattern so I can't group the URLs. A posible solution is to add the url base of the 2 flavor in the different build types and select the right one in the flavor.

buildTypes {
    debug {
        debuggable true
        buildConfigField STRING, API_VARIANT_PRODUCT1, '"api1.deb.com"'
        buildConfigField STRING, API_VARIANT_PRODUCT2, '"api2.debug.com"'

    }
    release {
        debuggable false
        buildConfigField STRING, API_VARIANT_PRODUCT1, '"api1.release.com"'
        buildConfigField STRING, API_VARIANT_PRODUCT2, '"api2.release.com"'
    }
}

productFlavors {
    product1 {
        buildConfigField STRING, URL_BASE, '"https://" + API_VARIANT_PRODUCT1 + "/v1"'
    }
    product2 {
        buildConfigField STRING, URL_BASE, '"https://" + API_VARIANT_PRODUCT2 + "/v1"'
    }
  }
}

UPDATE 2

If you need to add resources in gradle, like a 'KEY_MAP' the solution is in this page.

4

There are 4 answers

1
Phil H On

@Beni, you can use something like this

buildTypes {
    debug {
        debuggable true
        buildConfigField("String", "API_VARIANT", '"debugvariant"')
    }
    release {
        debuggable false
        buildConfigField("String", "API_VARIANT", '"releasevariant"')
    }
}
productFlavors {
    product1 {
        buildConfigField("String", "URL_BASE", '"https://api1." + API_VARIANT + ".com"')
    }
    product2 {
        buildConfigField("String", "URL_BASE", '"https://api2." + API_VARIANT + ".com"')
    }
}

The problem with what you were proposing to do is that the last definition of the the buildConfigField STRING, "URL_BASE" values for each buildType will get used in all product flavors. So what you would end up with would be something like "https://api2.release.com" in both release versions.

Using the above you will end up with something like this in your BuildConfig files for each variant

// Fields from build type: debug
public static final String API_VARIANT = ["debugvariant"|"releasevariant"];
// Fields from product flavor: [product1|product2]
public static final String URL_BASE = "https://[api1|api2]." + API_VARIANT + ".com";

Hope this helps.

0
JesusS On
applicationVariants.all { variant ->

   def apiVariant = variant.getFlavorName == "product1" ? "api1" : "api2"
   def server = variant.buildType.name == "debug" ? "debug" : "release"

   variant.buildConfigField STRING, URL_BASE, "http://" + apiVariant + "." + server + ".com"
}
7
n4h0y On

Build Type is not part of Product Flavor and vice versa. Variant is calculated based on both build type and product flavor. Using this you can just create either an extension (option 1) or a property (option 2) with a consistent format using both product flavor and build type.

Option 1

ext.product1_release_base_url = 'http://baseurl.myproduct/public'
ext.product2_release_base_url = 'http://baseurl.yourproduct/secure'
ext.product1_debug_base_url = 'http://debugurl.myproduct/test'
ext.product2_debug_base_url = 'http://yourproduct/debug'

android {
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
        debug {
            minifyEnabled false
        }
    }
    productFlavors {
        product1 {}
        product2 {}
    }
}

project.android.applicationVariants.all {variant ->
    def url = project.ext."${variant.flavorName}_${variant.buildType.name}_base_url"
    variant.buildConfigField('String', 'URL_BASE', "\"${url}\"")
}

Option 2

in gradle.properties

product1_release_base_url = 'http://baseurl.myproduct/public'
product2_release_base_url = 'http://baseurl.yourproduct/secure'
product1_debug_base_url = 'http://debugurl.myproduct/test'
product2_debug_base_url = 'http://yourproduct/debug'

in build.gradle

android {
    buildTypes {
        release {}
        debug {}
    }
    productFlavors {
        product1 {}
        product2 {}
    }
}

project.android.applicationVariants.all {variant ->
    def url = project."${variant.flavorName}_${variant.buildType.name}_base_url"
    variant.buildConfigField('String', 'URL_BASE', "\"${url}\"")
}
2
Gabriele Mariotti On

I don't know how you can set different values for multiple BuildVariants (build types + flavor) in build.gradle with the buildConfigField method.

However you can use a different value for your url_base inside res/values/strings.xml.

Something like:

<string name="url_base">https://api1.debug.com</string>

Then you can create the same string resource in these folders:

 - app/src/product1Debug: Contains product1-debug-related code/resources
 - app/src/product1Release: Contains product1-release-related code/resources
 - app/src/product2Debug: Contains product2-debug-related code/resources
 - app/src/product2Release: Contains product2-release-related code/resources

Of course it isn't the same to have a value inside the BuildConfig and is less confortable than the configuration with build.gradle.