让IDE自动增加内部版本号是一个长期讨论的问题 - 我总是感到惊讶的是,对我来说似乎非常基本的东西是如此多的工作。
本主题的得分最高的问答(相当多)在这里: https://stackoverflow.com/a/8156809/150016 我的问题是解决方案依赖于.net,我宁愿避免使用Eclipse解决方案的.net依赖。我还想避免对VCS的任何依赖。
所以,我正在寻找可移植的解决方案和'Eclipse-ish'。我认为最好的候选者是Ant解决方案(我将发布)或类似于上面链接答案中的dotNet应用程序的Java应用程序。
(我没有添加我对这个问题的答案,因为它有一个已接受的答案,并且已经是一个很长的帖子。如果主持人更喜欢我会删除这个问题,并将我的答案添加到上面的问题。)
我希望有一些相对简单的东西,但我认为解决这个问题的方法并不简单。
答案 0 :(得分:8)
在项目的属性对话框中,在构建器下,您可以配置脚本以在构建apk之前运行。
在属性对话框中,从左侧列表中选择“构建器”。单击“新建”以添加新脚本。在弹出的对话框中,选择“程序”。在随后的对话框中,在“名称”字段中调用您喜欢的构建器程序。将路径放在“位置”字段中。在工作目录字段中为其指定一个工作目录。请注意,您可以在这些字段中指定变量(例如,我们使用${build_project:/libs/update_version.sh}
来引用项目的lib目录中的脚本)。
您希望它在任何其他构建器之前运行,因此使用向上按钮将其移动到列表顶部。
在Dialog的Build Options选项卡上(它位于顶部的Name字段下方),您可以选择希望此程序运行的选项。
我在这里假设像Linux,Unix或MacOS这样的东西。在这些系统中,您可以使用grep或其变体来获取当前的versionCode,增加它,然后使用awk或类似来相应地修改文件。或者,您可以编写Ruby,Python,Perl等脚本来替换AndroidManifest.xml文件中的versionCode。我想在Windows上有相同的工具,但我对这个环境并不是很熟悉。
答案 1 :(得分:7)
你有没有尝试'Maven-ise'你的android项目构建?
如果您使用"maven-android-plugin",则可以使用pom.xml的“version”标记跟踪项目构建。
在pom.xml中,您可以使用"versions-maven-plugin"
增加构建版本要将增加的内部版本号反映到AndroidManifest.xml,您可以使用pom文件中的Synchronizing Version technique。
这样,每次应用程序构建时,您都可以通过运行“versions-maven-plugin”来自动增加android项目内部版本号。该解决方案也可以与Ant解决方案相同的方式移植。
我希望这也可以解决你提到的问题(以及我所理解的)。如果缺少某些东西,请纠正我。
答案 2 :(得分:3)
这是一个使用Ant的解决方案。我必须承认,获取Ant设置有点麻烦,但它似乎是Eclipse的一个广泛使用和强大的附件,所以我相信它会在其他方面对我有价值。
Ant是构建没有Eclipse的Android SDK应用程序(如described here)的首选解决方案,但不是ADT的一部分,所以如果你刚刚使用Eclipse,你可能不会拥有它。
因此,第一步是下载并安装Ant from here。
接下来将Ant添加到您的路径中,并确保您的路径也指向JDK(而不是JRE)。在Windows上,我发现我还必须创建JAVA_HOME并将其指向JDK的根目录。
我们只需要Ant用于自动增量步骤 - 目的不是替换Eclipse并将其用于整个构建 - 但是在这个方向上做一些步骤以确保Ant正常工作是很有用的。因此,转到项目的根目录并键入
> android update project --path .
这将为您的项目创建一个build.xml。一旦我做完了,我就能做到了
> ant release
和Ant构建了我的项目。如果你想继续朝这个方向前进,我发现this article很有用。
接下来,我编辑了我的项目的新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中的应用程序代码的解决方案。 Here is一个包含执行该任务的任务的答案,但它需要第三方Ant任务(xmltask),并且我有点犹豫是否有第三方任务修改我的清单(现在非常庞大)在每个构建。如果您决定使用该任务,那么获取内部版本号的相应Android代码将是:
String packageName = ctx.getPackageName();
PackageInfo pInfo = ctx.getPackageManager().getPackageInfo( packageName, 0);
int appVer = pInfo.versionCode;
最后,每次进行构建时都需要让Eclipse运行此Ant任务。
转到项目的属性,找到Builders,然后单击按钮添加新的Builder。这里有很多选项,但你只需要指定几个。
我将新的Builder移动到第一个构建步骤。
此解决方案的一个问题是,每次让Eclipse部署(运行)您的应用程序时,即使项目未更改,也会将其视为新的手动构建。因此,如果将应用程序部署到多个设备,则每个设备将具有不同的构建版本,并具有自己的构建版本号。有一点可以改善这个问题,谷歌表示未来的ADT将允许在一次操作中进行多次部署。
这个(上面)在Win7 32bit上使用Ant 1.8.4,Eclipse Indigo SR2(3.7.2),ADT 20 preview 2和SDK Tools 20进行了测试。
答案 3 :(得分: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 => ${a}</echo>
<echo>2. => ${b}</echo>
<echo>3.3 => ${c}</echo>
<echo>4.4. => ${d}</echo>
<echo>5.5.5 => ${e}</echo>
<echo>6.6.6. => ${f}</echo>
<echo>7.7.7.7 => ${g}</echo>
</target>
<target name="update.manifest">
<fail message="File not found: "${manifest.file}"" 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 "android:versionName" undefined into "${manifest.file}"" 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.*=.*".*${version.name}.*""
replace="android:versionName="${new.version.name}""/>
<!-- Replaces for check and generates a exception (if not found version) -->
<replace
file="${manifest.file}"
token="android:versionName="${new.version.name}""
value="android:versionName="${new.version.name}""
failOnNoReplacements="true"/>
<!--<echo>${version.file}</echo>
<echo>${manifest.file}</echo>-->
<echo>Auto Increment Build: ${version.name} => ${new.version.name}</echo>
</target>
ant [-Dmanifest.file=<file>] [-Dversion.file=<file>] [-Dbuild.slot=<number>] -Dmanifest.file - path and filename AndroidManifest.xml. Default: AndroidManifest.xml in a folder with build.xml -Dversion.file - path and file name in which to store the number Build version. Default: version.properties folder with build.xml -Dbuild.slot - position of build number in version array. Default: 2, ie X.X.build.
Project | Properties | Builders | New | Ant Build Main Build file <path>/build.xml Arguments -Dmanifest.file=${workspace_loc://AndroidManifest.xml} -Dversion.file=${workspace_loc://version.properties} Refresh [x] Refresh resources upon completion (*) Specify resources [Specify resources] <Project> [x] AndroidManifest.xml Build Options [x] Specify working set of relevant resources [Specify resources] <Project> [x] res [x] src [x] AndroidManifest.xml
答案 4 :(得分:0)
我的解决方案使用了其他答案中的一些代码,XMLTask和Groovy来自动增加内部版本号。我还包含一个规则,用于执行git commit和tag以将版本号链接到版本控制中的特定点 - 对于错误跟踪很有用。
<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>
答案 5 :(得分:0)
你可以在这里找到一个“位”更好的解决方案答案...... https://stackoverflow.com/a/8156809/304270
Tiny c#工具,它将在每次新建构建之前执行,并在清单文件中增加适当的值..