I'm trying to get a handle on this whole "Ant" buildsystem thing. I've created a build.xml that Android natively gives me by using the command: android update project -p . .
While this has given me a template build.xml file, I would like a couple more options. Specifically, I would like to be able to JAR and/or Compile my project; preferably with a version number.
Bonus Question: How can I exclude files from my JAR build. For example, I have one activity that I've used to test my functionality, but I don't want that to be included in the final JAR.
My build.xml file that Android has given me is Gisted here since it's pretty long (mostly comments).
EDIT: I'm also using IntelliJ so no Eclipse specifics, please!
Specifically, I would like to be able to JAR and/or Compile my project; preferably with a version number.
In Android, version numbers are for apps, not JARs.
That being said, adding a jar target is a matter of adding this to your build.xml file towards the bottom:
<target name="jar" depends="debug">
<jar
destfile="bin/whatever-you-want-to-call-the.jar"
basedir="bin/classes"
/>
</target>
Then, run ant jar to compile and package the JAR file.
You will see this pattern in most of the reusable Android components in my GitHub area (see the cwac- repos).
Bonus Question: How can I exclude files from my JAR build. For example, I have one activity that I've used to test my functionality, but I don't want that to be included in the final JAR.
Use excludes or excludesfile, as described in the jar Ant task documentation.
For reuse of Android and non-android projects I would suggest you take a look at the Android Maven Plugin. It takes advantage of dependency management and other powerful features of Maven and will be much more suitable to what you want to do.
Checkout the webpage and documentation on it and maybe the chapter about Android development in Maven : The Complete Reference I wrote to get a bit more understanding as well as have something to look at about Maven.
The Android plugin supports reuse for normal jar artifacts and if there are Android dependencies within the code you can use apklib projects. Lots of projects like Roboguice, robolectric, actionbarsherlock and others use this feature successfully.
Related
I work for a company which has a android mobile application developed by an offshore team. I have access to GitHub repositories.
I am piecing together the android app block by block and it is giving me hell.
How do I distinguish between module, libraries, jar, library projects, gradle projects, aar and jar. Can someone please give me a practical definition. NOT out of a freaking google search. I have Google too.
PS yes I am a noob and not proud of it.
I'm just giving a brief description about each of these. I hope I'm clear.
Module : A Module is an component of your application that can build / test independently and re use it in another application if required.
Libraries : AAR files, JAR files etc.
JAR : Java library
AAR : Just like JAR, only difference is that it also contains android specific files like resources etc.
Gradle Project : Gradle is just a build system which is used by Android Studio to build the android project. Its very much powerful as compared to the build system which was used in Eclipse earlier.
Library Project : An Android library project is similar to an Android app project in that it also includes a project manifest file in the project’s root directory. Also, this directory contains src, res, and other directories that you also find when building an app project.
However, there is a significant difference. You cannot compile a library project into an APK file because a library project doesn’t describe an app. Instead, it provides reusable code and resources that contribute to an app when the app’s project and source code refer to the library project. At build time, this code and these resources are merged into the app’s APK file.
To explain more on this, let me give you an example :
Say you want to use a networking library volley for making API calls, now since this is an open source library from Google you can clone it making customisations as per your requirement.
You can make volley library as your Library Project, build it independently, unit test, etc.
Now say you started building an application where you need to make HTTP calls so you need to add volley library to your project. You have two choices for that :
Compile your library project volley, generate the aar file and add it your app Project.
Add Volley as module in your project. (If you choose this option you can make changes to volley library in same studio project since it will act as a component in your project)
Please let me know if something is not clear.
1.) Module
A module is a collection of source files and build settings that allow you to divide your project into discrete units of functionality. Your project can have one or many modules and one module may use another module as a dependency. Each module can be independently built, tested, and debugged.
There are 4 type of module in Android Studio.
Phone & Table Module
Android Wear Module
Android TV Module
Glass Module
2.) Support Library
The Android Support Library offers a number of features that are not built into the framework. These libraries offer backward-compatible versions of new features, provide useful UI elements that are not included in the framework, and provide a range of utilities that apps can draw on.
Support libraries provide a range of different features:
Backward-compatible versions of framework components.
UI elements to implement the recommended Android layout patterns.
Support for different form factors.
Miscellaneous utility functions.
3.) Jar file
JarFile is used to read jar entries and their associated data from jar files.
for more detail visit this : https://developer.android.com/reference/java/util/jar/JarFile.html
4.) Android Library Project
The Android team introduced a new binary distribution format called Android ARchive(AAR). The .aar bundle is the binary distribution of an Android Library Project.
An AAR is similar to a JAR file, but it can contain resources as well as compiled byte-code. This allows that an AAR file is included in the build process of an Android application similar to a JAR file
5.) Gradle and Gradle Project
Gradle is an automated build toolkit that allows the way in which projects are built to be configured and managed through a set of build configuration files. This includes defining how a project is to be built, what dependencies need to be fulfilled for the project to build successfully and what the end result (or results) of the build process should be. The strength of Gradle lies in the flexibility that it provides to the developer. The Gradle system is a self-contained, command-line based environment that can be integrated into other environments through the use of plug-ins. In the case of Android Studio, Gradle integration is provided through the appropriately named Android Studio Plug-in.
for more detail visit this : http://www.techotopia.com/index.php/An_Overview_of_Gradle_in_Android_Studio
I have started working on a project where I will need to share a bunch of Java classes across a bunch of apps. In Eclipse it was possible to create one project with all such classes and use it as a library in a workspace with all your dependent projects, but in Android Studio it doesn't seem possible to do so (At least not easily).
I have been reading a bunch of posts and a lot of them suggest setting up a library project, generating an aar file and then using that in my projects. But, as I understand it, this will make my library open-source (Am I right?), which I don't want. I am doing this for a client and I want the code base to be private.
Also, I know that a module can be imported into a new project. But this creates a COPY of the original module. This is not what I want at all. I don't wanna maintain multiple copies of the same classes, which completely defeats the purpose of 'code sharing'.
Is there any good way of achieving what I am looking for? Any help is appreciated.
You have a couple different options.
One option is to maintain your libraries as separate projects and compile them to an archive format, such as JAR or AAR; JAR files are for pure Java libraries, and AAR is for Android libraries (which contain code that accesses Android APIs and/or has Android resources). As was pointed out in the comments, AAR doesn't force you to publish your code to the world any more than JAR files would; it's just an archive file format whose files can be local to your machine or your organization.
With that archive file in hand, you can include it in other projects. If you're part of a multi-developer organization, you may find it convenient to use a repository manager to publish and maintain those libraries within your organization, and you can use Maven coordinate-style specs to include libraries in your projects, which you don't have to manually copy over to your development machine.
The disadvantage of this approach is that it makes it a little harder to make changes to those libraries: you need to load up the project, make changes, build an archive, and distribute the archive.
The other approach is to keep the library as a source module like you did in Eclipse. You observed that Android Studio will make a copy of the module if you import it via UI, but if you bypass the UI and modify the build scripts directly, you can do what you want, which is to use the module in-place and share a single copy among multiple projects. To do this, work in your settings.gradle file and add this:
include ':module_name'
project(':module_name').projectDir = new File(settingsDir, '../relative/path/to/module')
I would strongly encourage you to not use a pure relative path here; in this example, the path is anchored to the settingsDir variable supplied by Gradle, which is defined to be the directory where settings.gradle is found. If you use a pure relative path (i.e isn't anchored to anything), you're dependent on the working directory being the same in all environments where the build file is run (command line vs. Android Studio vs. CI server), which isn't a good thing to assume.
You need to think in the eclipse projects as Android Studio/IntelliJ Idea modules. Then, you can generate android (or java) libraries and then include them in your project.
To mark an Android Studio module as a library you can go to File -> Project Structure -> Facets and there click on Library Module
I was in same situation as you, and i founded an approach using git.
Steps to do, to have library:
Create project in Android Studio.
Create android library module in that project.
In that library module create git repository.
Add modulename.iml in .gitignore file
Use GitHub or Bitbucket for private cloud repository. and push your library to it.
Create new android library model in any project that you want.
Close Android Studio (not sure is that mandatory).
Using explorer go to your created module folder.
Remove all data in it, except modulename.iml.
Clone your library from "GitHub" into it.
That's all.
Now you are able to use library in multiple project whether you are at home or at work. Just after finishing you work not forget to push library changes. And after opening new one pull them.
I think you can automate this thing somehow.
The benefit is that you don't need to build any jar, or aar.
You can certainly create and use a library without making it open source or available to others.
First, you don't need to make it an aar unless it contains Resources.
If it's just plain classes, you can just make it a .jar file.
Either way, the easiest way to share these libraries (either aar or jar) is to set up your own repository. Nexus and Artifactory are the two most common repository managers.
You keep the library in its own project, and then publish it to your own, in-house repository.
Then, projects that need to use the library are configured (in gradle) to use the in-house repository, and get the library from it.
Google's instructions for using the Play Service API (for example) say:
Copy the /extras/google/google_play_services/libproject/google-play-services_lib library project into the source tree where you maintain your Android app projects.
Note: You should be referencing a copy of the library that you copied to your source tree—you should not reference the library from the Android SDK directory.
This seems ugly to me - why not reference it from the SDK directory? Is there some technical reason for this? Or is it so that you have explicit control over when it gets upgraded?
I'd like to point out that this is entirely a limitation of Eclipse, and it is indeed ugly.
The problem is that this library contains resources in addition to source code. Eclipse can only deal with libraries packaged as jar files, which, for the purposes of Android development, cannot contain resources.
So, in order for the library's resource to be compiled into the application, the library's source code, with the resources, must be added to your project.
If you move your build to Maven, and use an IDE that 'understands' Maven, then you can compile a library that contains resources as an 'apklib', and treat it as an external library, in a manner similar to a jar file.
The new Gradle-based build system is built on Maven primitives, but uses a different format for this, 'aar'. Hopefully, it will eventually also support apklib so that Maven builds and Gradle builds can inter-operate.
I just went through the exercise of converting an Android application to a Maven build, including the use of some apklibs. I can tell you that Eclipse with the m2eclipse plugin does not handle apklibs properly. Both IntelliJ and the new Google Android Studio (based on IntelliJ) do handle apklibs with no issues.
It's not about "Play Services Library" specifically. Just like any other libraries that the project makes use of, this library should be referenced from project's source tree.
In this case the external library is in the Android SDK directory and referencing from there is not a good practice too. So yes, it can be called "a technical reason".
Used libraries (Play Services library in this case) shouldn't be referenced from anywhere other than the project's source tree.
I have maybe this not so common setup:
(> = dependency)
Android project > Android library project 1 > Android library project 2
So I have an Android library project which has a dependency to another library project.
When I'm building project in Eclipse everythings works fine but I cannot get my build working with Ant.
First Ant compiles Android library project 2 which generates a classes.jar and puts this file in the bin folder.
Then Ant tries to compile the Android library project 1 but then I'm getting errors becouse it is missing classes from Android library project 2.
Well this is not so weird becouse the jar file is not included in the libs folders.
But in project.properties i've made a dependency to the library project 2 so why does Ant not copy the classes.jar to the libs folders of library project 1?
Well I can think of a solution to use an Ant task to copy the file to the libs folder, but then I have to modify the build.xml which I do not prefer.
** EDIT
The problem is that the R class is missing, when I look in classes.jar this java file does not contain the R class. So my solution would proberly not work.
This behaviour was caused by a change in R17 of the build tools: http://tools.android.com/recent/dealingwithdependenciesinandroidprojects
In a nutshell: R files for libraries are no longer packaged in the classes.jar for that library. However, since the pareent.R for the parent-library (project1 in your example) also contains the resource-references for the 'child' library (project2 in your example), you don't have to refer to the child-R anyway.
Replace all project2.R-import statements in project1 with project1.R import statements and you should be fine.
For ant to compile add dependency in ant.properties.
eg:
android.library.reference.1=../path/to/library
This sounds like a very brittle setup - you may have good reason for this, but could you instead decouple the libraries dependence on each other?
For example; implement a bridge pattern to translate the calls between both libraries, and make the calling Android project attach them. This way, you have no code in either library that depends on the other, and the only project that needs to handle dependency setup is your main project.
One of the main reasons for using a library is to make the code re-usable, this approach ensures someone (you, a colleague, your successor...) could plug in just one library and create their own implementation of the other one.
Here is another good article on applying the bridge pattern in Java: http://java.dzone.com/articles/design-patterns-bridge
Well the problem was that the R class was missing.
So i removed the R class dependency between the two library projects.
I don't know if this is fixable but i think it is bad practice any way.
Without this dependency Ant builds fine.
Old question, but like me, others might be banging their head on this...
The official answer is "it cannot be done", specifically:
At build time, the libraries are merged with the application one at a time, starting from the lowest priority to the highest. Note that a library cannot itself reference another library and that, at build time, libraries are not merged with each other before being merged with the application.
(extracted from the official documentation: "Referencing a Library Project").
Which means that anything goes, as there is no "clean" way to do it with the tools (and dirty methods are in order).
Hope it helps
I have modularised some simple classes into their own project for reuse elsewhere. These classes typically contain only fields and accessor methods (i.e. nothing Android specific).
They are later packaged up using ant's jar task and stored in a Maven repository.
In an Android project, I've stored said jar file into a libs directory and added to the build path. On running the emulator however, I get a "class not found" exception relating to my package. Other third party libraries (such as GSon) are being picked up fine.
Are there any specific steps required to make a jar file compatible with Android? (This reply seems to suggest otherwise). How can I debug this further?
No as long as you do not need e.g. classes from javax.* that are not in Android. If I were you I would consider looking at using the Android Maven Plugin for your build though. Check out the morseflash example from the official samples collection. It showcases exactly your scenario.
You only need an Android library project if your going to be reusing Android components and resources. In your case, I believe you added the project to the build path, but I'm sure your not exporting it as part of the dependent project.
So open the project properties, open up the Java Build Path options and make sure that you have your JAR selected as an exported dependency in the Order and Export tab.
UPDATE
This is what your entry should read:
<classpathentry exported="true" kind="lib" path="libs/tlvince-dao-0.1.0.jar"/>
I've also forked an updated version of your gist.
This issue was a result of compiling the jar to Java 7. Android does not support Java 7 (yet).
Compiling to Java 6 bytecode by setting target="1.6" in ant's javac task solved the issue.