5

让 IDE 自动增加内部版本号是一个长期讨论的问题 - 我总是很惊讶,(对我而言)看起来如此基本的东西却有如此多的工作。

这个主题得分最高的问题和答案(相当多)在这里: https ://stackoverflow.com/a/8156809/150016 我的问题是解决方案取决于.net,我宁愿避免使用 . Eclipse 解决方案的网络依赖。我还想避免对 VCS 的任何依赖。

因此,我正在寻找一种可移植且“Eclipse-ish”的解决方案。我认为最好的候选人是 Ant 解决方案(我将发布)或类似于上面链接答案中的 dotNet 应用程序的 Java 应用程序。

(我没有添加我对该问题的答案,因为它有一个已被接受的答案并且已经是一个很长的帖子。如果版主愿意,我将删除这个问题并将我的答案添加到上面的问题中。)

我希望有一些相对简单的东西,但我认为这个问题的任何解决方案都不是很简单。

4

6 回答 6

8

在项目的属性对话框中,在 Builders 下,您可以配置脚本以在构建 apk 之前运行。

在属性对话框中,从左侧的列表中选择 Builders。单击新建以添加新脚本。在弹出的对话框中,选择程序。在随后的对话框中,在 Name 字段中调用您喜欢的 Builder Program。将脚本的路径放在位置字段中。在工作目录字段中给它一个工作目录。请注意,您可以在这些字段中指定变量(例如,我们${build_project:/libs/update_version.sh}用来引用项目 lib 目录中的脚本)。

您会希望它在任何其他构建器之前运行,因此使用向上按钮将其移动到列表顶部。

在 Dialog 的 Build Options 选项卡上(位于顶部的 Name 字段下方),您可以选择希望该程序何时运行的选项。

我假设这里有 Linux、Unix 或 MacOS 之类的东西。在这些系统中,您可以使用 grep 或其变体来获取当前版本代码,将其递增,然后使用 awk 或类似方法来相应地修改文件。或者,您可以编写一个 Ruby、Python、Perl 等脚本来替换 AndroidManifest.xml 文件中的 versionCode。我想在 Windows 上有等效的工具,但我对那个环境不是很熟悉。

于 2012-05-25T19:32:06.937 回答
7

您是否尝试过“Maven-ise”您的 android 项目构建?

如果你使用"maven-android-plugin",你可以使用 pom.xml 的 "version" 标签来跟踪你的项目构建。

在 pom.xml 中,您可以使用“versions-maven-plugin”增加构建版本

要将增加的内部版本号反映到您的 AndroidManifest.xml 中,您可以在 pom 文件中使用同步版本技术。

这样,您可以通过在每次构建应用程序时运行“versions-maven-plugin”来自动增加 android 项目构建号。与 Ant 解决方案一样,该解决方案也是可移植的。

我希望这也可以解决您提到的问题(以及我所理解的)。如果缺少某些内容,请纠正我。

于 2012-05-25T20:09:03.930 回答
3

这是一个使用 Ant 的解决方案。我必须承认,设置 Ant 有点麻烦,但它似乎是 Eclipse 的一个广泛使用且功能强大的附件,所以我相信它在其他方面对我来说会很有价值。

Ant 是在不使用 Eclipse 的情况下构建 Android SDK 应用程序的首选解决方案(如此处所述),但它不是 ADT 的一部分,因此如果您刚刚使用 Eclipse,您可能不会拥有它。

所以,第一步是从这里下载并安装 Ant 。

接下来将 Ant 添加到您的路径中,并确保您的路径也指向 JDK(而不是 JRE)。在 Windows 上,我发现我还必须创建 JAVA_HOME 并将其指向 JDK 的根目录。

我们只需要 Ant 进行自动增量步骤 - 目的不是替换 Eclipse 并将其用于整个构建 - 但朝这个方向执行一些步骤以确保 Ant 正常工作很有用。因此,转到项目的根目录并键入

> android update project --path .

这将为您的项目创建一个 build.xml。一旦我做到了,我就能做到

> ant release

Ant 构建了我的项目。如果你想继续朝着这个方向前进,我发现这篇文章很有用。

接下来,我编辑了我的项目的新 build.xml 并添加了以下任务(它可以去任何地方,只是不在另一个任务/目标的中间)

 <target name="update.buildnum">
      <buildnumber/>
      <!-- this task creates (and increments) Ant property 'build.number' which I use below -->
      <echo>Current build number:${build.number}</echo>         
      <echoxml file="res/values/buildnum.xml">
                <resources>
                    <string name="buildnum">${build.number}</string>
                </resources>                    
      </echoxml>
 </target>

