使用Android Studio/Gradle从git describe自动版本化Android项目

Mik*_*unt 36 git android auto-versioning gradle android-build

我已经进行了广泛的搜索,但可能由于Android Studio和Gradle的新功能,我还没有找到任何关于如何执行此操作的说明.我想基本上完成本文中描述的内容,但使用Android Studio,Gradle和Windows而不是Eclipse和Linux.

mov*_*y00 39

将以下内容放在项目的build.gradle文件中.无需直接修改清单:Google为其配置提供了必要的挂钩.

def getVersionCode = { ->
    try {
        def code = new ByteArrayOutputStream()
        exec {
            commandLine 'git', 'tag', '--list'
            standardOutput = code
        }
        return code.toString().split("\n").size()
    }
    catch (ignored) {
        return -1;
    }
}

def getVersionName = { ->
    try {
        def stdout = new ByteArrayOutputStream()
        exec {
            commandLine 'git', 'describe', '--tags', '--dirty'
            standardOutput = stdout
        }
        return stdout.toString().trim()
    }
    catch (ignored) {
        return null;
    }
}
android {
    defaultConfig {
        versionCode getVersionCode()
        versionName getVersionName()
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,如果计算机上未安装git,或者获取版本名称/代码时出现其他错误,则默认为Android清单中的内容.

  • @ moveaway00而不是使用`git tag --list | wc -l`是不是更好的只使用`git rev-list --first-parent --count master`这给出了初始版本的提交数量,我相信实际上是版本代码.使用标签风险更大,因为标签还有一个使用用例,并在rebase/squashes期间抛出引用 (3认同)
  • 使用信息的示例java代码.PackageInfo packageInfo = this.getPackageManager().getPackageInfo(this.getPackageName(),PackageManager.GET_ACTIVITIES); Log.d(TAG,Integer.toString(packageInfo.versionCode)); Log.d(TAG,packageInfo.versionName); (2认同)
  • 为了澄清,这可以在Project> app> build.gradle中进行,而不是顶级build.gradle (2认同)

Léo*_*Lam 27

在看到moveaway00的回答Avinash R对该答案的评论后,我最终使用了这个:

apply plugin: 'android'

def getVersionCode = { ->
    try {
        def stdout = new ByteArrayOutputStream()
        exec {
            commandLine 'git', 'rev-list', '--first-parent', '--count', 'master'
            standardOutput = stdout
        }
        return Integer.parseInt(stdout.toString().trim())
    }
    catch (ignored) {
        return -1;
    }
}

def getVersionName = { ->
    try {
        def stdout = new ByteArrayOutputStream()
        exec {
            commandLine 'git', 'describe', '--tags', '--dirty'
            standardOutput = stdout
        }
        return stdout.toString().trim()
    }
    catch (ignored) {
        return null;
    }
}

android {
    defaultConfig {
        versionCode getVersionCode()
        versionName getVersionName()
    }
}
Run Code Online (Sandbox Code Playgroud)

我编辑了moveaway00的代码也包含了Avinash R的评论:版本代码现在是提交的数量master,因为这是版本代码应该是什么.

请注意,我不需要在清单中指定版本代码和版本名称,Gradle负责处理它.

  • 使用HEAD代替分支名称是很好的.因此gradle将使用当前分支的修订计数 (3认同)
  • @Vetalll,在这种情况下使用 `HEAD` 不好。这是因为如果您使用主题分支方法(如 git-flow)进行开发,主题分支将有更多提交,这意味着当分支与 master 合并时,versionCode 将被降级由于存在`--first-parent`。因此,为了让您和您的开发伙伴不必在每次将主题分支合并到 master 时卸载应用程序,请从“master”(或您的发布分支)中获取“versionCode” (2认同)

Die*_*ego 24

一种更恰当和精益的方式来实现最近获得牵引力的结果将是通过Groovy JGit绑定使用gradle git集成.因为它使用JGit甚至不需要安装git来工作.

这是一个显示类似(但在gitVersionName字符串中有一些附加信息)解决方案的基本示例:

buildscript {
  dependencies {
    classpath 'org.ajoberstar:grgit:1.4.+'
  }
}
ext {
  git = org.ajoberstar.grgit.Grgit.open()
  gitVersionCode = git.tag.list().size()
  gitVersionName = "${git.describe()}"
}
android {
  defaultConfig {
    versionCode gitVersionCode
    versionName gitVersionName
  }
}
[...]
Run Code Online (Sandbox Code Playgroud)

正如您在Grgit API文档看到的,描述操作提供了除历史记录中可访问的最新标记之外的其他信息:

找到可从HEAD访问的最新标记.如果标记指向提交,则仅显示标记.否则,它将标记名称后缀为标记对象顶部的附加提交数和最近提交的缩写对象名称.

无论如何,它不会告诉状态是否脏.通过查看repo 的干净状态可以轻松添加此信息,如果不干净则附加字符串.


gla*_*ded 10

另一种方式:

https://github.com/gladed/gradle-android-git-version是一个新的gradle插件,可以自动计算安卓友好的版本名称和版本代码.

它处理许多使用已接受的解决方案无法实现的特殊情况:

  • 同一个仓库中多个项目的版本标签
  • 扩展版本代码如1002003 for 1.2.3
  • 用于轻松提取CI工具的版本信息的gradle任务
  • 等等

免责声明:我写了.


jpo*_*s18 7

这是另一种需要语句而不是函数来访问命令行的解决方案。警告:*nix 唯一解决方案

def gitSha = 'git rev-parse --short HEAD'.execute([], project.rootDir).text.trim()

// Auto-incrementing commit count based on counting commits to master (Build #543)
def commitCount = Integer.parseInt('git rev-list master --count'.execute([], project.rootDir).text.trim())

// I want to use git tags as my version names (1.2.2)
def gitCurrentTag = 'git describe --tags --abbrev=0'.execute([], project.rootDir).text.trim()

android {
    compileSdkVersion 22
    buildToolsVersion "22.0.1"

    defaultConfig {
        applicationId "com.some.app"
        minSdkVersion 16
        targetSdkVersion 22
        versionCode commitCount
        versionName gitCurrentTag

        buildConfigField "String", "GIT_SHA", "\"${gitSha}\""

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

    }
}
Run Code Online (Sandbox Code Playgroud)