如何在gradle中仅将插件应用于一个flavor?

73

我有一个多种口味,多种构建类型的Android项目,我想集成NewRelic插件。但是我必须仅将其应用于一个客户,因此仅适用于一种产品口味。
NewRelic使用仪器,并且如果我在其他口味中应用了该插件,该插件将在其他口味中生成代码,而我们不允许这样做。

所以我的问题是:如何在gradle文件中使用apply plugin: something命令仅适用于我的其中一种口味?

7个回答

61

使用这段代码:

if (!getGradle().getStartParameter().getTaskRequests()
        .toString().contains("Develop")){
    apply plugin: 'com.google.gms.google-services'
}

getGradle().getStartParameter().getTaskRequests().toString() 的返回值类似于 [DefaultTaskExecutionRequest{args=[:app:generateDevelopDebugSources],projectPath='null'}],因此根据注释所述,Develop 必须以大写字母开头。


3
这段代码是可以运行的。但是需要注意口味名称的第一个字母应该是大写的。 - Phoenix Wang
1
这对我来说几乎可以工作,但是我注意到当输入 ./gradlew assembleDe 时,getTaskRequests 中的值也是 assembleDe - 而我预期它已经扩展为 assembleDebug - Fabio
3
这段代码无法正常工作。它会打印出一个空的数组"[]"。 请使用以下代码: println("${getGradle().getStartParameter().getTaskRequests().toString()}") - Pavel
1
我确认了@Pavel的评论。似乎在Android Studio中可以工作,但是从命令行运行时不起作用。这是我得到的全部内容:[DefaultTaskExecutionRequest{args=[build],projectPath='null'}] - AlanKley
1
@Fabio, 你找到解决问题的方法了吗?比如,执行 ./gradlew asF 而不是 ./gradlew assembleFlavor,就会失败,因为这个答案提出的解决方案中,任务请求字符串包含 "asF" 而不是 assembleFlavor。当尝试匹配 "Flavor" 时,这是一个问题! - Erik
显示剩余5条评论

17

尝试了不同的解决方案,但没有一个适用于我。这是我想出来的,并且在我测试的范围内似乎可以工作:

build.gradle

productFlavors {
    someFlavorWithGoogleGcm {
        dimension "type"
        applicationId "com.example.withGcm"
        ext.useGoogleGcm = true
    }
    someFlavorWithoutGoogleGcm {
        dimension "type"
        applicationId "com.example.withoutGcm"
    }
}

在配置之外,build.gradle文件内:

android.productFlavors.each { flavor ->
    if (getGradle().getStartParameter().getTaskRequests().toString().toLowerCase().contains(flavor.name) && flavor.ext.useGoogleGcm) {
        println("Building flavor with Google GCM [${flavor.name}] - applying plugin")
        apply plugin: 'com.google.gms.google-services'
    }
}

2
这是唯一对我起作用的解决方案。但是,我稍微改变了您的if语句为if (getGradle().getStartParameter().getTaskNames().stream().filter { it.toLowerCase().contains(flavor.name) }.count() > 0 && flavor.ext.useGoogleGcm) - Gabriel Gava
它似乎对我没有执行。我不知道为什么没有得到日志,插件也没有应用。在if语句之前添加了额外的日志,但仍然没有成功。 - Slion
似乎使用 .all 而不是 .each 可以解决这个问题。 - Slion
在使用Gradle 7.0.2时,我遇到了错误Cannot get property 'shouldMinify' on extra properties extension as it does not exist。因此,我需要将ext.shouldMinify属性添加到所有的flavors中(并设置相应的值)。 - Sasha Davydenko
这个“有点”有效,是的,它只在存在该扩展名时应用插件,但由于某种原因,“apply plugin: 'com.google.gms.google-services'”不会生成“R.string.default_web_client_id”。 - Suau
我猜测 'com.google.gms.google-services' 插件在实际构建生成 R.string.default_web_client_id 之前就已经运行了。 - Suau

16

我只是在应用级别的build.gradle文件中的flavor中使用了apply plugin: 'com.google.gms.google-services',它完全正常工作。

productFlavors {
    ..... your other flavors ....
    yourFlv {
        ....
        ....
        apply plugin: 'com.google.gms.google-services'
    }
}

无需额外步骤。


