If your Android project is compiled and built using Maven or SBT (or maybe something else other than Ant), then you already use the dependency management mechanism, which is provided out of the box. However, if you use Ant, or simply build an application in Eclipse using an ADT plug-in, then you don’t have this functionality, and the lib directory in the project root is filled manually, and there is no desire or opportunity to switch to Maven. Then, is it possible not to store jar files manually, not to keep them binary, in VCS, not to add them to the “Build Path” in the project settings? Of course there are, what questions!
I think that in the world of “big Java” many have heard or even worked with such a tool called
Ivy - “The agile dependency manager”. By the way, if you use SBT, then you automatically use Ivy, just don’t know about it. What can Ivy? Roughly speaking, it is intended for exactly one thing - managing your project’s dependencies on third-party libraries. Ivy is not a build system, it can only complement it.
If the project uses one or two libraries, then perhaps using an instrument such as Ivy will seem an unnecessary “overhead” to you, however, it can make life much easier if your project grows and “grows” with functionality provided by a third party.
')
Training
Our goal will be an application that can be built from both Eclipse and console. To work with Ivy from the console, we will use Ant, which needs to be informed about this - I just put
ivy.jar in
~ / .ant / lib / . We may also need the JSch library (ssh2 implementation) -
jsch.jar , which can also be put in
~ / .ant / lib / . Do not use outdated versions, there were problems with them. There is no need to do anything more at this stage, we proceed to setting up the project.
Customization
The next step we need to configure Ivy to work with the used package repositories. For this there is a so-called.
resolvers - descriptions of repositories that specify their URL, structure, and other characteristics. For our example, I chose 3 used libraries - ZXing, ACRA and RoboGuice. The latter can be found in
mvnrepository.com , the other two use their own Maven-compatible repositories. The file with the Ivy settings is called
ivysettings.xml and is located in the directory with
build.xml - in our case it is the project root. Here are its contents for this example:
<ivysettings> <resolvers> <ibiblio name="maven2" m2compatible="true" /> <url name="acra" m2compatible="true"> <artifact pattern="http://acra.googlecode.com/svn/repository/releases/[organization]/[module]/[revision]/[module]-[revision].jar" /> </url> <url name="zxing" m2compatible="true"> <artifact pattern="http://mvn-adamgent.googlecode.com/svn/maven/release/[organization]/[revision]/[module]-[revision].jar" /> </url> <chain name="chained" returnFirst="true"> <resolver ref="maven2" /> <resolver ref="acra" /> <resolver ref="zxing" /> </chain> </resolvers> <settings defaultResolver="chained" /> </ivysettings>
The ibiblio
resolver is standard from the Ivy package and includes storage located on maven.org and others. Next, configurable storage with ZXing and ACRA. Notice the
pattern attribute, which defines the storage structure. Also, resolvers are combined in a
chained chain, defining the order of enumerating storages when searching for the required package.
So, the storages are configured, then we will describe the dependencies themselves. To do this, create a file
ivy.xml (in the same directory with
ivysettings.xml ). Its contents are:
<ivy-module version="2.0"> <info organisation="com.example" module="ivy-android-example" revision="0.1" /> <dependencies> <dependency org="org.acra" name="acra" rev="4.2.3" /> <dependency org="com.google.inject" name="guice" transitive="false" rev="2.0-no_aop" /> <dependency org="org.roboguice" name="roboguice" rev="1.1.2" transitive="false" /> <dependency org="com.google.zxing.core" name="core" rev="1.6" /> </dependencies> </ivy-module>
The
info section is necessary, and its purpose, I think, is clear from the example. It is followed by a description of the dependencies themselves. More worthwhile stops at
guice and
roboguice . The first library is a dependency for the second, and two of them are enough (according to the documentation of RoboGuice itself), but the
guice will “pull” its dependencies, because both packages are written with the attribute
transitive = “false” , which prevents further dependencies from resolving them. With this configuration, additional packages
-javadoc and
-sources , if
any , will also be provided. In case you do not need them, then you need to add the
configurations section in
ivy.xml and create an empty configuration:
<configurations> <conf name="default" visibility="public" /> </configurations>
and in the description of dependencies add the attribute
conf = "default" .
The final step will be the modification of the
build.xml project (how to generate it - described in the official documentation). However, if you do not plan to use Ant, you can skip this step. First, you need to add a namespace (namespace) Ivy in the project description:
<project xmlns:ivy="antlib:org.apache.ivy.ant" name="IvyAndroidExample" default="help">
And add a new target (target):
<target name="resolve" description="--> retrieve dependencies with ivy"> <ivy:retrieve /> </target>
As a final touch, you can add our goal to the application build process (if you build a project using Ant):
<target name="-pre-build" depends="resolve" />
Now, if in the root of the project run the command
$ ant resolve
then you should see the package download process, and the result should be the
lib directory containing the jar files of the libraries.
Integration with Eclipse
First you need to install the
IveDE plugin for Eclipse. The plugin is available in the Eclipse Marketplace. After installation, the “Resolve All Dependencies” button should appear in the toolbar:

