I have an android library with flavors defined
flavorDimensions "player"
productFlavors {
educator {
dimension "player"
}
learner {
dimension "player"
}
}
and dependencies like so
dependencies {
learnerImplementation project(':learnerFeatureModule')
}
Now when I use this library in my Educator app, I get error
Project with path ':learnerFeatureModule' could not be found in project ':myLibrary'
because I have not defined :learnerFeatureModule in my settings.gradle.
I have defined missing strategy in Educator app/build.gralde too.
missingDimensionStrategy 'player', 'educator'
But learnerFeatureModule is learnerImplementation. Why is educator app even trying to resolve this?
I need a way, where Educator app does not look for this module as its not requried.
1 workaround that solves it for me (this does not use flavor as such)
in library build.gradle
dependencies {
def skipLearnerModule = rootProject.ext.get("skipLearnerModule")
if(!skipLearnerModule)
implementation project(':learnerFeatureModule')
and in educator app's root build.gradle
buildscript {
ext {
skipLearnerModule = true
}
I believe the reason why flavor does not work is because gradle's project configure step tries to resolve module for all variant of the app
How do I use setIgnore on a local library either from the apps build.gradle or the library build.gradle based on the apps flavor. I am not sure if I can reference the apps build.gradle flavor/dimension from the library build.gradle. I also don't know if I can reference a library from the apps build.gradle and use lib.setIgnore(true). Any solution to solving this issue?
I am currently only using one dimension for the application and multiple flavors.
This is how it is typically done; but I need to set Ignore on a library based on the apps flavor.
android {
...
variantFilter { variant ->
if(variant.buildType.name == 'release' && variant.getFlavors().get(0).name == 'vanilla') {
variant.setIgnore(true)
}
}
}
Maybe you can use the library only when you need.
dependencies {
// use "mylib" for debug
debugImplementation project(path: ':mylib')
// all the flavors
implementation "com.android.support:appcompat-v7:28.0.0'
}
You can try to wait for the task graph to be assembled and then removes the undesired name pattern as follows:
gradle.taskGraph.whenReady { graph ->
graph.allTasks.findAll { it.name ==~ /.*vanilla.*/ }*.enabled = false
}
App level build gradle dependencies
devCompile project(path: ':mymodule', configuration: 'devRelease')
proCompile project(path: ':mymodule', configuration: 'proRelease')
qaCompile project(path: ':mymodule', configuration: 'qaRelease')
offlineCompile project(path: ':mymodule', configuration: 'offlineRelease')
mentioned
publishNonDefault true
flavorDimensions "default"
I have tried This accepted answer but didn't work.
Update:
Look at the library gradle flavor that I want to compile. I have the same flavor mentioned in my app's Module.
dev {
manifestPlaceholders = [facebookId: "SOME_FACEBOOK_ID_1"]
}
pro {
manifestPlaceholders = [facebookId: "SOME_FACEBOOK_ID_2"]
}
qa {
manifestPlaceholders = [facebookId: "SOME_FACEBOOK_ID_3"]
}
offline {
manifestPlaceholders = [facebookId: "SOME_FACEBOOK_ID_4"]
}
You just need to reduce the details you provide:
compile project(path: ':mymodule')
The details what in which configuration is decided by gradle now by themselves. So it became way easier. Instead of 4 lines you just need the above now.
Also remove the publishNonDefault true from your modules gradle. It is not needed anymore.
Dependency management between modules has changed since Android Gradle Plugin 3.0.0. It automatically tries to matches flavours between your app and the libraries/modules it depends on.
See the documentation for more explanation!
My app has several flavors for several markets in-app-billing systems.
I have a single library which shares the base code for all of my projects. So I decided to add those payment systems to this library as product flavors.
The question is can android library have product flavors?
If so, how can I include different flavors in respective flavor of the app?
I searched a lot, and I couldn't find anything about this scenario. The only close thing I found was this in http://tools.android.com/tech-docs/new-build-system/user-guide:
dependencies {
flavor1Compile project(path: ':lib1', configuration: 'flavor1Release')
flavor2Compile project(path: ':lib1', configuration: 'flavor2Release')
}
I changed configuration to different things but it did not work!
I'm using android studio 0.8.2.
Finally I found out how to do this, I will explain it here for others facing same problem:
If App and Library have same Flavor name(s)
It's possible since Gradle Plugin 3.0.0 (and later) to do something like:
Library build.gradle:
apply plugin: 'com.android.library'
// Change below's relative-path
// (as the `../` part is based on my project structure,
// and may not work for your project).
apply from: '../my-flavors.gradle'
dependencies {
// ...
}
android {
// ...
}
Project build.gradle:
buildscript {
// ...
}
apply plugin: 'com.android.application'
// Note that below can be put after `dependencies`
// (I just like to have all apply beside each other).
apply from: './my-flavors.gradle'
dependencies {
api project(':lib')
}
android {
productFlavors {
// Optionally, configure each flavor.
market1 {
applicationIdSuffix '.my-market1-id'
}
market2 {
applicationIdSuffix '.my-market2-id'
}
}
}
My flavors .gradle:
android {
flavorDimensions 'my-dimension'
productFlavors {
market1 {
dimension 'my-dimension'
}
market2 {
dimension 'my-dimension'
}
}
}
If App or Library has different Flavor-name (old answer)
The key part is to set publishNonDefault to true in library build.gradle, Then you must define dependencies as suggested by user guide.
Update 2022; publishNonDefault is now by default true, and setting it to false is ignored, since said option is deprecated.
The whole project would be like this:
Library build.gradle:
apply plugin: 'com.android.library'
android {
....
publishNonDefault true
productFlavors {
market1 {}
market2 {}
market3 {}
}
}
project build.gradle:
apply plugin: 'com.android.application'
android {
....
productFlavors {
market1 {}
market2 {}
market3 {}
}
}
dependencies {
....
market1Compile project(path: ':lib', configuration: 'market1Release')
market2Compile project(path: ':lib', configuration: 'market2Release')
// Or with debug-build type support.
android.buildTypes.each { type ->
market3Compile project(path: ':lib', configuration: "market3${type.name}")
}
}
Now you can select the app flavor and Build Variants panel and the library will be selected accordingly and all build and run will be done based on the selected flavor.
If you have multiple app module based on the library Android Studio will complain about Variant selection conflict, It's ok, just ignore it.
There are one problem with Ali answer. We are losing one very important dimension in our build variants. If we want to have all options (in my example below 4 (2 x 2)) we just have to add custom configurations in main module build.gradle file to be able to use all multi-flavor multi-buildType in Build Variants. We also have to set publishNonDefault true in the library module build.gradle file.
Example solution:
Lib build.gradle
android {
publishNonDefault true
buildTypes {
release {
}
debug {
}
}
productFlavors {
free {
}
paid {
}
}
}
App build.gradle
android {
buildTypes {
debug {
}
release {
}
}
productFlavors {
free {
}
paid {
}
}
}
configurations {
freeDebugCompile
paidDebugCompile
freeReleaseCompile
paidReleaseCompile
}
dependencies {
freeDebugCompile project(path: ':lib', configuration: 'freeDebug')
paidDebugCompile project(path: ':lib', configuration: 'paidDebug')
freeReleaseCompile project(path: ':lib', configuration: 'freeRelease')
paidReleaseCompile project(path: ':lib', configuration: 'paidRelease')
}
Update for Android Plugin 3.0.0 and higher
According to the official Android Documentation - Migrate dependency configurations for local modules,
With variant-aware dependency resolution, you no longer need to use variant-specific configurations, such as freeDebugImplementation, for local module dependencies—the plugin takes care of this for you
You should instead configure your dependencies as follows:
dependencies {
// This is the old method and no longer works for local
// library modules:
// debugImplementation project(path: ':library', configuration: 'debug')
// releaseImplementation project(path: ':library', configuration: 'release')
// Instead, simply use the following to take advantage of
// variant-aware dependency resolution. You can learn more about
// the 'implementation' configuration in the section about
// new dependency configurations.
implementation project(':library')
// You can, however, keep using variant-specific configurations when
// targeting external dependencies. The following line adds 'app-magic'
// as a dependency to only the "debug" version of your module.
debugImplementation 'com.example.android:app-magic:12.3'
}
So in Ali's answer, change
dependencies {
....
market1Compile project(path: ':lib', configuration: 'market1Release')
market2Compile project(path: ':lib', configuration: 'market2Release')
}
to
implementation project(':lib')
And plugin will take care of variant specific configurations automatically. Hope it helps to others upgrading Android Studio Plugin to 3.0.0 and higher.
My Android Plugin is 3.4.0,and I find that it doesn't need configurations now.All you need is to make sure the flavorDimensions and productFlavors in application contains one productFlavor of the same flavorDimensions and productFlavors in libraries.For sample:
In mylibrary's build.gradle
apply plugin: 'com.android.library'
android {
....
flavorDimensions "mylibFlavor"
productFlavors {
market1
market2
}
}
application's build.gradle:
apply plugin: 'com.android.application'
android {
....
flavorDimensions "mylibFlavor", "appFlavor"
productFlavors {
market1 {
dimension "mylibFlavor"
}
market2 {
dimension "mylibFlavor"
}
common1 {
dimension "appFlavor"
}
common2 {
dimension "appFlavor"
}
}
}
dependencies {
....
implementation project(path: ':mylibrary')
}
After sync,you can switch all options in Build Variants Window:
To get the flavors working on an AAR library, you need to define defaultPublishConfig in the build.gradle file of your Android Library module.
For more information, see: Library Publication.
Library Publication
By default a library only publishes its release variant. This variant
will be used by all projects referencing the library, no matter which
variant they build themselves. This is a temporary limitation due to
Gradle limitations that we are working towards removing. You can
control which variant gets published:
android {
defaultPublishConfig "debug" }
Note that this publishing configuration name references the full
variant name. Release and debug are only applicable when there are no
flavors. If you wanted to change the default published variant while
using flavors, you would write:
android {
defaultPublishConfig "flavor1Debug" }
I also ran into a problem compiling modules for various options.
What i've found:
It looks like we don't need add publishNonDefault true into lib's build.gradle file, since Gradle 3.0.1.
After decompiling a class BaseExtension found this:
public void setPublishNonDefault(boolean publishNonDefault) {
this.logger.warn("publishNonDefault is deprecated and has no effect anymore. All variants are now published.");
}
And instead of:
dependencies {
...
Compile project(path: ':lib', configuration: 'config1Debug')
}
We should use:
dependencies {
...
implementation project(':lib')
}
Only the important thing, is to add a configurations {...} part to the build.gradle.
So, the final variant of app's build.gradle file is:
buildTypes {
debug {
...
}
release {
...
}
}
flavorDimensions "productType", "serverType"
productFlavors {
Free {
dimension "productType"
...
}
Paid {
dimension "productType"
...
}
Test {
dimension "serverType"
...
}
Prod {
dimension "serverType"
...
}
}
configurations {
FreeTestDebug
FreeTestRelease
FreeProdDebug
FreeProdRelease
PaidTestDebug
PaidTestRelease
PaidProdDebug
PaidProdRelease
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation project(':lib')
...
}
Also, you can use Filter variants to restrict build variants.
P.s. don't forget to include modules in the settings.gradle file, like:
include ':app'
include ':lib'
project(':lib').projectDir = new File('app/libs/lib')
At the moment it's not possible, although if I recall correctly its a feature they want to add. (Edit 2: link, link2 )
Edit:
For the moment I'm using the defaultPublishConfig option to declare which library variant get's published:
android {
defaultPublishConfig fullRelease
defaultPublishConfig demoRelease
}
I know this subject has been closed, but just an update with gradle 3.0, see this : https://developer.android.com/studio/build/gradle-plugin-3-0-0-migration.html#variant_aware and grep matchingFallbacks and missingDimensionStrategy.
Now it's way more simple to declare the dependencies between module flavors.
...and in this precise case with gradle3.0, as flavors share the same name, gradle would map them magically, there is no configuration required.
In this situation. How could I import the dependency for a specific build. For example: market1Common1Debug
market1Common1DebugImplementation 'androidx.appcompat:1.2.0'
I have a suite of projects that use the same module, which contains nearly all the actual code. The project is setup like:
project/
- app/
- build.gradle
- libraries/
- module/
- build.gradle
- build.gradle
- settings.gradle
The dependencies are all setup correctly, and I can build and run apps great, however I can only add flavors to the project, which is not the ideal solution. settings.gradle contains the following:
include ':app', ':libraries:module'
In the app directory's build.gradle file, I added the following block:
productFlavors {
alpha
production
}
Using gradle 0.11, this syncs and creates assembleAlphaDebug, assembleAlphaRelease, assembleProductionDebug, assembleProductionRelease tasks. When I attempt to do this in the module instead, I get the error:
No resource found that matches the given name (at 'theme' with value '#style/MyCustomTheme')
in the built app/src/main/AndroidManifest.xml. For some reason, the module is not being built, so the custom theme is not working. What am I doing wrong?
In the library module's build.gradle, you need a couple extra lines to tell it to export the flavors and which build variant to use by default if not specified when being included from another module:
android {
defaultPublishConfig "productionRelease"
publishNonDefault true
productFlavors {
alpha {
}
production {
}
}
}
That publishNonDefault bit is only necessary if someone would want to depend on something other than the productionRelease variant. Presumably this is the case if you set up multi-flavors in your library in the first place.
Now if you add a dependency from another module via this in its build.gradle:
dependencies {
compile project(':module')
}
it will depend on the productionRelease variant by default. If you'd like to depend on a non-default variant:
dependencies {
compile project(path: ':module', configuration:'alphaDebug')
}
First add below gradle code snippet to your app/build.gradle
flavorDimensions "env"
productFlavors {
dev {
dimension "env"
}
pre {
dimension "env"
}
prod {
dimension "env"
}
}
Second, add below gradle code snippet to your module/build.gradle
flavorDimensions "env"
productFlavors {
register("dev")
register("pre")
register("prod")
}
I have posted an ansower in this
Use different library module for each android flavor