使用Git和Eclipse为您的Android应用程序编号的自动版本

Dob*_*bbo 14 versioning git android

我相信计算机是做重复性任务的最佳选择.我当然不是,我要么忘记,要么(大多数时候)不以一致的方式做事 - 这不是我想要的.

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

我发现这个Stackoverflow帖子在提出解决方案时非常有用,但是我花了一段时间对它进行微调,以便它按照我想要的方式工作.早期的尝试有时会导致继续建设,这是一个痛苦.所以我想我会在这里发布我的解决方案,希望别人会发现它有用.

Dob*_*bbo 14

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

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

因为android:versionCode需要一个数字.这需要时钟版本而不是开发版本,并作为每一个版本都会有一个版本字符串标签我简单地计算这些.我总是在表单v<major>.<minor>[.<patch>]中标记我的版本<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
Run Code Online (Sandbox Code Playgroud)

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

1).右键单击项目库,选择"属性",然后选择"构建器".

2).点击"新建"按钮,然后选择"程序"选项.

3).将您的版本命名为"<project> Auto Version".该字符串在所有项目中都必须是唯一的.

4).配置"Main"选项卡如下:

图4a).在"位置"部分中,使用"浏览文件系统"并导航并选择脚本文件.

图4b).在"工作目录"部分中,使用"浏览工作区"选择项目.

5).在"刷新"选项卡中取消选中"完成后刷新资源".

6).不要在"环境"选项卡中设置任何变量.

7).在"构建选项"选项卡中:

7A).确保选中"在手动构建期间",并且

7B).还会勾选"在自动构建期间".

7C).我现在还有其他一切未被选中.我甚至没有为它分配一个控制台.老鹰目瞪口呆可能已经发现脚本确实输出了一些信息,但现在我已经开始工作了,我只想让这个东西在没有打扰我的情况下默默地运行.

8).好的是构建设置,然后将构建器放在"Android Pre-Compile"和"Java Builder"之间.

回到开发应用程序的安全性,知道他们正在正确版本化,并检查您的应用程序的信息.不是那个版本号很酷.:-)

史蒂夫

  • 你让我今天一整天都感觉很好!经过两次小小的调整后,上面的工作完美无瑕.我不得不'chmod + x'这个version.sh文件,并且至少在我的git-history中标记了一个提交以使其正常工作! (3认同)

Avi*_*h R 12

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

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

  • 用于计算version.code:

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

    这遵循版本指南.因为它有效地从初始提交(包括)中查找提交的数量,该提交总是从先前版本递增.

  • 用于计算version.name:

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

执行:

build.xml 通常导入一个名为的自定义ant脚本 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>
Run Code Online (Sandbox Code Playgroud)

会做的.

在坚果壳,它只是取代了android.versionCode,并android.versionName与当前版本的代码和名称,存储在饭桶.

注意事项

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

请享用.

参考文献

重要编辑

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

PS:与AS用户相关:使用Android Studio/Gradle从git describe自动版本化Android项目

  • 请注意,这应该也是一个跨平台的解决方案. (2认同)

Sea*_*ean 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")
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)