Now, let's add dependencies to the project: open the project properties ->
Java Build Path -> go to the
Libraries tab ->
Add Library -> in the list that appears, select
IvyDE Managed Dependencies -> click Next. Next, we will be asked about the location of the
ivy.xml file and other settings. In this case, you can leave everything as it is and go to the
Settings tab, in which you can specify the path to our
ivysettings.xml file in the
Ivy settings path property . After that you can click Finish. Now, all libraries that have been registered in
ivy.xml as dependencies should be connected to the project, and visible in the Package Explorer:

When you make changes to
ivy.xml, Eclipse will run the Ivy Resolve task. You can also run it using Ant View by adding the
build.xml project to it.
Local storage
It often happens that the required libraries are not in public repositories, or maybe you will use a library written by another team of your project and you need to connect it as a dependency, or something else. Although creating your own Ivy-storage is somewhat beyond the scope of this note, but I decided to include a description of a very basic (but quite working) configuration.
I took the
Droid @ Screen library as an experimental instance, and the storage will be located in
/ var / ivy . Now, you should choose the structure of the location of the artifacts - and in this case it will be
/ organization / name / version / artifact . For our test library,
com.ribomation is used as the organization in the package names, then the storage structure will look like this:
/ var / ivy
Com── com
Ri── ribomation
D── droidAtScreen
0.5── 0.5.1
D── droidAtScreen.jar
I── ivy.xml
Pay attention to the
ivy.xml file - it contains a description of the artifact, its dependencies, configurations and other things. Its minimum content is:
<ivy-module version="2.0"> <info organisation="com.ribomation" module="droidAtScreen" revision="0.5.1" /> <publications> <artifact /> </publications> </ivy-module>
Next, you need to connect our local repository to
ivysettings.xml (dots already marked tags, your KO are marked):
<ivysettings> <property name="repo.dir" value="/var/ivy"/> <resolvers> <...> <filesystem name="local" m2compatible="true"> <ivy pattern="${repo.dir}/[organization]/[module]/[revision]/[artifact].[ext]" /> <artifact pattern="${repo.dir}/[organization]/[module]/[revision]/[module].jar" /> </filesystem> <chain name="chained" returnFirst="true"> <...> <resolver ref="local" /> </chain> </resolvers> <...> </ivysettings>
Pay attention to the
m2compatible attribute - its use will lead to the fact that Ivy will replace the points with system separators in the organization name, respectively, and the search for artifacts will be conducted not in the
com.ribomation directory, but in their hierarchy -
com / ribomation . Now, add the dependency to
ivy.xml :
<dependency org="com.ribomation" name="droidAtScreen" rev="0.5.1" />
Actually, this is all - you can run the problem
resolve .
If you are interested in having a remote repository accessed via SSH, then you need to use
ssh for the resolver, not the
filesystem , but:
<ssh name="shared" host="example.com" user="${user.name}" keyFile="${user.home}/.ssh/key"> <...> </ssh>
Otherwise, they are identical.
Remarks
During the work with Ivy and Eclipse, the following error was noticed - if your project is divided into several (main, tests, etc.), then when opening them, the Ivy plug-in for some reason confuses dependencies between projects. The solution is very simple - just click the “Resolve All Dependencies” button on the toolbar.
Instead of conclusion
So, the purpose of this note was to show how you can, without changing the existing structure (and infrastructure) of the project, add to it a mechanism for resolving dependencies and get rid of the manual labor of maintaining and adding them to the project. The source code of the project is
here . I hope that the information will be useful to you.