上面使用的任务会自动增加项目根目录中名为“build.number”的文件(它将创建)中的内部版本号。上述任务的其余部分将当前内部版本号放入资源字符串中,以便您的应用程序可以使用以下代码检索它:

String build = context.getString( com.your.app.R.string. buildnum );
int appBuild = ( int ) Integer.parseInt( build ); 

有些人更喜欢将内部版本号写入 AndroidManifest.xml 中的应用程序代码的解决方案。 这是一个包含执行此任务的任务的答案,但它需要一个 3rd 方 Ant 任务(xmltask),而且我有点犹豫是否让第 3 方任务在每个构建中修改我的清单(现​​在非常庞大) . 如果您决定使用该任务,那么获取内部版本号的相应 Android 代码将是:

String packageName = ctx.getPackageName();
PackageInfo pInfo = ctx.getPackageManager().getPackageInfo( packageName, 0);
int appVer = pInfo.versionCode;

最后,您需要在每次构建时让 Eclipse 运行这个 Ant 任务。

转到项目的属性,找到 Builders,然后单击按钮添加一个新的 Builder。这里有很多选项,但您只需要指定几个。

  • 通过设置Name:字段为构建器命名。
  • 选择构建文件: . 我使用“浏览工作区”选项来选择它,然后用“${workspace_loc:/appname/build.xml}”填充该字段
  • 从目标选项卡上的列表中选择目标。在我的情况下,我必须删除“帮助”任务(上面生成的 build.mxl 中的默认任务),然后添加“build.number”任务。我建议你只为Manual Build:设定一个目标。

我将新的 Builder 移动为第一个构建步骤。

此解决方案的一个问题是,每次让 Eclipse 部署(运行)应用程序时,它都被视为新的手动构建,即使项目没有更改。因此,如果您将应用程序部署到多个设备,每个设备将具有不同的内部版本和自己的内部版本号。可以稍微改善这个问题的一件事是,谷歌表示未来的 ADT 将允许在一个操作中进行多次部署。

这(上图)在 Win7 32 位上使用 Ant 1.8.4、Eclipse Indigo SR2 (3.7.2)、ADT 20 preview 2 和 SDK Tools 20 进行了测试。

于 2012-05-25T19:40:05.803 回答
1

我的解决方案基于使用 Ant(没有 XMLTask)

<property name="version.file" value="version.properties"/>
<property name="manifest.file" value="AndroidManifest.xml"/>
<!--build.slot: 0.1.2.3.4.5-->
<property name="build.slot" value="2"/>

<target name="all">
    <antcall target="increment.build"/>
    <antcall target="update.manifest"/>
</target>

<target name="increment.build">
    <propertyfile file="${version.file}">
        <entry key="build.no" type="int" default="0" operation="+" value="1" />
    </propertyfile>
</target>

<scriptdef name="setBuildNo" language="javascript">
    <attribute name="verName" />
    <attribute name="buildNo" />
    <attribute name="buildSlot" />
    <attribute name="property" />
    <![CDATA[
        var verNums = attributes.get("vername").split(".");
        var buildNo = attributes.get("buildno");
        var buildSlot = attributes.get("buildslot");
        if (!(buildSlot > 1 && buildSlot < 10))
            buildSlot = 2;
        var newVer = "";
        for (var i = 0; i < Math.min(verNums.length, buildSlot); i++)
            newVer += (verNums[i].trim() || "0") + ".";
        for (var i = verNums.length; i < buildSlot; i++)
            newVer += "0" + ".";
        project.setProperty(attributes.get("property"), newVer + buildNo);
    ]]>
</scriptdef>

<target name="debug">
    <setBuildNo verName="1" buildNo="999" property="a"/>
    <setBuildNo verName="2." buildNo="999" property="b"/>
    <setBuildNo verName="3.3" buildNo="999" property="c"/>
    <setBuildNo verName="4.4." buildNo="999" property="d"/>
    <setBuildNo verName="5.5.5" buildNo="999" property="e"/>
    <setBuildNo verName="6.6.6." buildNo="999" property="f"/>
    <setBuildNo verName="7.7.7.7" buildNo="999" property="g"/>

    <echo>1 =&gt; ${a}</echo>
    <echo>2. =&gt; ${b}</echo>
    <echo>3.3 =&gt; ${c}</echo>
    <echo>4.4. =&gt; ${d}</echo>
    <echo>5.5.5 =&gt; ${e}</echo>
    <echo>6.6.6. =&gt; ${f}</echo>
    <echo>7.7.7.7 =&gt; ${g}</echo>

</target>

