How to Automatically Modify versionName in Manifest during Build?

Eternal Learner picture Eternal Learner · Sep 14, 2012 · Viewed 8.4k times · Source

So far I have been focusing on my application's programming and paid little attention to making the build process smarter. Thus I have been doing things pretty much manually (the "dumb way"), including updating by hand android:versionCode and android:versionName in AndroidManifest.xml.

I would like now to automatically (i.e. upon Build or upon Export):

  1. Fetch from git the latest tag/branch containing build and version codes.
  2. Parse them so that I can assign them to the respective fields in AndroidManifest.xml.
  3. Modify AndroidManifest.xml accordingly.
  4. Proceed with the normal build process (Eclipse+ADT, no Ant whatsoever), as if I did 1-2-3 by hand...

I found a few clues about a "pre-build step", builders and build.xml, but I have no idea where to find those and where to start.

Any tips or pointers on where I could find more information on the subject? (a step-by-step tutorial would be ideal)

Update 1: I found this thread to be suggesting that I:

  1. Right-click on the project, Properties > Builders
  2. Add a builder that points to the project's Ant build file.
  3. Order that builder to be invoked before the Java builder

Fine, but where is the project's Ant build file? Where do I find it?

Update 2: Apparently, it's possible to export the entire project into an Ant file. But I am not sure that's I want. Must a pre-build step always include an Ant build file?

Update 3: Is building an Ant file, only for the pre-build step, the right approach?

Answer

cermak.cz picture cermak.cz · Oct 12, 2012

Here's what I use to dynamically assign a versionCode and versionName to AndroidManifest.xml. It works only when building with ant, so you'll have to install it first. Then go to the project directory in your command line and execute "android update project -p .", which will create the necessary files for building with ant, like local.properties and build.xml.

Then open build.xml and place this inside:

  <target name="-pre-build" depends="-custom-git-version,-custom-manifest-version">
  </target>

  <!-- Packages the application. -->
  <target name="-post-build">
    <antcall target="-custom-restore-manifest"/>

    <property name="suffix" value="${git.commits}-${git.version}.apk" />

    <exec executable="sed" inputstring="${out.final.file}" outputproperty="out.final.renamedfile">
      <arg value="s/\.apk/-${suffix}/" />
    </exec>

    <copy file="${out.final.file}" tofile="${out.final.renamedfile}" />
    <echo>Final file copied to: ${out.final.renamedfile}</echo>
  </target>  

  <!-- Custom targets -->
  <target name="-custom-git-version">
    <exec executable="sh" outputproperty="git.commits">
      <arg value="-c" />
      <arg value="git log --pretty=format:'' | wc -l" />
    </exec>
    <echo>git.commits: ${git.commits}</echo>
    <exec executable="git" outputproperty="git.version">
       <arg value="describe" />
       <arg value="--tags" />
       <arg value="--long" />
    </exec>
    <echo>git.version: ${git.version}</echo>
  </target>

  <target name="-custom-manifest-version">
     <echo>Creating backup of AndroidManifest.xml</echo>
     <copy file="AndroidManifest.xml" tofile="AndroidManifest.xml.antbak" preservelastmodified="true" />

     <replaceregexp
        file="AndroidManifest.xml"
        match='android:versionCode="(\d+)"'
        replace='android:versionCode="${git.commits}"' />

     <replaceregexp
        file="AndroidManifest.xml"
    match='android:versionName="(\d+\.\d+)\.\d+"'
    replace='android:versionName="\1.${git.commits}"' />
  </target>

  <target name="-custom-restore-manifest">
    <echo>Restoring backup of AndroidManifest.xml</echo>
    <move file="AndroidManifest.xml.antbak"
          tofile="AndroidManifest.xml"
          preservelastmodified="true"
          overwrite="true" />
  </target>

The output of this is not exactly what you want, but it is a start - feel free to modify it :) The result is something like "yourapp--.apk

Using this you'll build your application with executing "ant clean debug", or "ant clean release", depending on what you want. You can also create "ant.properties" file with this content:

key.store=keystore_file
key.store.password=some_password
key.alias=some_alias
key.alias.password=some_other_password

to enable automatic signing of your app.

You should also read this: http://developer.android.com/tools/building/building-cmdline.html