Android Gradle 基于多种风味库的多种风味应用程序

我的应用程序有几种风格的几个市场内应用程序计费系统。

我有一个共享所有项目基本代码的库。所以我决定将这些支付系统作为产品风格添加到这个库中。

问题是机器人库能有产品风格吗?

如果是这样,我如何包括不同的口味在各自的应用程序的口味?

我找了很多,但是没找到任何关于这个场景的东西。我在 http://tools.android.com/tech-docs/new-build-system/user-guide中找到的唯一接近的东西是这个:

dependencies {
flavor1Compile project(path: ':lib1', configuration: 'flavor1Release')
flavor2Compile project(path: ':lib1', configuration: 'flavor2Release')
}

我改变配置,以不同的事情,但它不工作!

我使用的是 android 工作室0.8.2。

54664 次浏览

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
}

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.

enter image description here

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')


}

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 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.

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.

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')

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: enter image description here

In this situation. How could I import the dependency for a specific build. For example: market1Common1Debug market1Common1DebugImplementation 'androidx.appcompat:1.2.0'

enter image description here