如何将插件应用于gradle中的一种风格?

Posted

技术标签:

【中文标题】如何将插件应用于gradle中的一种风格?【英文标题】:How to apply plugin to only one flavor in gradle? 【发布时间】:2015-10-01 12:09:22 【问题描述】:

我有一个多风格、多构建类型的 android 项目,我想集成 NewRelic 插件。但我必须只为其中一位客户应用它,因此只适用于一种产品风味。 NewRelic 使用插桩,如果我在那里应用插件,插件会生成其他风格的代码,这是我们不允许的。

所以我的问题是:如何使用 gradle 文件中的 apply plugin: something 命令仅应用于我的一种风格?

【问题讨论】:

【参考方案1】:

使用此代码:

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

getGradle().getStartParameter().getTaskRequests().toString() 返回类似 [DefaultTaskExecutionRequestargs=[:app:generateDevelopDebugSources],projectPath='null'] 的内容,因此在 cmets 中声明 Develop 必须以大写字母开头。

【讨论】:

此代码有效。但是需要注意风味名称的首字母大写 从右侧的 gradle 菜单中单击 assemble 时不起作用...手动安装应用程序时.. 这几乎对我有用,但我注意到当输入 ./gradlew assembleDe 时,getTaskRequests 中的值也是 assembleDe - 当我预计它已经扩展到 assembleDebug 代码不起作用。这将打印一个空数组 "[]" println("$getGradle().getStartParameter().getTaskRequests().toString()") 我确认了@Pavel 的评论。似乎可以在 Android Studio 中工作,但从命令行运行时却不行。这就是我得到的全部:[DefaultTaskExecutionRequestargs=[build],projectPath='null']【参考方案2】:

尝试了不同的解决方案,但没有一个对我有用。这是我想出的,并且在我测试的范围内似乎有效:

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'
    

【讨论】:

这是唯一对我有用的解决方案。但是,我将您的 if 更改为 if (getGradle().getStartParameter().getTaskNames().stream().filter it.toLowerCase().contains(flavor.name) .count() > 0 && flavor.ext.useGoogleGcm) 它似乎没有为我执行。我没有以某种方式获得日志,只是没有应用插件。在 if 语句之前添加了额外的日志,仍然没有乐趣。 似乎使用 .all 而不是 .each 可以解决问题。【参考方案3】:
    定义变量 - def fl

    在您的 Flavors(和/或构建)中初始化变量

        productFlavors 
    
                freeFlavour 
                    (...)
                    fl = "free"
                
    
                paidFlavour 
                    (...)
                    fl = "paid"
                
            
    

    使用 if 语句 -

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

【讨论】:

这似乎不起作用。在我的例子中(假设我正在调用 assembleFree),两个块都被执行,所以 fl 的值是最后声明的风味的名称。还有其他想法吗? 这将在配置时解决,并且由于这需要遍历它,fl 将包含最后一个值。【参考方案4】:

我只是在应用级别 build.gradle 的风味中使用了apply plugin: 'com.google.gms.google-services',它工作得很好。

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

无需额外步骤。

【讨论】:

我建议其他人使用这个 哇,就这么简单! 我将它用于确切的这个用例。它对我有用。 这适用于通过 Android Studio 构建,但不适用于使用 Jenkins 构建。 这是一个语法作弊,插件在构建其他产品风格时仍然涉及,用android gradle插件版本4.2.0测试【参考方案5】:

我找到了解决方案,但目前还不是最好的。 所以我不再确定,我最初想做的事情是可能的。 gradle 文件评估和选择正确的风格和构建类型处于 gradle 构建的不同阶段,所以我所做的是:

我使用命令行中的构建参数。当该参数为真时,我应用插件,当它甚至不存在时,我也应用它(用于 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 检查无效。【参考方案6】:

升级到 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”的任务已针对正确的任务运行,而对于错误的任务则跳过。如果您的构建抱怨toCapitalize,您可以在it.nameflavor.name 上使用toLowerCase

【讨论】:

【参考方案7】:

对于 Google Services 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

【讨论】:

以上是关于如何将插件应用于gradle中的一种风格?的主要内容,如果未能解决你的问题,请参考以下文章

Gradle:如何构建不同构建类型的不同风格?

Android studio版本对用的gradle版本和插件版本(注意事项)

我如何知道android gradle插件的applicationVariants中的属性?

Gradle 总是从最后一种风格中的 buildType 中获取值

Qigsaw源码之Gradle插件解析

内置 gradle 插件的版本号是多少?