is a special file in your home directory, in the sense that the commands in the$HOME/.profilefile areexecuted at login or open a new terminal session. These commands may be used to override the defaultenvironment behavior.2.Typecd ~to go to your home directory.3.Typetouch .profile2to create the hidden file named.profile, if one does not exist.4.Typeopen -e .profileto open the file in the TextEdit application.5.Then typeexport PATH=${PATH}:${ANDROID_HOME}/tools:${ANDROID_HOME}/platform-tools.6.Save the file and exit TextEdit, and we are done!The changes you made in your profile file may not be in effect yet on the current ter‐minal, so you need to runsource ~/.profileto enable the changes (you need only dothis once for the current terminal). You can also just restart your terminal for a similareffect.Here’s an example of a.profilefile:# sample Android SDK tools and platform-tools paths for MAC# export ANDROID_HOME=/Users/<username>/android-sdksPATH=${PATH}:${ANDROID_HOME}/tools:${ANDROID_HOME}/platform-toolsWhat Is ADB (Android Debug Bridge)?Mobile applications are often developed on a machine that is different from the deviceyou finally deploy your solution on, and Android is no different. The machine on whichyou develop the solution is called a host, while the device for which the solution isintended is referred to as a target.ADB is a handy tool that comes as part of the Android SDK, which allows you to interactwith your connected Android devices or emulator (target) from the command line onthe host. An Android device can be connected to the development host machine usingeither TCP or USB.Basic ADB commands include:adb devicesLists the devices (targets) currently associated with the host.adb shellOpens a session to a basic shell running on the Android device.adb installInstalls an application (*.apk) file onto your device.What Is ADB (Android Debug Bridge)? | 17www.it-ebooks.infoadb uninstallUninstalls an application from the device.adb logcatStreams the activity log from your device to the console.adb shell am startSends an intent to the package manager component to be started. The intent maystart an activity (application) or may just deliver the intent to an existing activity ifit is already running.adb shell am instrumentStarts an instrumentation. Typically, this target <COMPONENT> is in the form<TEST_PACKAGE>/<RUNNER_CLASS>.adb shell dumpsys <?>Dumps all available data about a given parameter. For example, you can get moreinformation about the battery by typing the following command: adb shell dumpsys battery. To get the list of services in Android from the command line, youcan run adb shell dumpsys | grep DUMP. Once you get the result, you can thenrun each command individually.adb shell "am start -a android.intent.action.MAIN -n <packagename>/<classname with packagename>"Launches the activity from command line. For example, you can try adb shell "amstart -a android.intent.action.MAIN -n com.example.package/com.example.package.ExampleActivity".Connecting an Android Device to the Development HostSetting up a connection between an Android device and the host is very straightforward.If connecting via USB, all you need to do is connect the device and the developmenthost via a USB cable. After this, you should be able to access the device using ADB orEclipse.On Windows, you may have to install device-specific drivers beforeyou can connect to a device. However, once the drivers are installed,the process is pretty much the same.Connecting to an Android Device Over WiFiADB can connect to a device over WiFi as well. You can enable ADB over WiFi on thedevice by executing the following set of commands on the device.18 | Chapter 2: Setting Up Your Android Development Environmentwww.it-ebooks.infoadb shellsetprop service.adb.tcp.port 9999stop adbd start adbdOn the development computer, you can connect to the device using the following com‐mand:adb connect 192.168.1.1:9999Make sure you replace 192.168.1.1 with the actual IP address associated with the An‐droid device and 9999 with an available port on the device you wish to use for ADB.The following command can be used to switch ADB back to the USB mode:adb usbUsing Apache Ant to Automate Building AndroidApplicationsTo compile and package the application into what is known as an Android Package(APK) from the command line, we will use Apache Ant. Apache Ant is a command-linetool and a library (depending upon how you wish to use it) that can be used to automatethe build process or tasks. Ant provides a number of prepackaged tasks to compile,assemble, and build Java applications. We chose Apache Ant as our command-line buildtool because Google, along with Eclipse plug-ins, ships an Ant-based build system andassociated tool chain.Simply put, Ant is a tool that processes an XML-based scripting language to automatetasks. While you can provide any Ant-compliant XML file to Ant for execution, thedefault filename is build.xml. You can define all necessary build steps in this file. EachAnt XML file is described in terms of a project, target, or task.Google announced as part of the 2013 I/O conference that they will bemigrating from an Ant-based build system to a Gradle (Groovy) basedbuild system for Android. While the build system is still nascent, itholds promise. We will be releasing all our build scripts for Gradleeventually as the build system matures.Here are some Ant terms with which you should be familiar:Ant projectAn Ant project is a group of targets, and tasks. A project is typically associated witha single build file.Using Apache Ant to Automate Building Android Applications | 19www.it-ebooks.infoAnt targetA series of Ant tasks to be executed in the order in which they are specified. An Anttarget can depend upon a number of other Ant targets for completion, there byallowing us to build modular tasks.Ant tasksA unit of work that Ant can execute, such as compiling a source file, renaming files,and so on. As discussed earlier, there are number of tasks that come prepackagedwith Ant. Users can develop their own tasks in Java or another scripting languageas desired. As you delve deeper into the details of Ant, you’ll realize the whole Anttask notion is very flexible and can be leveraged to perform very complex operationsin a modular way.To create a new Android project from the command line:$ mkdir project_dir$ cd project_dir$ android create project -n HelloWorld -p ./ -t android-14-k com.helloworld --activity MainActivity# -p is the path where the project files are to be generated# -n Specified the name of the Project# -t The android SDK to be used for compilation# -k package name for the generated project# --activity Name of the generated Activity ClassHere’s the output of the preceding command:Created directory/Users/<username>/project_dir/src/com/helloworld Added file./src/com/helloworld/MainActivity.java Created directory/Users/<username>/project_dir/res Created directory/Users/<username>/project_dir/bin Created directory/Users/<username>/project_dir/libs Created directory/Users/<username>/project_dir/res/values Added file./res/values/strings.xml Created directory/Users/<username>/project_dir/res/layout Added file./res/layout/main.xml Created directory/Users/<username>/project_dir/res/drawable-xhdpi Created directory/Users/<username>/project_dir/res/drawable-hdpi Created directory/Users/<username>/project_dir/res/drawable-mdpi Created directory/Users/<username>/project_dir/res/drawable-ldpi Added file./AndroidManifest.xml Added file ./build.xml Added file./proguard-project.txtYou’ll notice that upon execution, a number of files—including build.xml—will be gen‐erated by the Android tool. We will look at some of these files in this chapter. Let’s lookat build.xml for now.<?xml version="1.0" encoding="UTF-8"?><project name="HelloWorld" default="help"><property file="local.properties" />20 | Chapter 2: Setting Up Your Android Development Environmentwww.it-ebooks.info<property file="ant.properties" /><property environment="env" /><condition property="sdk.dir" value="${env.ANDROID_HOME}"><isset property="env.ANDROID_HOME" /></condition><loadproperties srcFile="project.properties" /><fail message="sdk.dir is missing. Make sure to generate local.proper-ties using 'android update project' or to inject it through the ANDROID_HOME'"unless="sdk.dir"/><import file="custom_rules.xml" optional="true" /><import file="${sdk.dir}/tools/ant/build.xml" /></project>To create the Ant build system for an existing project created using Eclipse, run thefollowing:$ cd project_dir $ android update project -p .# -p is the pathExecuting this command generates a build.xml quite similar to the one just shown. Theonly difference being that, in this case, it will be able to retrieve Android target infor‐mation and project details from the AndroidManifest.xml file in the current projectfolder.Once you create the Ant build files in your project, type ant help on command line tosee the available list of targets. (For Ant newbies, we are launching Ant and asking it toexecute tasks associated with the help target.)Now that we have a basic understanding of how Ant works, let’s address the functionalityof some common build targets you will be using through your development.# cleans up the compiled files and generated resourcesant clean# compile and package a debug version of the appant debug# builds the debug version and installs it on the device or the# emulator. Another interesting aspect to observe is that you are chaining# multiple targets in the order they were mentioned on the command lineant debug install# builds release versionant releaseIf you want to release your Android application to Google Play or any other app store,you need to self-sign your application with a certificate. Details about creating a self-sign certificate can be found at the Android application signing instruction website.In general, you will execute the following command to generate a signing key:Using Apache Ant to Automate Building Android Applications | 21www.it-ebooks.infokeytool -genkey -v -keystore project_release.keystore -alias \project -keyalg RSA -keysize 2048 -validity 10000After running this command, the key tool will prompt you for a password and a numberof distinguished data fields to identify your key and the keystore. It then generates thekeystore as a file called project_release.keystore in the current directory. The keystore and key are protected by the passwords you entered. The keystore contains asingle key, valid for 10,000 days. After having created a valid key store, you will have toinform the Android build system about the keystore to be used for your project. Dothat by creating an ant.properties file in your project’s base directory (in the same di‐rectory as build.xml). In this file, you need to specify the paths to the signing key andthe alias.# sample ant.properties file# Relative path to the keystorekey.store=project_release.keystore# The alias for thekey.alias=project# The password which you supplied while creating the alias for thekey.alias.password=MyPassword# Password for the keykey.store.password=MyPasswordSigning an application in Android associates it with a developer, which can then be usedto ascertain valid updates and remove applications from the app store.Understanding the Android Build ProcessThe build process is almost similar for Eclipse and command-line builds. Unless youare customizing the build process, they are one and the same. The Android build systemcompiles your source code along with resources, then packages them into a ZIP-compatible archive format. The build process on Android is composed of multiplestages. Let’s look at these stages.Resource PrecompilationThe first step of the Android build system deals with autogeneration of an R.java fileusing the apt tool. This file is placed inside the gen folder, and contains constants forall resources in your project. The constants are used by developers to refer to resourcesinside the packaged application.Here is a sample R.java, which was generated for the hello world project:/* AUTO-GENERATED FILE. DO NOT MODIFY.*22 | Chapter 2: Setting Up Your Android Development Environmentwww.it-ebooks.info* This class was automatically generated by the* aapt tool from the resource data it found. It* should not be modified by hand. */package com.helloworld;public final class R {public static final class attr { }public static final class drawable {public static final int ic_launcher=0x7f020000;}public static final class layout {public static final int main=0x7f030000;}public static final class string {public static final int app_name=0x7f040000;}}Service Interface PrecompilationThe second build step deals with autogeneration of Java code corresponding to theservice interfaces declared in your project. Service interfaces are aidl files, which describea service interface. In this step, the aidl tool looks at these files and generates the ac‐companying Java code. We will not look into aidl and service interfaces in this book;this topic has just been mentioned for completeness purposes. If you’re interested inmore details on this topic, you can visit the Android AIDL website.Java CompilationAfter the code autogeneration phase is complete, the actual Java source code and theautogenerated code is compiled to produce Java byte code. During the compilationprocess, the Android build system automatically adds the following files to your class‐path (.classpath):android.jarThis file includes all android public APIs, stubs specific to the target platform foryour application.libs/*.jarLibrary jars you may have included in your project. These jars are located withinthe libs subdirectory.DEX GenerationThe output of the previous stage is a JAR file, which then needs to be converted into theDEX file format. DEX is the format supported by the Android or Dalvik virtual machine.Understanding the Android Build Process | 23www.it-ebooks.infoIn this step, the Android build system uses the dx tool to convert your application JARand all other exported JARs into a single dex file.Resource PackagingNow resources are packaged into a partial ZIP file using the apt tool. While strings areplaced in resources.arsc, the icons and other images are optimized and stored in this filepreserving their relative directory structure in the resource folder.Creation of the APK FileNext, the apk builder tool combines the resources and the dex file to create an appli‐cation package for your application inside the bin folder. The apk builder includes thefollowing components in the APK file.•The Dalvik executable file bin/classes.dex•Non Java resources in src folder•Any native code, aka shared objects included in you project•The partial resource package generated in the previous step along with the resour‐ces.arsc fileOnce the package apk file has been created, it is signed using the debug or release key,depending on whether you are compiling a debug or a release build, respectively. TheAndroid build system generates the debug key store automatically for your developmentpurposes, which is located in the $HOME/.android folder.AlignmentThe final step of the build process deals with aligning the signed apk file to the 4 byteboundary. This is done using the zipalign tool. This step is primarily an optimizationperformed by the Android build system to allow the virtual machine to better memorymap the resources at runtime.Once the apk file has been aligned, it can then be installed on the Android device or anemulator.CSS PreprocessorsCSS preprocessors take the CSS representational code written in a specific language tocompile and convert it into the normal CSS format. Although CSS is really simple tounderstand, it can become hard to manage in a large scale project. With the help of CSSprocessors, we can maintain our CSS code easier and faster.24 | Chapter 2: Setting Up Your Android Development Environmentwww.it-ebooks.infoFor example, consider a scenario in which you wish to use a particular shade of blue foryour app across all the CSS files. Now, let’s assume you wish to experiment with someother color scheme and would like to see how your application looks in the new colormodel. Traditionally, you would perform a mass search and replace within the CSS files,replacing old color values with new ones. This old method is cumbersome at best, asthis kind of mass replace is often error prone because reverting the changes back mayaffect the other values.This is where the CSS preprocessors become a really handy tool for many developersand designers. As you will see later in the chapter, you can use one of the several availableCSS preprocessors to represent you application CSS in a more structured way, leveragingthe concepts of object-oriented programming. This way, instead of replacing each in‐stance of color or CSS attribute, you will focus on changing the base CSS classes withspecific values. These classes are then inherited by others to create a more structuredstyle representation for your app, thereby saving you time and preventing errors. CSSpreprocessors are based around the DRY (Don’t Repeat Yourself) principle. The syn‐taxes are much easier to read than normal CSS syntaxes because they employ moresemantic markup.There are many CSS preprocessors available for developers.•SASS•LESS•Stylus•Turbine•Switch CSS•CSS Cacheer•CSS PreprocessorWe have chosen Syntactically Awesome Style Sheets (SASS) for building the CSS filesfor our application in this book. You can use any other available technologies; the prin‐ciples involved are similar with only minor syntactical differences across these tools.You can find a lot of invaluable information about SASS at the SASSwebsite.CSS Preprocessors | 25www.it-ebooks.infoInstalling SASSSASS was developed using Ruby and ships as a Ruby Gem. If you are using OS X, Rubyand Ruby Gems are preinstalled for you. To install SASS from the command line, usethe following command:$ gem install sassFor Windows, you will first install Ruby using an installer that can be found at the RubyInstaller website. Once Ruby is installed, you can in place SASS as previously describedusing the command line.If the command fails in Windows, please make sure you have Rubyand Ruby Gems in your path. Details on managing the path variablesin Windows can be found at the Windows website for managing en‐vironment variables.Here is some sample SASS code:/* -- application.scss -- */$font_family: Arial, Helvetica;$font_size: 1.6em;$images_path: "../../img/";$padding: 18px;$height: 50%;$header_color: #00FFDE;SASS files have .SCSS file extension. These are text files which can becreated using any standard text editor.Here is a simple usage of $header_color and $font_size in your SCSS file./* -- header.scss -- */@import "application";.main_header {color: $header_color;font-size: $font_size;}As you can see, SASS allows you to define variables, which can be used across multipleCSS classes, thereby avoiding the need for you to repeat yourself.Use the following command to convert an scss file into a css file:$ sass header.scss header.css26 | Chapter 2: Setting Up Your Android Development Environmentwww.it-ebooks.infoOnce you run the command to convert the SASS file into normal CSS format, this is theoutput you will get (shown in Figure 2-4)./* -- header.css -- */.main_header {color: #00FFDE;font-size: 1.6em;}Figure 2-4. SASS conversion process flowSASS has many nice features that will help you develop your CSS quickly with littlehassle. For example, you can tell SASS to watch your SCSS files for any changes andconvert them into CSS files on the fly:# SASS will watch any changes in the +header.scss+ file# and automatically update the +header.css+ with changes.$ sass --watch header.scss:header.css# SASS will watch any changes in the +sass_source+ directory# and automatically update the files in the +stylesheet_output+# directory with changes.$ sass --watch sass_source:stylesheet_outputIntegrating SASS into the Android Command-Line Build SystemThe following ANT macrodef defines a task that can be used to preprocess SCSS files togenerate CSS files.<!-- SASS - Converting SCSS files to CSS --><macrodef name="sass-css" description="SASS - Converting SCSS files to CSS"><attribute name="include-path"/><attribute name="src-sass-file"/><attribute name="dst-css-file"/><sequential><exec executable="sass"><arg value="-I@{include-path}" /><arg value="@{src-sass-file}" /><arg value="@{dst-css-file}" /></exec></sequential></macrodef>Installing SASS | 27www.it-ebooks.infoFor this task to work correctly, make sure that SASS is properly in‐stalled and the executable is reachable through the user path. You canalso provide the complete path to the SASS executable if that is notpossible.The previous Ant macro can be called from anywhere within Ant to convert an existingSASS file to a CSS file. For example, in the hybrid application we will be building in thisbook, we have used the macro in the following way:<target name="sass-css"><sass-cssinclude-path="src/hybrid/css/ldpi"src-sass-file="src/hybrid/css/import.scss"dst-css-file="assets/css/ldpi.css" /><sass-cssinclude-path="src/hybrid/css/mdpi"src-sass-file="src/hybrid/css/import.scss"dst-css-file="assets/css/mdpi.css" /><sass-cssinclude-path="src/hybrid/css/hdpi"src-sass-file="src/hybrid/css/import.scss"dst-css-file="assets/css/hdpi.css" /><sass-cssinclude-path="src/hybrid/css/xhdpi"src-sass-file="src/hybrid/css/import.scss"dst-css-file="assets/css/xhdpi.css" /></target>As you can see, we are exporting the CSS for multiple resolutions. You can customizethis code fragment to suit your application requirements.JSLint Framework and Strict Coding ConventionsJSLint is a tool that was originally developed by Douglas Crockford for validating Java‐Script coding conventions. Although JSLint is not a proof of a program’s correctness, itcan help detect problems in your code before they slip into your production code. JSLintis highly configurable and has many features that can help spot incorrect syntax, un‐defined variables and functions, missing semicolons, erroneous expression statements,and many other pitfalls.jslint4Java is a command-line wrapper for the tool that can be integrated into Ant asa task. We will be using this task to automatically check the integrity of our JavaScriptproject every time we compile the project.<!-- JSLint - Syntax-checks JavaScript files --><property name="jslint.dir" value="${out.dir}/jslint" /><property name="jslint.version" value="1.4.7" />28 | Chapter 2: Setting Up Your Android Development Environmentwww.it-ebooks.info<target name="get-jslint"description="JSLint - Syntax-checks JavaScriptfiles" if="jslint-not-found"><mkdir dir="${jslint.dir}" /><get dest="${jslint.dir}"skipexisting="true"src="http://repo2.maven.org/maven2/rhino/js/1.7R2/js-1.7R2.jar"verbose="true" /><get dest="${jslint.dir}"skipexisting="true"src="http://repo2.maven.org/maven2/com/googlecode/jslint4Java/jslint4Java/${jslint.version}/jslint4Java-${jslint.version}.jar"verbose="true" /><get dest="${jslint.dir}"skipexisting="true"src="http://repo2.maven.org/maven2/com/googlecode/jslint4Java/jslint4Java-ant/${jslint.version}/jslint4Java-ant-${jslint.version}.jar"verbose="true" /></target><target name="run-jslint"><available file="${jslint.dir}/js-1.7R2.jar"property="js-1.7R2.present"/> <availablefile="${jslint.dir}/jslint4Java-${jslint.version}.jar"property="jslint4Java.present"/><availablefile="${jslint.dir}/jslint4Java-ant-${jslint.version}.jar"property="jslint4Java-ant.present"/><condition property="jslint-not-found"><not><and><isset property="${js-1.7R2.present}"/><isset property="${jslint4Java.present}"/><isset property="${jslint4Java-ant.present}"/></and></not></condition><antcall target="get-jslint"/><taskdef name="jslint"JSLint Framework and Strict Coding Conventions | 29www.it-ebooks.info

