Wednesday, December 22, 2010

Android Ant builder

Android build process is quite complicated
First of all it is based on ant script together with sdk tools and java apps aligned to ant.

Lets take a closer look to it
to create ant script manually just type:

cmd <enter>
if you don't have Android SDK folder in system PATH environmental variable - add it
set path=%path%;X:\android\android-sdk-windows-1.5_r3\tools

now you can create new or update existent eclipse project
(I assume that you like me create project in eclipse first and then, for some reason, you need to build your fancy application from command line

set current dir to your android project dir

cd c:\apps\myapp <enter>
android update project  <enter>

now you have build.xml in your projects root folder

for now you can open them in eclipse but you cannot build (execute) ant script from eclipse
The problem is in java component that connect you build.xml ant script with platform dependent android ant script that located in SDK

for example for API level 8 it will be android_rules_r3.xml.

File contains a lot of comments about every section
but I'll explain some of them just for those who  who know nothing about ant engine :)

Ant stuff
I will explain only things that I need to build android project manually

every project contains
<project name="myapps" default="<default target>" basedir=<path to your android project> 
...
project>
nice to see basedir here because you are able to move you Ant script

main concept of ant is targets (like "release", "debug", "release-signed", ets.)
every target could have dependency on other targets
and targets could be public and private (hidden)

for example simple target:
<target name="help">
<echo>This project has extended helpecho>
target> 

complex target
<target name="release" depends="resources, java_compiler, zip, sign, renameing">

target> 

you can specify properties ( they are playing the same function as variables in other languages )
<property name="app.file.name" value="${build.prop.name}" />
let me explain this
you can read/ write app.file.name using ${app.file.name} sintax
in sample you define property and set value for it equal to value of  build.prop.name property

you could override this prop value in build.properties file
lets call it first level of customization

you also  able to define properties in build.properties and then load to project
<property file="build.properties"/>

Combination of both <property name.../> and <property file=.../> creates a list of properties that could be redefined in a separate settings file 
Example:

<property name="one" value="ha-ha"/>
<property file="build.properties"/>

now we can move to targets and other xml elements

<taskdef name="setup" classname="com.android.ant.SetupTask"
classpathref="android.antlibs"/>


Defines a java class with a starting "main" point in com.android.ant.SetupTask.
reference android.antlibs - a link to path(s) where SetupTask could be found.
All android elements (tags) could use (execute) this application
using <setup>setup> tag 

few more samples
<taskdef name="apkbuilder"
classname="com.android.ant.ApkBuilderTask"
classpathref="android.antlibs" />


<taskdef name="xpath"
classname="com.android.ant.XPathTask"
classpathref="android.antlibs" />
usage:

<xpath input="AndroidManifest.xml" expression="/manifest/@package"
output="manifest.package" />


<aaptexec executable="${aapt}"
    command="package"
    verbose="${verbose}"
    manifest="AndroidManifest.xml"
    androidjar="${android.jar}"
    rfolder="${gen.absolute.dir}">

aaptexec>   
if you command sequence that you have to use in different targets you could write a macro
definition:

<macrodef name="dex-helper">
   <element name="external-libs" optional="yes" />
   <element name="extra-parameters" optional="yes" />
   <sequential> 

      <echo>Converting compiled files and external libraries into ${intermediate.dex.file}...echo>
   sequential>
 macrodef>
usage: 
<dex-helper /> 
or 
<dex-helper>
   <extra-parameters>
     <arg value="--no-locals" />
   extra-parameters>
   <external-libs>
     <fileset file="${emma.dir}/emma_device.jar" />
   external-libs>
 dex-helper/>


I hope you've got the idea.

Now about problem I met

for android platform 2.2 (API level 8) 
if you open build script that contains external targets (targets that were defined in android_rules_r3.xml or other external files)
in eclipse. you've get ant compilation errors (unknown target)

if you run the same script (build.xml) from command promt - it works fine

for example in case with auto-generated build.xml

this one return error unknown help target if you open it in eclipse
after that you are not able to compile you app!!! 
As a not very good solution is moving  build.xml file outside project root dir in this case eclipce will not see it and you can add to get it working from command line

3 comments:

Anonymous said...

build.xml:46: taskdef class com.android.ant.SetupTask cannot be found
when running ant release with the following
sdk.dir=C:\\android-sdk-windows
and
sdk-location=C:\\android-sdk-windows
using sdk 2.2

Oleksandr said...

you should not define ${sdk-location} directly. it will be defined inside ant_lib_rules_r3.xml (for 2.2)

put ${sdk.dir} in file local.properties
add this line to the end of file
sdk.dir=C:\\android-sdk-windows

to debug ant script use echo command or eclipse debug engine.
in case with echo add this before setup definition
<echo>sdk.dir:${sdk.dir}</echo>

apilyugina said...

Thanks for your post! http://www.enterra-inc.com/techzone/using_ant_android_applications_building/ hope it couls be also useful