a little madness

A man needs a little madness, or else he never dares cut the rope and be free -Nikos Kazantzakis

Zutubi

Android Ant Builds: Targeting a Specific Device

While developing for Android, I often have more than one device available. For example, I might have an actual G1 hooked up via USB, and an emulator instance running. In this case, when installing and running development versions of my Android applications, I need to specify which device to target. If I’m working directly with adb, there are flags for just this purpose:

jsankey@caligula:~$ adb -?
Android Debug Bridge version 1.0.26
 -d                            - directs command to the only connected USB device
                                 returns an error if more than one USB device is present.
 -e                            - directs command to the only running emulator.
                                 returns an error if more than one emulator is running.
 -s <serial number>            - directs command to the USB device or emulator with
                                 the given serial number. Overrides ANDROID_SERIAL
                                 environment variable.
...

I prefer to use the general -s flag, as this works no matter how many devices I have connected. This does require a serial number, but they are easily listed:

jsankey@caligula:~$ adb devices
List of devices attached 
HT845KV55555	device
emulator-5554	device

Normally, however, I’m not running adb directly, but indirectly via an Ant build. If I try, for example, to run the install target with multiple devices attached, adb is not happy:

jsankey@caligula:~/work/my-app$ ant install
Buildfile: build.xml
    [setup] Android SDK Tools Revision 6
    [setup] Project Target: Android 2.2
...
install:
     [echo] Installing /home/jsankey/work/my-app/build/MyAppActivity-debug.apk onto default emulator or device...
     [exec] error: more than one device and emulator
BUILD FAILED
/usr/local/java/android/platforms/android-8/ant/ant_rules_r2.xml:362: The following error occurred while executing this line:
/usr/local/java/android/platforms/android-8/ant/ant_rules_r2.xml:191: exec returned: 1
Total time: 1 second

The Ant build cannot guess which device to use by default, so it errors out. By digging into the Android Ant rules file, I found that the Ant builds support a property named adb.device.arg, which allows you to pass flags through to adb. For example, I can instruct the Ant build to install the application on the emulator as follows:

jsankey@caligula:~/work/my-app$ ant -Dadb.device.arg="-s emulator-5554" install
Buildfile: build.xml
    [setup] Android SDK Tools Revision 6
    [setup] Project Target: Android 2.2
...
install:
     [echo] Installing /home/jsankey/work/my-app/build/MyAppActivity-debug.apk onto default emulator or device...
     [exec] 266 KB/s (14446 bytes in 0.052s)
     [exec] 	pkg: /data/local/tmp/MyAppActivity-debug.apk
     [exec] Success
BUILD SUCCESSFUL
Total time: 6 seconds

There is, however, one sticking point. To run a test application via Ant, you can use the run-tests target. As of the latest SDK release, however, the run-tests target does not respect the adb.device.arg property. When I discovered this a couple of weeks ago, I raised an issue about it, and it was promptly fixed. Until the fix is released, though, a workaround is needed.

Luckily, adb supports another way to specify the device: via the ANDROID_SERIAL environment variable. This variable takes the same serial values as the -s flag, and being part of the environment is independent of how you end up running adb. To repeat my previous example, I just need to set the variable to the serial for my emulator:

jsankey@caligula:~/work/my-app$ export ANDROID_SERIAL=emulator-5554
jsankey@caligula:~/work/my-app$ ant install
Buildfile: build.xml
    [setup] Android SDK Tools Revision 6
    [setup] Project Target: Android 2.2
...
install:
     [echo] Installing /home/jsankey/work/my-app/build/MyAppActivity-debug.apk onto default emulator or device...
     [exec] 277 KB/s (14446 bytes in 0.050s)
     [exec] 	pkg: /data/local/tmp/MyAppActivity-debug.apk
     [exec] Success
BUILD SUCCESSFUL
Total time: 4 seconds

Presuming you have control of the environment in which adb is run, the ANDROID_SERIAL variable is probably your best bet for targeting a specific device.

Liked this post? Share it!

11 Responses to “Android Ant Builds: Targeting a Specific Device”

  1. September 29th, 2010 at 9:38 pm

    cherrybeach says:

    Thanks! Very helpfull!

  2. May 20th, 2011 at 4:34 pm

    Alex says:

    thanks! Saved me a bit of time. Would have had to do the digging myself.

  3. February 23rd, 2012 at 8:59 pm

    walley says:

    Thanks, sad think is that you are the first google result for this issue.
    It should be google android documentation.

  4. April 2nd, 2012 at 3:29 am

    Masi says:

    You can also enhance you projects build.xml with custom targets like that:

  5. April 2nd, 2012 at 3:30 am

    Masi says:

    You can also enhance you projects build.xml with custom targets like that:

    [target name=”installdd” description=”install on default device”]
    [antcall target=”installd” inheritRefs=”true” ]
    [param name=”adb.device.arg” value=”-d” /]
    [/antcall]
    [/target]
    [target name=”installde” description=”install on default emulator”]
    [antcall target=”installd” inheritRefs=”true” ]
    [property name=”adb.device.arg” value=”-e” /]
    [/antcall]
    [/target]

    Replace the square brackets with angled brackets.

  6. November 19th, 2012 at 9:18 am

    Travis says:

    Thanks…knew there should be a way to accomplish this but it certainly doesn’t jump right out at ya from the docs does it? Seems like it aught to be part of ant’s help text when ‘ant help’ is run from the android directory.

  7. April 22nd, 2013 at 7:42 pm

    Zerho says:

    there is no way to use ant install with devices?
    eve this way:
    ant -Dadb.device.arg=”-s emulator-5554″ install
    you specified just the emulator not a real device.

    suggestion? thanks

  8. May 2nd, 2013 at 12:31 pm

    Jason says:

    You can specify real devices attached to USB in the same way, you just need the serial number. You can see this in the output of “adb devices” (first column). Just set adb.device.arg to “-s “.

  9. May 13th, 2014 at 9:12 pm

    László says:

    I have successfully used `ant -Dadb.device.arg=”-e” install` to automatically pick the emulator (similarly “-d” would pick the device).

    I’m a bit unsure from which version of the `adb` tool the `[-e|-d]` options are supported from, though.

    This, of course, only works when I have exactly one emulator (or one device for the “-d” option) up and running.

  10. June 6th, 2014 at 4:07 am

    Android from command line – Useful things | Venkatesh Shukla says:
  11. September 10th, 2014 at 9:06 am

    How to get started with Cocos2d-x on Windows | andersguide says:

    […] Use “adb -d SOME_COMMAND” to target (a lone) USB connected device and “adb -e SOME_COMMAND” to target (a lone) available emulator. See: http://www.shockoe.com/blog/adb-with-multiple-devices/ and http://www.alittlemadness.com/2010/06/15/android-ant-builds-targeting-a-specific-device/ […]

Leave a Reply