1
我建议其他人使用这个。 - Ljdawson
哇,它真的是那么简单! - Nuwisam
1
我就是用它来处理这个具体的问题,它对我有用。 - lilienberg
2
这适用于通过Android Studio构建,但对于在Jenkins中构建则无效。 - anro
8
这是一个语法快捷方式,当构建其他产品风格时仍然会涉及到该插件。已在 Android Gradle 插件版本 4.2.0 上进行了测试。 - yorkw
显示剩余2条评论

11
  1. 定义变量 - def fl
  2. 在您的Flavours(和/或构建)中初始化变量

    productFlavors {

            freeFlavour {
                (...)
                fl = "free"
            }

            paidFlavour {
                (...)
                fl = "paid"
            }
        }
  • 使用 if 语句 -

    if (fl == "free") { apply plugin: something }


  • 8
    似乎不起作用。在我的情况下(假设我正在调用assembleFree),两个块都被执行,因此fl的值是最后一个声明的flavour的名称。还有其他想法吗? - daemontus
    3
    这个问题将在配置时间内得到解决,由于需要遍及所有内容,"fl" 将包含最后一个值。 - l0v3

    6
    我找到了一个解决方案,但目前它不是最好的解决方案。因此,我不确定我最初想要做的事情是否可行。gradle文件评估和选择正确的口味和构建类型在gradle构建的不同阶段中进行,所以我所做的是:
    我使用命令行中的构建参数。当该参数为true时,我应用插件;当它不存在时,我也应用它(用于IDE构建)。我使用Jenkins,所以我可以将该参数写入构建作业。
    build.gradle文件:
    // First we have to attach a task to the project, which will be running first
    gradle.projectsEvaluated {
        preBuild.dependsOn(applyNewRelicByProperty)
    }
    
    // Then check on the parameter, which comes from the command line
    task applyNewRelicByProperty {
        if(!project.hasProperty('compileNewRelic')) {
            // NewRelic on: 'compileNewRelic' property not set, so running from IDE.
            apply plugin: 'newrelic'
        } else if(project.hasProperty('compileNewRelic') && project.getProperties().get('compileNewRelic').equals('true')) {
            // NewRelic on: 'compileNewRelic' property is set and it is 'true'.
            apply plugin: 'newrelic'
        } else {
            // NewRelic off
            println("No NewRelic")
        }
    }
    

    你需要通过以下方式运行gradle构建:

    assembleYourApp -PcompileNewRelic=true
    

    今天对我来说这个不起作用。显然,build.gradle解析器在评估项目之前查找apply语句,因此使if检查无效。 - Sebastiano

    2

    升级到Gradle 4.2后,Tarps的方法不再适用,所以我最终将其与Erik的答案结合起来。

    在您的build.gradle中为每个风味设置ext.useGoogleGcm

    productFlavors {
        a {
            ...
            ext.useGoogleGcm = true
        }
        b {
            ...
            ext.useGoogleGcm = false
        }
    }
    

    然后在文件底部:

    apply plugin: 'com.google.gms.google-services'
    
    afterEvaluate {
        android.productFlavors.each { flavor ->
            tasks.matching {
                it.name.contains('GoogleServices') && it.name.contains(flavor.name.capitalize())
            }*.enabled = flavor.ext.useGoogleGcm
        }
    }
    

    在您的assembleRelease任务输出中,您应该看到名称中带有“GoogleServices”的任务已运行,对于值为true的任务执行,对于值为false的任务跳过执行。如果您的构建出现关于toCapitalize的问题,您可以对it.nameflavor.name都使用toLowerCase

    1
    在Google服务Gradle插件的情况下,以下内容有效。
    apply plugin: 'com.google.gms.google-services'
    
    afterEvaluate {
        tasks.matching { it.name.contains("GoogleServices") && !it.name.contains(yourFlavorName) }*.enabled = false
    }
    

    其中,yourFlavorName 是一个大写字符串,包含必须应用插件的您的口味的名称;所有其他风味都不使用该插件。

    请注意,插件仍然适用于其他风味;此解决方案仅禁用它们的*GoogleServices*任务。这假定 Google Services Gradle 插件仅通过添加包含子字符串"GoogleServices"的任务来应用更改,这在未来可能不起作用。

    要检查这是否有效,您可以检查依赖项,例如:

    ./gradlew app:dependencyInsight --configuration yourFlavorNameDebugCompileClasspath --dependency google | grep -i services

    这应该显示一些yourFlavorName的依赖项,但不是其他口味的依赖项:

    ./gradlew app:dependencyInsight --configuration otherFlavorNameDebugCompileClasspath --dependency google | grep -i services


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