14

我相信计算机是完成重复性任务的最佳工具。我当然不是,我要么忘记,要么(大部分)不以一致的方式做事——这不是我想要的。

我可能会做的一件事是在发布新版本的 Android 应用程序时忘记在清单中更新版本信息。过去,我使用过具有自动版本编号功能的已配置构建系统,并且我已经习惯了它(或者我可能变得懒惰了)。

我发现这篇Stackoverflow 帖子在提出解决方案时非常有用,但我花了一些时间来微调它,让它按照我想要的方式工作。早期的尝试有时会导致继续建设,这是一种痛苦。所以我想我会在这里发布我的解决方案,希望其他人会发现它有用。

4

4 回答 4

15

该解决方案是在 Linux 上开发的。我确信熟练的 Windows 和 Mac 开发人员可以使其适应他们的平台,但我不是这样的开发人员。Linux 是我的技能所在。

git describe --dirtyGit 在命令中有一个很好的特性。它向下扫描提交日志并找到标记,然后从那里构建一个版本字符串。如果这是一个“生产构建”,其中最后一次提交已被标记并且所有文件都已被签入,那么这就是您的版本字符串。如果这是一个开发版本,那么最后一个标签会附加额外提交的数量和一个缩写的哈希码。该--dirty标志只是锦上添花:dirty如果有任何修改过的文件尚未提交,它会附加单词。这非常适合android:versionName清单文件中的属性。

对于android:versionCodea 数字是必需的。这需要为发布而不是开发构建计时,并且由于每个发布都会有一个带有版本字符串的标签,所以我只计算这些。v<major>.<minor>[.<patch>]我总是以where<major>和只是数字<minor>的形式标记我的版本。<patch>因此,计数以小写“v”开头后跟数字的标签就是这里真正需要的。

在使用模板清单文件后,我发现最好的方法是简单地使用项目库中的 AndroidManifest.xml 文件,使用流编辑器进行编辑sed并将结果存放在 bin/AndroidManifest.xml 中。

所以我开发了下面的脚本,将它放在与我的项目相同级别的脚本文件夹中(以便它们都可以共享相同的脚本),然后在 Eclipse 中配置一个自定义构建器。

有我称之为的脚本version.sh

#/bin/bash

echo "Auto Version: `pwd`"

CODE=`git tag | grep -c ^v[0-9]`
NAME=`git describe --dirty | sed -e 's/^v//'`
COMMITS=`echo ${NAME} | sed -e 's/[0-9\.]*//'`

if [ "x${COMMITS}x" = "xx" ] ; then
    VERSION="${NAME}"
else
    BRANCH=" (`git branch | grep "^\*" | sed -e 's/^..//'`)"
    VERSION="${NAME}${BRANCH}"
fi

echo "   Code: ${CODE}"
echo "   Ver:  ${VERSION}"

cat AndroidManifest.xml | \
    sed -e "s/android:versionCode=\"[0-9][0-9]*\"/android:versionCode=\"${CODE}\"/" \
        -e "s/android:versionName=\".*\"/android:versionName=\"${VERSION}\"/" \
    > bin/AndroidManifest.xml

exit 0

要在此处配置构建器,请执行以下步骤:

1)。右键单击项目库并选择“属性”,然后选择“构建器”。

2)。点击“新建”按钮并选择“程序”选项。

3)。将您的版本命名为“<project> Auto Version”。此字符串需要在所有项目中都是唯一的。

4)。配置“主要”选项卡,如下所示:

4a)。在“位置”部分使用“浏览文件系统”并导航并选择脚本文件。

4b)。在“工作目录”部分使用“浏览工作区”选择项目。

5)。在“刷新”选项卡中取消选中“完成后刷新资源”。

6)。不要在“环境”选项卡中设置任何变量。

7)。在“构建选项”选项卡中:

7a)。确保勾选“在手动构建期间”,并且

7b)。“在自动构建期间”也被勾选。

7c)。我现在没有选择其他所有内容。我什至没有为它分配控制台。鹰眼可能已经发现脚本确实输出了一些信息,但现在我已经让它工作了,我只想让这个东西安静地运行而不打扰我。

8)。好的构建设置,然后将您的构建器定位在“Android Pre-Compile”和“Java Builder”之间。

在知道它们已正确版本化的情况下,返回安全地开发您的应用程序,并查看您的应用程序的信息。那个版本号是不是很酷。:-)

史蒂夫

于 2013-02-15T12:51:46.707 回答
12

想法(使用 ant 和 git 可执行文件)

好的,这是一种新颖的方法:

  • 计算version.code

    git rev-list master --first-parent --count

    这遵循版本控制指南。因为它有效地从初始提交(包括)中找到提交数量,该提交数量总是从以前的版本增加。

  • 用于计算version.name

    git describe --tags --dirty --abbrev=7

执行:

