Add mercurial or git changeset id to your Android app

We recently automated the debug builds of our Android app. As a result, we wanted to include the Mercurial changeset id in our app settings, so we could quickly tell what version of the app someone was running.

What we ended up doing was writing the changset id to a custom properties file that was then copied into the raw directory during a build. That properties file could then be read by our PreferencesActivity on runtime.

In order to do this we wrote a custom build.xml file for ant. Simply copy and paste the following into your build.xml file:

    <!-- Require the hg.revision task during pre-build -->
    <target name="-pre-build" depends="hg.revision" />
 
    <!-- Check to see if a mercurial repository exists in the source dir -->
    <available file=".hg" type="dir" property="hg.present" />
 
    <!-- Get the mercurial changeset id for tip -->
    <target name="hg.revision" description="Store mercurial revision in ${repository.version}" if="hg.present">
        <exec executable="hg" outputproperty="hg.revision" failifexecutionfails="false" errorproperty="">
            <arg value="id" />
            <arg value="-i" />
            <arg value="-n" />
            <arg value="-r" />
            <arg value="tip" />
        </exec>
        <echo message="Repository version is ${hg.revision}" />
 
        <!-- Create property file containing mercurial changeset id -->
        <propertyfile file="version.properties" comment="The changset id that this app was built from.">
            <entry key="changeset" value="${hg.revision}" />
        </propertyfile>
 
        <!-- Move property file to app accessible res/raw/ directory -->
        <move file="version.properties" todir="res/raw/" />
    </target>

Essentially this creates an executable task that calls hg id -i -n -r tip in the build workspace. It then adds the result of that command to a propertyfile called version.properties. That file is then copied to the res/raw/ directory.

Our app code is even more straightforward. We simply wrote a function to retrieve the changeset id from the properties file in the raw resources directory. We then take the output of this function and update the preference item.

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.settings);
 
        // Display app_build in settings as set in the app.version properties file at build time
        Preference build = findPreference("app_build");
        build.setSummary(this.getAppChangsetFromPropertiesFile());
    }
 
    public String getAppChangsetFromPropertiesFile() {
        Resources resources = getResources();
 
        try {
            InputStream rawResource = resources.openRawResource(R.raw.version);
            Properties properties = new Properties();
            properties.load(rawResource);
            return properties.getProperty("changeset");
        } catch (IOException e) {
            Log.e(TAG, "Cannot load app version properties file", e);
        }
 
        return null;
    }