Build Numbers in Android Applications
When working with new innovative technologies you often have to take apart old tools and gleu them back in new ways to deal with new issues. If you have worked in JavaMe(j2ME) before you might have used something like JReleaseInfo to adjust and collate different manifest items to add to the manifest before you jar’d it such as the build number. However, in the Adnroid Java Application development world the manifest is no longer an *.Mf file but an XML file and thus the version number we have to change upon calling an ANT task such as build number is in that file.
I came up with:
<!-- Set build number -->
<condition property="build.number.property.set">
<available file="build.number"/>
</condition>
<if>
<equals arg1="${build.number.property.set}" arg2="false"/>
<then>
<!-- We know build.number will set to 1 at <buildnumber/> call
-->
<buildnumber/>
</then>
<else>
<!-- Set var build.number.initial to build.number-1 -->
<if>
<equals arg1="${build.number}" arg2="1"/>
<then>
<!-- do not change AndrodManifest -->
</then>
<else>
<!--- okay do our repalce thing on AndoridManifest.xml -->
<property name="android.version.code" value="android:versionCode="/>
<property name="android.version.name" value="android:versionName="/>
<replaceregexp file="androidManifest.xml"
match="android:versionCode=(.*)"
replace='${android.version.code}"${build.number}"'/>
<replaceregexp file="AndroidManifest.xml"
match="android:versionName=(.*)"
repalce='${android.version.name}"${build.number}.00"'/>
<buildnmuber/>
</else>
</if>
</else>
</if>
The way I came up with is:
1. check to see if build.number file exists, rember the build.number property is incremented from zero to 1 on first <buildnumber/> ant task call.
2. if false than cal <buildnumber/> task
3 if true than check to see if build.number is 1 and if so do not change AndroidManifest.xml and if not change to relfect new build number.
AndCooper Progress-August
In past lives I have used DSL scripting languages to decrease complexities of builds. If this was a groovy/grails project your woudl set-up a projectName.environment.groovy script that would hold a static list of environment settings and use that to configure the build and use a environmentTarget flag to choose between whether you had the debug, testing, or production build environment. You could get away with that in a groovy/grails project because the one viewing and using the build system should know some groovy, that is not the case with the AndCoooper build system where we do not want the user of the system to resort to having to know such things.
But, using DSL could decrease the amount of build script lines from somewhere around 2500 to something more manageable and flexible.Let me show you an example from AndCooper ANT version:
this is the release target
<target name="release" depends="dex, package-resources">
<apkbuilder
outfolder="${out-folder}"
basename="${ant.project.name}"
signed="false"
verbose="false">
<file path="${intermediate-dex}" />
<sourcefolder path="${source-folder}" />
<jarfolder path="${external-libs-folder}" />
<nativefolder path="${native-libs-folder}" />
</apkbuilder>
<echo>All generated packages need to be signed with jarsigner before they are published.</echo>
</target>
this is the debug target
<target name="debug" depends="dex, package-resources">
<apkbuilder
outfolder="${out-folder}"
basename="${ant.project.name}"
signed="true"
verbose="false">
<file path="${intermediate-dex}" />
<sourcefolder path="${source-folder}" />
<jarfolder path="${external-libs-folder}" />
<nativefolder path="${native-libs-folder}" />
</apkbuilder>
</target>
If I was using a DSL language as the build script language, such as groovy, I could just over ride the compile target with new a behaviour and thus not have to fully retype a new full release target and rename it as debug. What I could do instead is based on the setting of the envriomentTag of debug, testing, or production change the behaviours of the targets during the set up phase of said targets using:
init.doFirst {
logger.info(Logging.LIFECYCLE, 'INITIALIZING Gradle Project')
// check if a profile property is set :
if (!hasProperty('targetEnvironment')) {
targetEnvironment = DEFAULT_TARGET_ENV
}
if (targetEnvironment == debug) {
//over ride targets with new behaviours here
}
logger.info(Logging.LIFECYCLE, 'target environment is: ' + targetEnvironment)
}
What I could do is keep the environmentTag setting of debug, testing, production concept and actually use something like Gradle. With Gradle one could set 3 external program run settings in yoru IDE for debug, testing, and production as most modern IDE’s have it set up so that that the location of the project folder can be passed as a parameter to allow such launching as Gradle when launched takes that parameter and launches the default build.gradle file in the project folder.
Than why not extend further as this is the IDE launch parameters(Eclipse):
-f -p ${workspace_loc}${container_path} -b ${resource_name} ${string_prompt}
which would give be the same as at the command line in project directory:
gradle targetName -p enivronmentTag=debug
we extend that to be:
gradle targetName -p enivronmetnTag=debug -p machineSerialNumber=5567
what does that give us? Hold on to your seat or hat, a full virtual device lab without paying no third party for that honour! Hold on I am not done yet! EMMA support will probably not include being able to run EclEMMA plugin in Eclipse for another 8 months.
gradle targetName -p environmentTag=emma
and combine that with setting ANDROID-PRODUCTION_OUT as system variable than read that in in build.gradle to set the source emulator location and thsu we can laucnh the source emulator to execute the EMMA tests.
Yes, Google developing certain Android Application such as Latitude was kind of pissing me off. Let us make it an equal playing filed a little bit. I cannot attack the Google marketing power but I can certainly out engineer Google in one specific area!
How To Start Android Emulator using ANT
To start the Android Emulator and proceed to the next ant task, this should work:
<target name="start.emulator">
<parallel>
<daemons>
<exec executable="${emulator}">
<arg value="-avd"/>
<arg value="${my-avd}"/>
</exec>
</daemons>
</parallel>
</target>
It should work. Now this is the emulator in the released SDK as when you build the sdk/emulator from source its creating
its own AVD and configuration file entry to use that avd. But for just the released SDK/emulator it should work.
Driving Two Android Projects At Once
Usually, when developing a java jar or NDK *so shared library you have two projects the main one where you do the apk and the other one where you develop the library. The targets I came up with:
<target name="javalib.compile" depends="clean">
<javac encoding="ascii" target="1.5" debug="true" extdirs=""
destdir="${out-classes}"
bootclasspathref="android.target.classpath">
<src path="${source-folder}" />
<!-- do not need genfolder -->
<classpath>
<fileset dir="${external-libs-folder}" includes="*.jar"/>
<pathelement path="${main-out-classes}"/>
</classpath>
</javac>
<!-- We package or jar in the same target -->
<jar destfile="${dist}/javalib/${projectlib.java.projectname}.jar"
basedir="$[out-classes}"/>
</target>
<target name="javalib.move" depends="javalib.compile">
<!-- run compile javalib -->
<exec executable="ant" failonerror="true">
<arg value="-f" />
<arg value="${projectlib.java.projectlocation}/android_build.xml" />
<arg value="javalib.compile"/>
</exec>
<!-- move javalib to main project-->
<copy file="${projectlib.java.projectlocation}/dist/javalib/${projectlib.java.projectname}.jar" todir="${basedir}/libs" />
</target>
<target name="javalib.incremental" depends="javalib.move, compile">
</target>
This way I can point the IDE java builder to use this javalib.incremental target and thus have both projects incrementally compiled off of one target and thus have the javalib jar as input to my main project. I would imagine that you could set-up the NDK stuff the same way except you would be driving a target that drives an *.mk script to compile the *.so and move it before the main project compile task taking the *.so as input in the libs folder of main project.
Is ANT support Broken in Android SDK?
As you know if you read my posts on Android SDK customization that I customize the Android SDK to supply better ANT scripts upon executing the create project command. Here is what I mean by broke, mobile development is different in that we have more one-person-shops than say in enterprise development. Thus, having default build scripts to handle most user cases in android development becomes more of a priority for getting developer s to the platform as these developers will not become Apache ANT experts just to use the platform.
And the Android SDK set-up is such that one cannot easily make changes ot the android_rules.xml file to fix the ANT support becasue that would break other things. Sure, I could suggest that we intentionally break the build.template in order to get better build scripts in the Android SDk but that fix/enhancement will never get approval not because it gives more stuff to application developers but it is how android_rules.xml and build.template in the SDK were originally setup as far with other components having dependencies on those files.
The most obvious potential supporter of this movement towards better ANT support for Android Developers would be Motorola as the current release of MotoDveStudio for Android shows. I am not sure how to crack that ‘wall’ at this time as I run into too many ‘oh Motorola is so big we do not know where to ask your question’ response from any Motorola employee I ask(You should have seen how long it took to get Moto HQ staff to change from going my old blog to this one, shakes head..sheesh!)
So what does an example user case look like indicating broken ANT support? The continued every new Android Developer getting Proguard settings in their ANT task wrong, perhaps? The question now appears on the developers lists more than once a week. That is just one example, as the questiosn about ANT have gone up from only one per month when Google started the android Dev lists to several per week.
According to Fadden(Proguard), here is how obfuscation task should look:
<target name="-obfuscate" depends="compile.incremental">
<!-- In versions prior to 4.4 Peephole optimization was turned off
however in 4.4beta is now on and thus we
have turn off with the command of
-optimizations !code/simplification/cast
per Fadden also use
-allowaccessmodification -->
<proguard>
-libraryjars ${android.jar}: ${external-libs-folder}
-injars ${out-classes-location}
-outjars ${obfuscate-location}/classes.min.jar
-keep public class * extends android.app.Activity
-optimizations !code/simplification/cast
-allowaccessmodification
</proguard>
</target>
Notice that there are now two new settings and that is updated per Fadden’s notes from this week. That is just a sample of the areas of ANT support where the Android developers do not want to become ANT experts or build engineer experts but they need to know or have a basic default set of build scripts that is specific to Android development.
If we do not tackle this now, when 9 million Android devices hit the market it will ‘bite’ the whole development community in the ass.
PMD Task For Android
I do not think any of us are Apache ANT experts, but here is the PMD task that I am using with an Android setup:
<pmd >
<ruleset>rulesets/andcooper.xml</ruleset>
<formatter type="xml" toFile="${inreports-folder}/${project.name}.${DSTAMP}.${TSTAMP}.pmd.xml"/>
<auxclasspath>
<pathelement location="${android-jar}"/>
<fileset dir="${project.home}/libs">
<include name="*.jar" />
</fileset>
</auxclasspath>
<classpath refid="reporttools.classpath" />
<fileset dir="${source-location}" includes="**/*.java" />
</pmd>
<xslt basedir="${inreports-folder}" destdir="${outreports-folder}"
includes="${project.name}.${DSTAMP}.${TSTAMP}.pmd.xml"
style="${pmd.home}/andcooper.pmd.xsl">
<param name="rulesets" expression="${rulesets}"/>
<param name="project" expression="${project}"/>
<param name="today" expression="${today}"/>
</xslt>
Of course you will have to define your own ANT properties. It is assumed that the PMD ruleset is in the PMD.jar and thus you will include again with classpath refid
so that the PMD task can find the ruleset. Also notice to use the PMD xslt provided stylesheet you should provide two xslt parameters to the xslt task
What is a Mini-Continuous Integration Server for Android