build.xml通常会导入一个名为custom_rules.xml

所以将脚本的内容制作为:

<?xml version="1.0" encoding="UTF-8"?>
<project name="application-custom">

<macrodef name="git" taskname="@{taskname}">
    <attribute name="command" />
    <attribute name="dir" default="" />
    <attribute name="property" default="" />
    <attribute name="taskname" default="" />
    <attribute name="failonerror" default="on" />
    <element name="args" optional="true" />
    <sequential>
        <exec executable="git" dir="@{dir}" outputproperty="@{property}" 
            failifexecutionfails="@{failonerror}" failonerror="@{failonerror}">
            <arg value="@{command}" />
            <args/>
        </exec>
    </sequential>
</macrodef>

<target name="-pre-build">
    <git command="rev-list" property="versioning.code" taskname="versioning">
        <args>
            <arg value="master" />
            <arg value="--first-parent" />
            <arg value="--count" />
        </args>
    </git>
    <git command="describe" property="versioning.name" taskname="versioning">
        <args>
            <arg value="--tags" />
            <arg value="--dirty" />
            <arg value="--abbrev=7" />
        </args>
    </git>
    <echo level="info" taskname="versioning">${versioning.code}, ${versioning.name}</echo>
    <replaceregexp file="AndroidManifest.xml" match='android:versionCode=".*"' replace='android:versionCode="${versioning.code}"' />
    <replaceregexp file="AndroidManifest.xml" match='android:versionName=".*"' replace='android:versionName="${versioning.name}"' />
</target>

<target name="-post-build" >
    <replaceregexp file="AndroidManifest.xml" match='android:versionCode=".*"' replace='android:versionCode="0"' />
    <replaceregexp file="AndroidManifest.xml" match='android:versionName=".*"' replace='android:versionName="0"' />
</target>

会做的。

简而言之,它只是将android.versionCodeand替换为android.versionName存储在 git 中的当前版本代码和名称。

注意事项

  • 初始版本代码和名称在构建完成时设置为 0。如果您需要它,请替换-post-build目标中的零,或者(尽管我非常怀疑您是否需要它)您可以使其可配置并将其放置在某个属性中(文件或嵌入;您的选择)
  • 如果构建失败或中止,版本将保持原样。(虽然我非常怀疑它是否有任何问题,只需还原文件!)

享受。

参考文献

重要编辑

  1. 防止HEAD用于计算内部版本号;在开发期间进行构建时会导致版本降级问题,然后在安装稳定版本时(或在进行 beta 到主要版本的转换时)。使用master(或用于生产构建的分支) ref 代替。

PS:与 AS 用户相关:使用 Android Studio/Gradle 从 git describe 自动对 Android 项目进行版本控制

于 2013-12-14T13:56:35.677 回答
8

使用 Android Studio (Gradle):

android {
    defaultConfig {
        ...
        // Fetch the version according to git latest tag and "how far are we from last tag"
        def longVersionName = "git -C ${rootDir} describe --tags --long".execute().text.trim()
        def (fullVersionTag, versionBuild, gitSha) = longVersionName.tokenize('-')
        def(versionMajor, versionMinor, versionPatch) = fullVersionTag.tokenize('.')

        // Set the version name
        versionName "$versionMajor.$versionMinor.$versionPatch($versionBuild)"

        // Turn the version name into a version code
        versionCode versionMajor.toInteger() * 100000 +
                versionMinor.toInteger() * 10000 +
                versionPatch.toInteger() * 1000 +
                versionBuild.toInteger()

        // Friendly print the version output to the Gradle console
        printf("\n--------" + "VERSION DATA--------" + "\n" + "- CODE: " + versionCode + "\n" + 
               "- NAME: " + versionName + "\n----------------------------\n")
        ...
    }
}
于 2014-09-07T06:10:05.777 回答
0
'  for windows
'   preBuildMy.cmd  include  repVer.vbs 

' repVer.vbs :

Dim objFileSystem, objOutputFile
Dim objInputFile
Dim sText,gitFile

FileName = "./bin/AndroidManifest.xml"
'  gitFile = ".\..\.git\refs\heads\master"
gitFile = ".\..\.git\refs\remotes\origin\master"

Set objFileSystem = CreateObject("Scripting.fileSystemObject")

set objInputFile= objFileSystem.OpenTextFile(FileName)
sText= objInputFile.ReadAll

set objOutputFile = objFileSystem.CreateTextFile(FileName , TRUE)

set objInputFile= objFileSystem.OpenTextFile(gitFile)
refText= objInputFile.ReadAll

sText = Replace(sText,"v1.0","v 1.0 " & Now & " ref=" & mid(refText,1,7))

objOutputFile.WriteLine(sText)

objOutputFile.Close

Set objFileSystem = Nothing
WScript.Quit(0)
于 2013-03-03T14:20:13.397 回答