Android Ant Build - java

I would like to build two versions of my Androidapplication using an Apache ant file. The problem is, that both versions are identical except the advertisement in the lite version. I read about using Configurations with ant to build debug versions.
The following class defines some constants that can be referenced within the application.
public class Config {
// Whether or not to include logging in the app.
public final static boolean LOGGING = true;
}
And here is an example on how to use this constants to determine if logging is enabled or not.
if (Config.LOGGING) {
Log.d(TAG, "[onCreate] Success");
}
Now i can enable and disable logging in my properties file.
# Turn on or off logging.
config.logging=true
That does not work, because before using this config I have to create a second config file and use filterset and copy.
public class Config {
// Whether or not to include logging in the app.
public final static boolean LOGGING = #CONFIG.LOGGING#;
}
That's pretty easy, but how I could use this to build two versions of my application with and without advertisement. And how could I change the package names using ant, so the android market would accept both packages (Full and Lite).
Thank you, for your suggestions, but I still have some problems.
I managed to write some basic targets that cleanup my builds and copy all files needed to build the application in two folders /full and /lite. So I have two directories with the same content. Now I rename all matches of the applications package name in all *.java files and the AndroidManifest file (target prepare).
To really build two different version I would now have to include the code from my first post. But how do I have to do this and how can I build both versions in the release target and write the resulting *.apk files into the build directoy?
Finally ... Would that be all I have to do to build running *.apks that would be accepted by the android market?
<?xml version="1.0" encoding="UTF-8"?>
<project name="my.application" default="help" basedir=".">
<!-- Load the custom property files -->
<property file="build.properties" />
<property file="passwords.properties" />
<!-- Set global properties for this build -->
<property name="my.application.pkg" value="my.application"/>
<property name="my.application.pkg.full" value="my.application.full"/>
<property name="my.application.pkg.lite" value="my.application.lite"/>
<property name="my.application" location="."/>
<property name="my.application.build" location="build"/>
<property name="my.application.src" location="src"/>
<property name="my.application.res" location="res"/>
<property name="my.application.gen" location="gen"/>
<property name="my.application.full" location="full"/>
<property name="my.application.full.src" location="full/src"/>
<property name="my.application.full.res" location="full/res"/>
<property name="my.application.full.gen" location="full/gen"/>
<property name="my.application.full.build" location="full/build"/>
<property name="my.application.lite" location="lite"/>
<property name="my.application.lite.build" location="lite/build"/>
<property name="my.application.lite.src" location="lite/src"/>
<property name="my.application.lite.res" location="lite/res"/>
<property name="my.application.lite.gen" location="lite/gen"/>
<!-- Create and update the local.properties file -->
<loadproperties srcFile="local.properties" />
<!-- Load the ant.properties file -->
<property file="ant.properties" />
<!-- Load the project.properties file -->
<loadproperties srcFile="project.properties" />
<!-- Quick check on sdk.dir. -->
<fail
message="sdk.dir is missing."
unless="sdk.dir" />
<!-- Version-tag: 1 -->
<import file="${sdk.dir}/tools/ant/build.xml" />
<target name="release" depends="report, prepare">
<echo>Building the target!</echo>
</target>
<target name="prepare" depends="cleanup" >
<!-- Copy the Manifest.xml to the full copy -->
<copyfile src="${my.application}/AndroidManifest.xml"
dest="${my.application.full}/AndroidManifest.xml" />
<!-- Copy the source files to the full copy -->
<copy todir="${my.application.full.src}" overwrite="true">
<fileset dir="${my.application.src}" />
</copy>
<!-- Copy the resources to the full copy -->
<copy todir="${my.application.full.res}" overwrite="true">
<fileset dir="${my.application.res}" />
</copy>
<!-- Copy the generated to the full copy -->
<copy todir="${my.application.full.gen}" overwrite="true">
<fileset dir="${my.application.gen}" />
</copy>
<!-- Replace the package name in the full manifest file -->
<replaceregexp file="${my.application.full}/AndroidManifest.xml"
match='package="(.*)"'
replace='package="${my.application.pkg.full}"'
byline="false" />
<!-- Change the package name in all Java files -->
<replaceregexp flags="g" byline="false">
<regexp pattern="${my.application.pkg}" />
<substitution expression="${my.application.pkg.full}" />
<fileset dir="${my.application.full.src}" includes="**/*.java" />
</replaceregexp>
<!-- Copy the Manifest.xml to the lite copy -->
<copyfile src="${my.application}/AndroidManifest.xml"
dest="${my.application.lite}/AndroidManifest.xml" />
<!-- Copy the source files to the lite copy -->
<copy todir="${my.application.lite.src}" overwrite="true">
<fileset dir="${my.application.src}" />
</copy>
<!-- Copy the resources to the lite copy -->
<copy todir="${my.application.lite.res}" overwrite="true">
<fileset dir="${my.application.res}" />
</copy>
<!-- Copy the generated to the lite copy -->
<copy todir="${my.application.lite.gen}" overwrite="true">
<fileset dir="${my.application.gen}" />
</copy>
<!-- Replace the package name in the lite manifest file -->
<replaceregexp file="${my.application.lite}/AndroidManifest.xml"
match='package="(.*)"'
replace='package="${my.application.pkg.lite}"'
byline="false" />
<!-- Change the package name in all Java files -->
<replaceregexp flags="g" byline="false">
<regexp pattern="${my.application.pkg}" />
<substitution expression="${my.application.pkg.lite}" />
<fileset dir="${my.application.lite.src}" includes="**/*.java" />
</replaceregexp>
</target>
<!-- Deletes all directories, not needed anymore after compiling the source files -->
<target name="cleanup">
<!-- Delete the full version build dir -->
<delete dir="${my.application.full}"/>
<!-- Delete the lite version build dir -->
<delete dir="${my.application.lite}"/>
<!-- Delete the *.apk file -->
<delete file="my.application.full.apk"/>
<!-- Delete the *.apk file -->
<delete file="my.application.lite.apk"/>
</target>
</project>

