如何将插件应用于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.name
和flavor.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中的一种风格?的主要内容,如果未能解决你的问题,请参考以下文章
Android studio版本对用的gradle版本和插件版本(注意事项)
我如何知道android gradle插件的applicationVariants中的属性?