classname="com.googlecode.jslint4Java.ant.JSLintTask"

>

<classpath>

<pathelement

location="${jslint.dir}/js-1.7R2.jar"

/>

<pathelement

location="${jslint.dir}/jslint4Java-${jslint.version}.jar"

/>

<pathelement

location="${jslint.dir}/jslint4Java-ant-${jslint.version}.jar"

/>

</classpath>

</taskdef>

<jslint

haltOnFailure="true"

>

<formatter

type="plain"

/>

<fileset

dir="${src.dir}/js"

excludes="vendor/**/*.js"

includes="**/*.js"

/>

</jslint></target>In this Ant task, if thejslint4Javafor Ant is not available locally, we can downloadthe specified versionjslint4Java-1.4.7.jarfile while building our project. Subsequently,we will use the existing version for all future builds. The latest version ofjslint4Javacan be downloaded from thejslint4java download website.Process HTML TemplatesJohn Resig (creator of jQuery) is said to be the person who first popularized the conceptof HTML templates within script tags. Visit theJQuery Micro-Templating websiteformore information. The idea is to preload the markup data and logic within a script tagwith an invalid script type. The browser automatically ignores script tags withinvalidtypes but we are free to access the content via JavaScript. This is a lot better than theolder way of using hidden div tags because it is less memory intensive and more per‐formant.We leverage this concept and take it a step further. Basically, the idea is to build the userapplication using HTML templates, and then merge these templates intoindex.htmlduring compilation.Following is an example of what an HTML template looks like. Templates can not onlycontain regular markup but actual conditional logic to be used by template processors.Thetype="text/x-tmpl"makes this script invalid to the JavaScript interpreter. Thepurpose of this is that we want the WebView or browser to ignore the content withinthese tags and keep them nonrendered because we will be rendering these templatesusing JavaScript. All the placeholder variables in the template will be replaced with the30 | Chapter 2: Setting Up Your Android Development Environmentwww.it-ebooks.inforeal values using our JavaScript template engines. We will introduce more details aboutJavaScript templating techniques in later chapters.We have used Underscore.js for the templating engine in our sample project.<script id="tmpl_about_index" type="text/x-tmpl"><section class="content about"><div class="wrapper"><span class="title">About Hybrid Note</span><span class="summary">Hybrid Note is a productivity appfor taking your notes...</span><span class="version">Version <%= data.app_version %></span><span class="copyright">Copyright <%= data.current_year%> Hybrid Note</span></div></section></script>To facilitate the merging of HTML templates, we’ve built an Ant task to concatenate andappend all our templates inside the index.html file.<!-- Templates - Process HTML templates files --><macrodef name="templates"description="Templates - Process HTML templates files" ><sequential><!-- merge all template files into templates.html --><concat destfile="${out.dir}/templates.html" ><fileset dir="${src.dir}/templates"includes="**/*.tmpl" /></concat><loadfile property="templates"srcFile="${out.dir}/templates.html" /><copy file="${src.dir}/index.html"overwrite="true"todir="${assets.dir}" ><filterset><filter token="templates"value="${templates}" /></filterset></copy></sequential></macrodef>Process HTML Templates | 31www.it-ebooks.infoMinifying CSS and JavaScript Files Using YUI CompressorAs you are developing for mobile phones and potentially would be downloading contentover the Web, it is important to send as few bytes as possible of CSS and JavaScript overthe network. Also keep in mind that it is not only the minimum number of bytes weshould send, but the fact they should be sent across in a minimum number of requests.The minifiers are utilities that compress CSS, JavaScript, and HTML markup files, whilestill retaining the structure of code, thereby reducing the amount of data transmittedover the wire.YUI Compressor is a Java-based, free, open source tool. It is one of the most popularJavaScript minifier tools, designed to be very safe and yield a better compression ratio.The YUI Compressor can also compress CSS files. With the help of YUI Compressorand Ant, we can consolidate our JavaScript and CSS files, then compress and combinethem into a single minified version, one for CSS and one for JS, in order to obtain fasterloading time and optimize overall performance.<!-- tells Ant to refer to your environment vars --><property environment="env" /><!-- defines location of YUI Compressor --><property name="lib.dir" value="${env.COMPRESSOR_HOME}" /><!-- defines output directory --><property name="build.dir" value="build" /><!-- output files, one for JS one for CSS --><property name="final_js" value="${basedir}/js/complete.js" /><property name="final_css" value="${basedir}/css/complete.css" /><!-- define nicknames for libraries --><property name="yui-compressor"location="${lib.dir}/yuicompressor-2.4.2.jar" /><property name="yui-compressor-ant-task"location="${lib.dir}/yui-compressor-ant-task-0.5.jar" /><!-- adds libraries to the classpath --><path id="yui.classpath"><pathelement location="${yui-compressor}" /><pathelement location="${yui-compressor-ant-task}" /></path><!-- define tasks --><taskdef name="yui-compressor"classname="net.noha.tools.ant.yuicompressor.tasks.YuiCompressorTask"><classpath refid="yui.classpath" /></taskdef><!-- targets -->32 | Chapter 2: Setting Up Your Android Development Environmentwww.it-ebooks.info<target name="-concat"><!-- concatenates all compressed JS files into one --><concat destfile="${final_js}" force="true" fixlastline="true">