There are a number of ways in which you could achieve what you require.
Here are a couple of ideas that I have used in the past,
1) Have two application 'heads' that pull in a common Android library.
Each head initializes static data that sets up the library to behave as either the lite or the full version of your application.
This has the advantage that you can perform the build from Eclipse projects as well as with Ant.
2) Have two seperate build targets that share common build targets to create two seperate apk files.
In the Ant build script have it build two versions of the APK.
One that is the full version and then the other which builds the lite version.
The difference between the two targets are that they build using slightly different files (either by copying, directing to diferent directories or modifying with scripts).
This can all be done in Ant using targets and properties.
If at the top level of your build you have a release target depending on two other targets.
e.g.
<target name="release"
depends="release-Full, release-Lite">
</target>
<target name="release-Full">
<ant antfile="thisbuild.xml" inheritAll="true" target="full">
<property name="MyCustomProperty" value="Full" />
</ant>
</target>
<target name="release-Lite">
<ant antfile="thisbuild.xml" inheritAll="true" target="lite">
<property name="MyCustomProperty" value="Lite" />
</ant>
</target>
You can then use these targets and properties to modify your build to do whatever you require to build each of the APK files.

Related

Placeholder for value/version/date replacement in xml using Ant build

I have more than 30 odx-d files (odx-d is just xml file with different extension).
All files have common tags:
<DOC-REVISION>
<REVISION-LABEL>01.02.03-04</REVISION-LABEL>
<STATE>RELEASE</STATE>
<DATE>2018-11-14T16:26:00+01:00</DATE>
</DOC-REVISION>
At every release I need to change these values in all files.
Note: Manipulation using Java is not possible as while build just making zip of all these files not using Java to manipulate these files.
Please suggest a way to have one file (any file type you suggest) where I can have these values and place holders for the tags in all these files.
Thanks.!
This is doable with the following steps:
replace the common tag values with placeholders e.g. #revision#,
#state#, #date#
copy each file to a temporary location
perform the replacements in the copied files using a <replace file="${dest.file}"> task with nested <replacefilter .../> elements
zip the transformed files in the temporary location
For example, using a template file "template.xml" like this:
<DOC-REVISION>
<REVISION-LABEL>#revision#</REVISION-LABEL>
<STATE>#state#</STATE>
<DATE>#date#</DATE>
</DOC-REVISION>
you can set the real values with this ant target (skipping the zip part):
<target name="test">
<property name="my.revision" value="01.02.03-04"/>
<property name="my.state" value="RELEASE"/>
<tstamp>
<format property="my.date" pattern="yyyy-MM-dd hh:mm z"/>
</tstamp>
<property name="template.file" value="./template.xml"/>
<property name="dest.file" value="./doc.odx"/>
<delete file="${dest.file}" quiet="true"/>
<copy toFile="${dest.file}" file="${template.file}"/>
<replace file="${dest.file}">
<replacefilter token="#revision#" value="${my.revision}"/>
<replacefilter token="#state#" value="${my.state}"/>
<replacefilter token="#date#" value="${my.date}"/>
</replace>
</target>
Solution for multiple files.
Replace values with placeholders #revision#, #state#, #date# and place into template folder.
Perform the copy operation with filterset from template to dest directory.
Example:
Template dir: 'fromDir', destination: 'toDir'
1) Template files:
<DOC-REVISION>
<REVISION-LABEL>#revision#</REVISION-LABEL>
<STATE>#state#</STATE>
<DATE>#date#</DATE>
</DOC-REVISION>
2) Declare properties and perform test target operation.
<!-- Properties -->
<property name="version" value="01.02.03-04" />
<property name="state" value="RELEASE" />
<tstamp>
<format property="now" pattern="yyyy-MM-dd'T'HH:mm:ss.SSSXXX"/>
</tstamp>
<!-- Target -->
<target name="test">
<copy todir="${toDir}">
<fileset dir="${fromDir}" />
<filterset>
<filter token="revision" value="${version}" />
<filter token="state" value="${state}" />
<filter token="date" value="${now}" />
</filterset>
</copy>
</target>
Thanks!

