[TUT] Switching Android build constants using Ant

By blundell  

When you want to create two different builds/configurations for your development environment and your live build, it can be really annoying having to change all those constants; or you don’t have them as constants and you’ve got some horrible if else logic in your code.
Here I’ll show you how to use Ant to swap in and out your different configs when you run and build your APKs.
I’m not going to go over the inner workings of Ant because 1) I suck at it and 2) You won’t need to learn it (hopefully) it’ll just be simple and self explanatory.
So what are we going to do?

1) Create a config java file that will hold are constants (server address, google maps key)

2) Create a template that will be used to swap your constants

3) Switch the constants in the config file with the running of 1 Ant script

This Ant script will also create your APK, this is optional but necessary if you are going to move on to a fully automated Android build.

Ok here we go! First off I’ve created a simple application that shows a message on the screen declaring which set of constants we are running with. It also displays the version number of the app if we are running in development mode and hides this version if we are running in live mode.

This tutorial is not just about Android classes, we are going to be creating some configuration files that live outside of the build path. Here is a screenshot of the completed project for your reference:

Below is the Config.java file, this is used to keep all our app constants in one place, I’ve just used three consts but you can add anything you can think of (logging on/off, port numbers, admob keys, market variant, beta):

Config.java:

package com.blundell.tut;

// ** This build is currently using DEVELOPMENT properties **
public class Config {
	public static final boolean LIVE = false;
	public static final String SERVER = "http://development.server.net";
	public static final String GMAPS_API_KEY = "aaaaaaa";
}

Now the trick is we mirror the Config.java on the build path with a file in a ‘template’ file that is not on the build path. We use the template with Ant to create a new file that will be copied over the original Config.java to change the properties (bear with me).

Here is what the template looks like, in the project tree structure it is /config/Config.java. The main thing to notice is the package has to match the package of the compiled Config.java.

package com.blundell.tut;

// @GENERATED@
public class Config {
	public static final boolean LIVE = @CONFIG.LIVE@;
	public static final String SERVER = "@CONFIG.SERVER@";
	public static final String GMAPS_API_KEY = "@CONFIG.GMAPS_API_KEY@";
}

The @ symbols are used as placeholders inbetween each pair of @’s is what we will be replacing.

Ok so we have a constants file, we have a template of this constants file, now we need a list of what to replace the @properties@ with in the template. Just a plain text file like so: (this is also kept in /config/)

config.dev.properties:

GENERATED		= ** This build is currently using DEVELOPMENT properties **
CONFIG.LIVE		= false
CONFIG.SERVER		= http://development.server.net
CONFIG.GMAPS_API_KEY	= aaaaaaa

Thats it! The rest is done in your build.xml Ant file….eek!

