而且,为什么要这样的东西? 你可能会问你自己。
好吧,让我们从回答另一个问题开始。你生成的所有apk都一样么?当然不是。应用名称(又称versionName)用于引用应用程序的具体版本,如2.3,13.1.0_2342,42.2-build.4424或其他。对发布版可能是足够公平,但是当应用处于开发阶段,应用名应当提供更多的信息。
我发现这个方法在我的团队中非常有用,因为每个团队成员正在开发一个不同的功能,所以应用程序将根据该功能进行重命名,所以任何构建都可以由利益相关者标记,如测试人员,产品所有者或持续集成系统。
自定义Gradle插件
作为一个Android开发者,我们每天都使用一些gradle插件,例如com.android.application是Android应用构建的gradle插件。插件遵循一些约定或提供特定的配置来处理并扩展我们的构建过程。其实这就是我们想要的,修改默认构建过程来改变应用的versionName。
这有3个不同的方式来创建gradle插件(在这里可以检查文档),但我们打算选择buildSrc文件夹,主要是它创建简单并包含在你的仓库。另一方面,插件将添加到你的项目并且不能重复使用。
buildSrc文件夹
首先我们需要创建适当的文件夹结构,让gradle编译buildSrc文件夹代码。 注意,同步之后,gradle会理解groovy文件夹,它将被标记为如此。 因此,构建过程将编译此文件夹中的每个源代码。
我们还将在所需的包文件夹下创建插件文件(CustomPlugin.groovy)。 插件的主要目的是创建一个gradle任务,其实际上负责更改app versionName,并将其添加到任务层次结构中。 在编写插件之前,我们将要创建gradle任务,其将修改应用程序名称。
Gradle任务
你可能知道,任务是构建过程中的一项冤死工作。 在下一步中,我们将创建一个自定义任务,该任务需要Android构建变体并更改versionName属性。
作为任务,我们需要从DefaultTask中扩展它,它强制我们创建默认的run()方法。
让我们看看任务如何定义。
class RenameAppVersionNameTask extends DefaultTask {
@TaskAction
def run() {
project.configure(project) {
// Check if plugin works on an Android module
if (it.hasProperty("android")) {
// Iterate over app build variants (build types + flavors)
project.android.applicationVariants.all { variant ->
// Only change debug build type variants
if (variant.buildType.name == project.android.buildTypes.debug.name) {
// Rename versionName
def customVersionName = variant.mergedFlavor.versionName
variant.mergedFlavor.versionName = customVersionName + " custom"
}
}
}
}
}
RenameAppVersionNameTask() {
group = 'customPlugin'
description = 'Renames versionName of the app depends on the current git branch name'
}
}
注意:此任务仅为versionName添加自定义后缀,但在这里,您可以重命名为所需的任何约定。 我稍后会给你一个例子。
任务依赖
我们已经设计了修改应用程序版本名称的任务,所以现在是实现gradle插件的时候了,并且将我们的新任务添加到构建依赖关系中。
由于Android构建包含应用程序的versionName信息,所以我们必须定义任务依赖关系,以便在Android构建开始之前触发它。 有一个名为preBuild的gradle任务可以完美的完成这一要求。
class CustomPlugin implements Plugin<Project> {
@Override
void apply(Project project) {
project.task('renameAppVersionName', type: RenameAppVersionNameTask)
project.tasks.getByName('preBuild').dependsOn('renameAppVersionName')
}
}
插件已经可以使用了。
使用插件
一旦创建了插件,就可以将其使用到Android应用模块(甚至Android库模块)。
只需在应用的build.gradle文件中包含apply语句,就像任何其他插件一样。
...
apply plugin: CustomPlugin
...
奖励:用git分支重命名
正如你所看到的,gradle任务仅能为应用程序版本名称添加一个后缀,但是我们可以将其更新成任何所需的命名约定。
例如,在我的团队中,我们正在使用git跟随gitflow。 这意味着我们正在开发的每个功能创建一个分支。 此外,分支名称基于在该特征的id(在这种情况下为Jira问题id)的前缀的约定。
任务将取出分支名称,提取功能ID并将其添加到versionName。
class RenameAppVersionNameTask extends DefaultTask {
...
static def renameDebugAppVersionName(variant) {
def customVersionName = variant.mergedFlavor.versionName + getCurrentBranchCodeName()
variant.mergedFlavor.versionName = customVersionName
println "${variant.name} version name: ${customVersionName}"
}
static def getCurrentBranchCodeName() {
def currentBranchName = 'git rev-parse --abbrev-ref HEAD'.execute().text.trim()
String branchTicketCode = "";
Matcher matcher = currentBranchName =~ /write here your regex/
if (matcher.size() > 0) {
branchTicketCode = matcher[0][1]
}
return branchTicketCode
}
}
最后,我们可以通过应用程序名称来识别构建,并确定相关的功能,例如在Fabric Beta或测试设备中。 像2.3_P-23或4.1.2_P-292这样的名字更容易让我们知道在说什么。