<target name="update.manifest">

    <fail message="File not found: &quot;${manifest.file}&quot;" status="1">
        <condition>
            <not>
                <available file="${manifest.file}" />
            </not>
        </condition>
    </fail>

    <!-- Reads build version -->
    <loadproperties srcfile="${version.file}">
        <filterchain>
            <linecontains>
                <contains value="build.no="/>
            </linecontains>
        </filterchain>
    </loadproperties>

    <!-- Reads versionName from AndroidManifest -->
    <xmlproperty file="${manifest.file}" collapseAttributes="true"/>
    <fail unless="manifest.android:versionName" message="Attribute &quot;android:versionName&quot; undefined into &quot;${manifest.file}&quot;" status="1"/>
    <property name="version.name" value="${manifest.android:versionName}"/>

    <!-- Create a new version -->
    <setBuildNo verName="${version.name}" buildNo="${build.no}" buildSlot="${build.slot}" property="new.version.name"/>

    <!-- Replaces using regexp -->
    <replaceregexp
        file="${manifest.file}"
        match="android:versionName.*=.*&quot;.*${version.name}.*&quot;"
        replace="android:versionName=&quot;${new.version.name}&quot;"/>

    <!-- Replaces for check and generates a exception (if not found version) -->
    <replace
        file="${manifest.file}"
        token="android:versionName=&quot;${new.version.name}&quot;"
        value="android:versionName=&quot;${new.version.name}&quot;"
        failOnNoReplacements="true"/>

    <!--<echo>${version.file}</echo>
    <echo>${manifest.file}</echo>-->
    <echo>Auto Increment Build: ${version.name} =&gt; ${new.version.name}</echo>

</target>

使用

蚂蚁 [-Dmanifest.file=<文件>] [-Dversion.file=<文件>] [-Dbuild.slot=<编号>]
    -Dmanifest.file - AndroidManifest.xml 的路径和文件名。默认值:AndroidManifest.xml 在带有 build.xml 的文件夹中
    -Dversion.file - 存储版本号的路径和文件名。默认值:带有 build.xml 的 version.properties 文件夹
    -Dbuild.slot - 版本数组中内部版本号的位置。默认值:2,即XXbuild。

Eclipse中的自动增量构建

项目 | 属性 | 建筑商 | 新 | 蚂蚁构建
    主要的
        构建文件
            <路径>/build.xml
        论据
            -Dmanifest.file=${workspace_loc://AndroidManifest.xml} -Dversion.file=${workspace_loc://version.properties}
    刷新
        [x] 完成后刷新资源
        (*) 指定资源
            [指定资源]
                <项目>
                    [x] AndroidManifest.xml
    构建选项
        [x] 指定相关资源的工作集
            [指定资源]
                <项目>
                    [x] 资源
                    [x] 源代码
                    [x] AndroidManifest.xml
于 2014-06-23T08:37:47.337 回答
0

我的解决方案使用了在其他答案、XMLTask 和 Groovy 中找到的一些代码来自动增加内部版本号。我还包括了一个规则来执行 git 提交和标记,以将内部版本号链接到版本控制中的特定点 - 对于错误跟踪很有用。

 <taskdef name="xmltask" classname="com.oopsconsultancy.xmltask.ant.XmlTask"/>


  <path id="groovy.classpath">
    <fileset dir="/Users/deepwinter1/.gvm/groovy/current/lib/">
      <include name="*.jar"/>
    </fileset>
  </path>

  <taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy">
    <classpath refid="groovy.classpath"/>
  </taskdef>

  <target name="update.build.number">
    <xmltask source="AndroidManifest.xml">
      <copy path="manifest/@android:versionCode" property="buildNum"/>
    </xmltask>
    <groovy>
      buildNum = Integer.valueOf(properties["buildNum"])
      properties["buildNum"] = buildNum + 1
    </groovy>
    <xmltask source="AndroidManifest.xml" dest="AndroidManifest.xml">
      <replace path="manifest/@android:versionCode"
        withText="${buildNum}"/>
    </xmltask>
    <antcall target="commit.and.tag.build">
      <param name="buildNum" value="${buildNum}"/>
    </antcall>
  </target>

  <target name="commit.and.tag.build">
    <exec executable="git">
      <arg value="commit"/>
      <arg value="-a"/>
      <arg value="-m"/>
      <arg value="Build Number ${buildNum}"/>
    </exec>
    <exec executable="git">
      <arg value="tag"/>
      <arg value="b${buildNum}"/>
    </exec>
  </target>
于 2013-05-17T21:56:30.467 回答
0

您可以在此处找到“位”更好的解决方法答案... https://stackoverflow.com/a/8156809/304270

微型 c# 工具,它将在每次新构建之前执行并增加清单文件中的适当值。

于 2013-07-11T12:35:31.577 回答