<?xml version="1.0" encoding="UTF-8"?>
<project
    name="BuildChoiceTut"
    default="help" >

    <property file="local.properties" /> <!-- load the SDK directory variable -->

    <property file="ant.properties" /> <!-- load the keystore variables (for building APKS) -->

    <loadproperties srcFile="project.properties" /> <!-- load the Android target and proguard (if enabled) -->

    <!-- quick check that sdk.dir has been set properly-->

    <fail
        message="sdk.dir is missing. Make sure to generate local.properties using &apos;android update project&apos;"
        unless="sdk.dir" />

    <!--
         Custom Android task to deal with the project target, and import the proper rules.
         This requires ant 1.6.0 or above.
    -->

    <path id="android.antlibs" > <!-- This is Android build stuff its needed! -->

        <pathelement path="${sdk.dir}/tools/lib/anttasks.jar" />

        <pathelement path="${sdk.dir}/tools/lib/sdklib.jar" />

        <pathelement path="${sdk.dir}/tools/lib/androidprefs.jar" />

        <pathelement path="${sdk.dir}/tools/lib/apkbuilder.jar" />

        <pathelement path="${sdk.dir}/tools/lib/jarutils.jar" />
    </path>

    <!-- version-tag: 1 -->

    <import file="${sdk.dir}/tools/ant/build.xml" /> <!-- Inherit from the Android build file (very useful) -->

    <!-- The configuration depends on "clean" because otherwise the build system will not detect changes in the configuration. -->

    <target
        name="buildDev"
        description="Build APK with developer settings i.e. logging on etc" > <!-- Name the build and give it a helpful description -->

        <antcall target="clean" /> <!-- clean out the /bin/ directory and delete all temp and cached files -->

        <antcall target="loadDevProperties" /> <!-- this is the business! here we are overwriting our config file -->

        <antcall target="debug" /> <!-- Build a debug APK and place it in /bin/ -->
    </target>

    <!-- The configuration depends on "clean" because otherwise the build system will not detect changes in the configuration. -->

    <target
        name="buildLive"
        description="Build APK with live settings i.e. logging off etc" >

        <antcall target="clean" />

        <antcall target="loadLiveProperties" />

        <antcall target="release" />
    </target>

    <property
        name="config.target.path"
        value="src/com/blundell/tut/" /> <!-- This is like java variable creation. Here we setup the path of where the Config.java file is in your Android project -->

    <!-- Copy Config,java to our source tree, replacing custom tokens with values from ant.properties -->

    <target
        name="loadDevProperties"
        description="Use dev properties for logging / url etc" >

        <property
            name="config.properties.file"
            value="config.dev.properties" /> <!-- For loading dev properties we setup the variable 'config.properties.file' to be the dev properties -->

        <antcall target="copyProperties" /> <!--  We then copy from our /config/ to our project build /com.blundell.tut/ -->
    </target>

    <!-- Copy Config,java to our source tree, replacing custom tokens with values from ant.properties -->

    <target
        name="loadLiveProperties"
        description="Use live properties for logging / url etc" >

        <property
            name="config.properties.file"
            value="config.live.properties" />

        <antcall target="copyProperties" />
    </target>

    <target
        name="copyProperties"
        description="Copy the configuration file, replacing tokens in the file" >

        <copy
            encoding="utf-8"
            file="config/Config.java"
            overwrite="true"
            todir="${config.target.path}" > <!-- This is reading the template file and overwriting our build path equivalent file -->

            <filterset filtersfile="config/${config.properties.file}" /> <!-- Whilst it is overwriting we replace the placeholder with the values we set -->
        </copy>

        <tstamp />

        <echo message="Copy of properties finished. ${TSTAMP}" />
    </target>

</project>

The above Ant script has been commented heavily so I’ll try not to repeat myself here. If you need further explanation please leave a comment.
This build.xml can now be used to switch your configs, the below tutorial explains how to run your Ant script.

Here’s how you Run an Ant Build in Eclipse

As the above link shows, to switch your configs you run either ‘buildDev’ or ‘buildLive’ this will also create you an apk in the /bin/ directory. If you just wanted to swap the configuration you could run ‘loadDevProperties’ or ‘loadLiveProperties’

As a side note, I have packaged the keystore in with the configuration. This allows you to 1) keep it in subversion, where you won’t lose it! 2) it can be used by the build.xml to automatically build your live application (You can also add your keystore password if you want full automation but not in this tutorial). Therefore if you download the demonstration project below the live build actually won’t work, but it will change your configuration.

Finally if your using Eclipse, don’t forget your F5(refresh) key to check the values have changed!

I strongly recommend you download the source project below and check it our yourself, it’s a much more visual explanation than my poor attempt at literacy.

Ant Build Choice Eclipse Source Project
If your using this source project don’t forget to change local.properties to point at your SDK not mine!

Also mirrored on GitHub: https://github.com/blundell/BuildChoiceTut

Goodluck and if you find this useful please say so!


2 Comments

  1. Saad Farooq
    Posted November 18, 2012 at 2:19 am | Permalink | Reply

    I love you man..!!

  2. Vincent B.
    Posted June 20, 2012 at 10:39 am | Permalink | Reply

    Thanks for this tutorial. Nice way of processing.

    Just maybe some comment to add to your build.xml about the ” ” to replace with something else to avoid it to be override by the android update cmd (this comment is present in the default build.xml file generated).

    Also a link to another tutorial with info about the ant.properties and the use of the keystore would be the perfect thing.

    Thanks for this neat tutorial !

2 Trackbacks

  1. By Homepage on June 21, 2012 at 3:24 am

    … [Trackback]…

    [...] Read More here: blog.blundell-apps.com/switching-android-configurations-using-constants-and-ant/ [...]…

  2. [...] The app also shows the use of a Config file to show extra information when running in ‘non-live’ mode. You can see an example of switching that configuration here. [...]

Post a Comment

Your email is never shared. Required fields are marked *

*
*