Nutch - Could not load definitions from resource org/sonar/ant/antlib.xml

I'm learning Nutch through the official guide. So when I run Ant at bin directory, it says:
"Could not load definitions from resource org/sonar/ant/antlib.xml. It
could not be found."
I've spent a lot of time in google to solve it, but I failed. My OS is Ubuntu16.04.
Try to comment all this part in build.xml:
<!-- ================================================================== -->
<!-- SONAR targets -->
<!-- ================================================================== -->
<!-- Define the Sonar task if this hasn't been done in a common script -->
<taskdef uri="antlib:org.sonar.ant" resource="org/sonar/ant/antlib.xml">
<classpath path="${ant.library.dir}"/>
<classpath path="${mysql.library.dir}"/>
</taskdef>
<!-- Add the target -->
<target name="sonar" description="--> run SONAR analysis">
<!-- list of mandatory source directories (required) -->
<property name="sonar.sources" value="${src.dir}"/>
<!-- list of properties (optional) -->
<property name="sonar.projectName" value="Nutch Trunk 1.4 Sonar Analysis" />
<property name="sonar.binaries" value="${build.dir}/classes" />
<property name="sonar.binaries" value="${build.dir}/plugins" />
<property name="sonar.tests" value="${test.src.dir}" />
<sonar:sonar workDir="${base.dir}" key="org.apache.nutch:trunk"
version="1.4-SNAPSHOT" xmlns:sonar="antlib:org.sonar.ant"/>
</target>
in this way, it should work.

Issue while creating war using ant with Jenkins

