如何为不同的产品风味定义不同的依赖关系

198

我正在将我的一个应用程序转换为Gradle,并希望使用新的构建风格特性来拥有一个付费版本和一个基于广告的免费版本。

我只想让基于广告的版本依赖于Admob SDK。

我的构建文件看起来像这样:

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:0.5.+'
    }
}
apply plugin: 'android'

repositories {
    mavenCentral()
}

android {
    compileSdkVersion 18
    buildToolsVersion "18.0.1"

    defaultConfig {
        minSdkVersion 10
        targetSdkVersion 18
    }

    productFlavors {
        Pro {
            packageName "de.janusz.journeyman.zinsrechner.pro"
        }
        Free { 
            dependencies {

            }
        }
    }
}

dependencies {
    compile 'com.android.support:support-v4:18.0.+'
    compile 'com.actionbarsherlock:actionbarsherlock:4.4.0@aar'
    compile fileTree(dir: 'libs', include: '*.jar')
}

有没有一种方法可以配置免费产品风格中的依赖项,使其拥有自己的libs文件夹,并将该文件夹与包含两种风格的通用库的主要libs文件夹合并?

如果可以,请问我应该如何定义此文件夹?


请访问此线程:https://dev59.com/qGAf5IYBdhLWcg3wQQu4#24910671 - Ali
7个回答

220

为了定义特定于口味的依赖关系,您可以在依赖项部分中使用proCompile而不是compile。运行 gradle properties 命令时,您会获得自动生成配置的概述。

正确的构建文件如下所示:

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.2.3'
    }
}
apply plugin: 'com.android.application'

repositories {
    mavenCentral()
}

android {
    compileSdkVersion 22
    buildToolsVersion "22.0.1"

    defaultConfig {
        minSdkVersion 10
        targetSdkVersion 22
    }

    productFlavors {
        pro {
            packageName "de.janusz.journeyman.zinsrechner.pro"
        }
        free { }
    }
}

dependencies {
    compile 'com.android.support:support-v4:22.2.0'
    freeCompile 'com.google.android.gms:play-services-ads:7.5.0'
}

21
哦,看起来你需要将dependencies块移动到android块下面。多么直观啊。 - nmr
15
请注意,如果Flavor名称以大写字母开头,Gradle生成的xxxCompile闭包将无法正常工作。 - Jarett Millard
2
"packageName" 应该改为 "applicationId"。 - Apperside
8
你如何处理避免调用广告类(Ad classes)的问题? - Jared Burrows
2
@JaredBurrows 在不同的版本中放置调用广告类的类的不同版本。可能最好有一个单一的中央类,在其中调用这些类。 - Stephan
显示剩余7条评论

48

快进到2018年中期。您需要添加flavorDimensions

android {
    ...
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    flavorDimensions "dimensionName"
    productFlavors {
        pro {
            dimension "dimensionName"
        }
        free {
            dimension "dimensionName"
        }
    }
}

dependencies {
    implementation 'com.android.support:support-v4:22.2.0'
    freeImplementation 'com.google.android.gms:play-services-ads:15.0.1'
}

另外,请注意:

'compile' 配置已经过时并被 'implementation' 和 'api' 取代。它将在2018年底之前删除。有关更多信息,请参见: http://d.android.com/r/tools/update-dependency-configurations.html


你知道如何使用buildVariants来实现吗?比如proDebugImplementation。 - Leandro Ocampo
1
请添加一个单独的问题,链接在评论部分。请完整说明您想要实现的内容。 :) - user1506104

16

简单:

dependencies {

    ....
    ....

    gradle.startParameter.getTaskNames().each { task ->
        if(task.contains("free")) {
             implementation 'com.google.android.gms:play-services-ads:17.2.0'
        }
    }

    ....
    ....
}

或者只需要:

FreeImplementation 'com.google.android.gms:play-services-ads:17.2.0'

14
您需要为每个口味手动添加配置。例如:
configurations {
    proCompile
    freeCompile
}

dependencies {
    compile 'com.parse.bolts:bolts-tasks:1.3.0'

    proCompile 'com.android.support:design:23.1.1'
    freeCompile 'com.parse:parse-android:1.12.0'
}

2
如何继续进行?如何激活不同的配置?这仅适用于Android构建吗?非Android构建是否可以实现? - koppor

11

编辑:我建议使用其他技巧!

除了被接受的答案,这是一个替代方案:

    ext {
        flavorType = ""
    }


    gradle.startParameter.getTaskNames().each { task ->

        if(task.contains("flavor1")){
            flavorType = "flavor1"
        } else if (task.contains("flavor2")){
            flavorType = "flavor2"
        } else {
            flavorType = "flavor3"
        }

    }

 if(flavorType == 'flavor1' || flavorType == 'flavor2') {
        compile 'com.android.support:support-v4:18.0.+'
    }

2
这个程序似乎不允许同时构建多个版本,这对我们大多数人来说是一个致命问题。此外,它可能也无法与Android Studio很好地配合使用。 - Rene Groeschke
3
这是在依赖模块里吗? - user1743524
2
这个块是否有依赖关系? - Karacago
嗯...对于10或50种口味来说,它的可扩展性不太好,是吧? - Ewoks
@Ewoks 我需要制作很多种口味,你有更好的想法吗? - Viks

9
如果您使用Gradle和Kotlin(build.gradle.kts),则可以按照以下方式添加自定义flavor的依赖项:
dependencies {
    "freeImplementation"("com.google.android.gms:play-services-ads:7.5.0")
}

它能工作,但为什么它是一个有效的答案?有任何来源吗? - VaiTon
1
@VaiTon 它被定义为 DependencyHandlerScope.kt 中 String 的重载运算符,如下所示: operator fun String.invoke(dependencyNotation: Any): Dependency? = dependencies.add(this, dependencyNotation) - Miloš Černilovský

0
这种方法适用于多模块项目。
创建一个构建 gradle 文件(例如 build_flavor_config.gradle),并在其中定义您的配置,就像这样。
android {
    flavorDimensions 'resource_type'
    productFlavors {
        create("flavor1") {
            dimension 'resource_type'
            versionName "$app_version_name - flavor1"
        }
        create("flavor2") {
            dimension 'resource_type'
            versionName "$app_version_name - flavor2"
        }
    }
}

将此Gradle文件应用于您想要的每个模块,例如应用程序模块或功能模块,如下所示:
apply from: rootProject.file("build_flavor_config.gradle")

同步项目后,您可以像这样访问每个版本的特定实现:

flavor1Implementation("flavor1Library")
flavor2Implementation("flavor2Library")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接