- Image via CrunchBase
When I started developing AndCooper I certainly did not intend to build a continuous integration server. But, along the way it seemed that Android Application development might need one. Not in the sense that it attempts to solve all problems but problems that are specific to Android Application Development.
What does a mini-continuous integration server look like? Its very small in Ant build script size and made to act as a Java Builder within modern IDE tools to get that incrmental set of builds as the developer is coding and thus generate code analysis reports as the develpoer is developing code. The analysis is specifically adjusted to pertain to Android developer challgnes, for example a new set of PMD rules beyond the PMD provided ruleset for Android, such as a rule checking for services leaks in code.
On the ease of code analaysis report use and etc, a web dash board to view reports and eventually BiRT functionalities to query analysis data. The mini-continuous integration server for Android application development looks different in that there is no server really deploy just drop it in yoru project folder and point the IDE JavaBuilder to use the build script, its just that simple.
As I finish version 0.1 over the weekend I am wondering how AndCooper will be received by Google, OHA members such as Motorola and etc as having a mini-continuous integration server for Android application development is kind of a new concept. And having support for javascript analysis for webview Android applications is a even neweer concept. Its a trail that no-one has trail-blazed before.
![Reblog this post [with Zemanta]](http://img.zemanta.com/reblog_e.png?x-id=af0d10cb-295f-41b7-8221-bf63ee7de2b5)
![Reblog this post [with Zemanta]](http://img.zemanta.com/reblog_e.png?x-id=103e0fe7-ae4e-4c51-9557-2c4925bfae33)
![Reblog this post [with Zemanta]](http://img.zemanta.com/reblog_e.png?x-id=95983cb9-fc1d-47f8-af4d-d5532634753a)
![Reblog this post [with Zemanta]](http://img.zemanta.com/reblog_e.png?x-id=a7d79f47-2825-4871-afcd-6a244b53039d)
![Reblog this post [with Zemanta]](http://img.zemanta.com/reblog_e.png?x-id=5cea9009-ad58-4b94-9601-dcdf554c79f3)
![Reblog this post [with Zemanta]](http://img.zemanta.com/reblog_e.png?x-id=a653116b-3863-41cf-bc22-2c0bf6cf2716)