I have a ant build script which creates a war file. The file content are as follows.
<?xml version="1.0" encoding="UTF-8"?>
<project name="TestProj" default="war" basedir=".">
<property name="project-name" value="${ant.project.name}" />
<property name="builder" value="IaasTeam" />
<property name="war-file-name" value="${project-name}.war" />
<property name="source-directory" value="src" />
<property name="classes-directory" value="build/classes" />
<property name="web-directory" value="WebContent" />
<property name="web-xml-file" value="WebContent/WEB-INF/web.xml" />
<property name="lib.dir" value="WebContent/WEB-INF/lib" />
<property name="catalina.home" value="../../outside/project/lib"/>
<tstamp prefix="build-info">
<format property="current-date" pattern="d-MMMM-yyyy" locale="en" />
<format property="current-time" pattern="hh:mm:ss a z" locale="en" />
</tstamp>
<property name="build-directory" value="build" />
<path id="classpath">
<fileset dir="${lib.dir}" includes="**/*.jar"/>
<fileset dir="${catalina.home}" includes="**/*.jar"/>
</path>
<target name="clean">
<delete dir="build"/>
</target>
<target name="compile">
<mkdir dir="build/classes"/>
<javac includeantruntime="false" srcdir="src" destdir="build/classes" classpathref="classpath" />
</target>
<target name="war" depends="clean,compile">
<mkdir dir="${build-directory}" />
<delete file="${build-directory}/${war-file-name}" />
<war warfile="${build-directory}/${war-file-name}" webxml="${web-xml-file}">
<classes dir="${classes-directory}" />
<fileset dir="${web-directory}">
<!-- Need to exclude it since webxml is an attribute of the war tag above -->
<exclude name="WEB-INF/web.xml" />
</fileset>
<manifest>
<attribute name="Built-By" value="${builder}" />
<attribute name="Built-On" value="${build-info.current-date}" />
<attribute name="Built-At" value="${build-info.current-time}" />
</manifest>
</war>
</target>
I am using Jenkins as a build server (this is hosted on different machine kind of DEV environment).
I also use Gitlab as a repository and after pushing the latest code I have a hook for Jenkins job which gets triggered automatically and calls this build.xml.
Now the issues here is that when I run this script on my local machine everything works well but when Jenkins execute this it fails during the compilation phase giving me below error.
compile:
[mkdir] Created dir: /app/infra/jenkins/workspace/TestProj/build/classes
[javac] Compiling 49 source files to /app/infra/jenkins/workspace/TestProj/build/classes
BUILD FAILED
/app/infra/jenkins/workspace/TestProj/build.xml:27: /app/infra/jenkins/outside/project/lib does not exist.
The reason for this issue is the build server does not have any directoy called outside/project/lib.
The only reason of adding this directory in my build.xml is to have the container specific jar files ready for compiling.
How can I fix this issue?
Do I need to copy container specific jars on my build server? Or is there any way to tell Jenkins that not to copy this external jars but just use them for compilation.
Where would Jenkins find the jars? They need to be accessible otherwise your build will fail. If you don't want to have the files checked in (which is very sensible), you could use Apache Ivy to download them for you.
This is the most common way of handling the situation you're having. Using a dependency management framework like Ivy (or Maven, or similar) will save you a lot of headaches down the line. I recommend you have a look at their tutorial. After you set it up, your ant build will take care of downloading the files you need.

Create a WAR file with version using ANT

I have a problem trying to build a WAR file with a version number.
This is my build.properties
jboss.home=D\:\java\jboss-as-7.1.1.Final
version=2.0
And this is part of my ANT task
<project name="AS2-jBoss7" basedir="../" default="deploy">
<!-- Configuraciones del proyecto -->
<property name="project.distname" value="AS2" />
<!-- Paths locales del sistema -->
<property file="${basedir}/ant/build.properties" />
<property name="webroot.dir" value="${basedir}/WebContent" />
<property name="webinf.dir" value="${webroot.dir}/WEB-INF" />
<property name="build.dir" value="build" />
<!-- Build project -->
<target name="build" depends="prepare,compile" />
<target name="rebuild" depends="clean,prepare,compile" />
<!-- Crea el war de la aplicacion -->
<target name="war" depends="build">
<mkdir dir="${build.dir}" />
<war basedir="${webroot.dir}" warfile="${build.dir}/${project.distname}_${version}.war" webxml="${webinf.dir}/web.xml">
<exclude name="WEB-INF/${build.dir}/**" />
<exclude name="WEB-INF/otros/**" />
</war>
</target>
<!-- Despliega el proyecto -->
<target name="deploy" depends="war">
<delete file="${deploy.dir}/${project.distname}.war" />
<delete dir="${deploy.dir}/${project.distname}" />
<copy file="${build.dir}/${project.distname}_${version}.war" todir="${deploy.dir}" />
</target>
</project>
When I build my WAR file the name is AS2_2.0.war and that is correct, but when I view the site in the web browser I have to write the url:
http://localhost:8030/AS2_2.0/login.jsf
What I want is that the WAR version is AS2_2.0 but the URL does not contain the version number, how could I do that?
This has nothing to do with ANT, your application server is using the name of the WAR by default. What you want to do is change the "context root" for your web application. If you Google that phrase, along with the name of your application server (e.g. "Tomcat" or "JBoss"), I'm sure you'll find your answer. Or, if you tell me what server you're using I can try and help you.
See http://ant.apache.org/manual/Tasks/copy.html In examples, you can copy a single file with ant just like this,
<copy file="myfile.txt" tofile="mycopy.txt"/>
In your case supposing you want the deployed file to be named AS try
<target name="deploy" depends="war">
<delete file="${deploy.dir}/${project.distname}/AS.war" />
<delete dir="${deploy.dir}/${project.distname}" />
<copy file="${build.dir}/${project.distname}_${version}.war" tofile="${deploy.dir}/AS.war" />
</target>

Is there an ant task to add a .war to an existing exploded ear

Have a build process that can't be edited and need to pack another war in the the ear that is generated. The ear is exploded so it's just a matter of copying the war file into it but the application.xml needs to be updated so I'd like to find an ant task that will do this. Anyone know of one that will work?
ended up just doing :
<replace file="${j2ee.build.dir}/${j2ee.app..name}/META-INF/application.xml" token="</application>" value="<module><web><web-uri>admin.war</web-uri><context-root>/admin</context-root></web></module></application>"/>
Rather hackish but couldn't come up with another way to edit the file easily
The idea is to create the war and put the file into the ear directory, see the following build.xml code
<?xml version="1.0"?>
<project name="Add war to ear example" default="all" basedir=".">
<target name="init">
<property name="root.directory" value="${basedir}"/>
<property name="classdir" value="${root.directory}/build/src"/>
<property name="src" value="${root.directory}/src"/>
<property name="web" value="${root.directory}/web"/>
<property name="deploymentdescription" value="${root.directory}/build/deploymentdescriptors"/>
<property name="war.file" value="test.war"/>
<property name="ear.file" value="test.ear"/>
<property name="ear.directory" value="${root.directory}/build/ear"/>
<property name="war.directory" value="${root.directory}/build/war"/>
<!-- Create Web-inf and classes directories -->
<mkdir dir="${war.directory}/WEB-INF"/>
<mkdir dir="${war.directory}/WEB-INF/classes"/>
<!-- Create Meta-inf and classes directories -->
<mkdir dir="${ear.directory}/META-INF"/>
</target>
<!-- Main target -->
<target name="all" depends="init,build,buildWar,buildEar"/>
<!-- Compile Java Files and store in /build/src directory -->
<target name="build" >
<javac srcdir="${src}" destdir="${classdir}" debug="true" includes="**/*.java" />
</target>
<!-- Create the War File -->
<target name="buildWar" depends="init">
<copy todir="${war.directory}/WEB-INF/classes">
<fileset dir="${classdir}" includes="**/*.class" />
</copy>
<copy todir="${war.directory}/WEB-INF">
<fileset dir="${deploymentdescription}" includes="web.xml" />
</copy>
<copy todir="${war.directory}">
<fileset dir="${web}" includes="**/*.*" />
</copy>
<!-- Create war file and place in ear directory -->
<jar jarfile="${ear.directory}/${war.file}" basedir="${war.directory}" />
</target>
<!-- Create the War File -->
<target name="buildEar" depends="init">
<copy todir="${ear.directory}/META-INF">
<fileset dir="${deploymentdescription}" includes="application.xml" />
</copy>
<!-- Create ear file and place in ear directory -->
<jar jarfile="${root.directory}/${ear.file}" basedir="${ear.directory}" />
</target>
</project>
Won't <copy> do the job?
What about using <xslt> to modify application.xml then?

Categories