Home > Android > Android Application, Android Libraries and Jar Libraries

Android Application, Android Libraries and Jar Libraries

THIS POST IS OUTDATED AS OF SDK r14

 

Sooner or later each successful platform provides tools for writing reusable components. For quite some time Android SDK supported only Jar Libraries. But there were no support for libraries that could contain both code and android resources.

In later releases Android SDK introduced support for Android Libraries, which could contain reusable android resources. But these Android Libraries had several very important limitations.

The first limitation was that Android Library couldn’t reference another Android Library. This was fixed in recent Android SDK updates. So now developers may create no-cyclic graph dependencies between their Android Components.

Another problem with Android Libraries, is that developer has to merge AndroidManifest.xml of Android Library files into application’s AndroidManifest.xml by herself (including activities, services, broadcast receivers, permissions, etc.) This is tedious task, especially if there are many Android Libraries in use. Though automatic merge is currently being developed and may be released in next releases of SDK.

Yet another issue with Android Libraries is that they can’t contain xml files (mostly layouts in this case) which use custom xml attributes (see bug 9656, I’ll write a separate post about this issue).

 

Android Library vs. Jar Library

The major logical difference between Android Library and Jar Library, is that Android Library contains both code and resource, while Jar Library contains only code. This should be an indicator which kind of library when to use.

image

Android Library vs. Android Application

Android Library is essentially the same as Android Application: they use same directory tree for resources and code. The only difference between them on physical level is that Android Library has android.library set to true in default.properties file (located in the root of project). If you set android.library to false or remove this property altogether you’ll convert Android Library into Android Application project.

image

Complex Dependencies

In latest Android SDK you can create as many Android Library dependencies as you want. You can have library A that depends on library B, which in turn uses library C. You just need to avoid circular dependencies.

image

Android Application and libraries

When you compile your Android Application build system goes through several steps (you can see a detailed description here):

  1. Generate R.java file
  2. Compile .java files into .class files
  3. All .class files and converted into dalvik bytecode (all .class files –> one .dex file).
  4. This .dex file is added into android .apk

image

 

This is important moment: all .class files are converted into dalvik bytecode format at compile time. This means that build system needs all .class files before it can start conversion.

Android Application and Jar Libraries

Jar Libraries are “imported” into .apk at build time. When android build system converts all .class files into .dex, the convertor (dx.jar) tool extracts all .class from referenced jar libraries and treats them as if they were locally compiled .class files.

      Note that

jar

      files are physically merged into

.apk

    file. There is no need to look for and load them in runtime, as your normal Java environment would do.

image

Android Application and Android Libraries

Note: I’m going to describe this one in greater details. So bear with me.

Let’s see how .apk is created when Android Application uses only one Android Library which has no other dependencies (i.e. does not reference other Android Libraries).

Single Android Library dependency

Let’s assume I have Android Application called “app” and Android Library called “lib-a”.

Here are steps build system goes through:

Note: Not all build steps are reflected in this description.

Note: This may become outdated as Android SDK evolves. Current Android SDK Level is 11.

1. Calculate “app” dependencies (in our case it will be “lib-a”)

2. Generate R.java classes:

Here is how build system handles this:

aapt package –f –m –auto-add-overlay

–M /absolute/path/to/app/AndroidManifest.xml

–S /absolute/path/to/app/res

-S /absolute/path/to/lib-a/res

-I /absolute/path/to/android.jar

-J /absolute/path/to/app/gen

 

Note that lib-a’s AndroidManifest.xml file is ignored!

Also note the –S parameter. This parameter is used to merge resources from several res folders. If app had string resource hello and lib-a had string resource hello, then the one from app would win, and the one from lib-a would be ignored. This happens because app’s res folder comes first in the command line.

Here is a description of –S parameter from aapt tool:

-S  directory in which to find resources.  Multiple directories will be scanned
and the first match found (left to right) will take precedence.

 

3. Compile .java files into .class files.

Note that on this step .java classes from app and from lib-a are treated as if they were from app. They are gathered together and compiled using one call to java compiler. There is no sign that we are using separate library at this step. Build system takes care about detecting all required .java source file paths.

Here is how build system handles this:

javac <other options> –sourcepath

/absolute/path/to/app/src;/absolute/path/to/app/gen/;absolute/path/to/lib-a/src

 

Also note, that if you have built Android Library before building Android Application, all .class files that were created during compilation of Android Library are simply ignored. This also means that if you have X different Android Applications reference one Android Library, this Android Library will be built X times.

4. Convert all .class files into dalvik format and create .dex file

5. Package resources

This step is identical to step #2, except instead of generating R.java classes, this will produce special file with all merged resources in it.

6. Combine packaged resources and .dex file and save them into .apk file

image

Multiple Android Library dependencies

Let’s look at another example of Android Libraries: we have application called app, also we have lib-a, lib-b, lib-c, lib-x. Here is how they depend on each other:

image

You can download the source code for this app and libraries here and check default.property files yourself. Note the order values: uses(1), uses(2). This means that `app` references `lib-a` first, and  then references `lib-x`.

1. Calculate dependencies and their order.

Here is the order that build system determined for Android Libraries.

    [setup] ——————
[setup] Ordered libraries:
[setup] …\android-libs\lib-a
[setup] …\android-libs\lib-b
[setup] …\android-libs\lib-c
[setup] …\android-libs\lib-x
[setup] ——————

This order is important. It’s used when detecting which resources win if duplicates are found.

2. Generate R.java classes:

aapt package –f –m –auto-add-overlay

–M /absolute/path/to/app/AndroidManifest.xml

–S /absolute/path/to/app/res

-S /absolute/path/to/lib-a/res

-S /absolute/path/to/lib-b/res

-S /absolute/path/to/lib-c/res

-S /absolute/path/to/lib-x/res

-I /absolute/path/to/android.jar

-J /absolute/path/to/app/gen

 

Note how order printed by build system is reflected in this command line.

3. Compile .java files into .class files.

javac <other options> –sourcepath

/absolute/path/to/app/src;/absolute/path/to/app/gen/;absolute/path/to/lib-a/src;absolute/path/to/lib-b/src;absolute/path/to/lib-c/src;absolute/path/to/lib-c/src

 

Note how order printed by build system is reflected in this command line.

4. Convert all .class files into dalvik format and create .dex file

5. Package resources from each each library and application into one file.

6. Combine packaged resources and .dex file and save them into .apk file

 

Summary on Android Libraries

Several important points you should take from this post:

  1. Source code and resources of all referenced Android Libraries are treated as if they were part of Android Application.
  2. Libraries’ AndroidManifest.xml files are ignored. Though this may change in future releases of Android SDK when manifest merging is added.
  3. Order of libraries determines who wins when identical resource names/ids are found across different libraries.
  1. xav
    June 11, 2011 at 02:17 | #1

    Good article!
    One correction, jar files are not unzipped in bin/classes. Instead the dx tools is able to take both folders of .class files and jar files as input.

    • June 14, 2011 at 21:49 | #2

      Of cause, you’re right. Jar libraries are not extracted to bin/classes. And I’m not sure why I concluded otherwise at the moment of writing the article. My guess is that I’ve tested jars with android libraries and old build system – when android libraries where compiled separately to their own folders. I suspect that .jar files referenced by android libraries were actually unzipped to bin/classes of that android library folder. But that are just my guesses and justifications :)

      I’ve corrected the article to reflect the correct order of things. Thanks Xavier!

  2. June 20, 2011 at 06:32 | #3

    Thanks for this informative article. There’re still some things I don’t quite understand though. I have the following scenario:
    – I want to create an APK library (let’s call it myLib) that exposes some APIs/services.
    – The library, once installed on the phone, can be called from other Android apps (which may be developed by other people).

    What’s not clear to me is, if a developer wants to create his own Android app that calls myLib:
    – How do I supply the APIs of myLib to the developer? Is it enough to give him myLib.apk (and obviously some documentation on the APIs)? Or, do I give him some myLib.jar?
    – How can he build/compile his app against myLib?
    – Once he’s built his app that calls myLib, does he need to install myLib.apk on his phone? Or does he only need to install his app?

    Obviously, I don’t want to give the developer my source code.

    • June 20, 2011 at 08:32 | #4

      This answer on stackoverflow may help you a bit: http://stackoverflow.com/questions/6269816/creating-closed-source-android-libraries

      Android build system currently supports jars and static open-sourced libraries (open-sourced meaning source code can be read by user of library, not open-source license). In other words library’s apk is never really installed on device, its not even created during the build. Android Library is directly compiled into application’s apk!

      So, in general, the scenario you described is not directly supported by Android. As far as I know, there is no way to load another (libary) apk’s code into your process. The only possible solution is to sign (library) apk with the same key as application apk and then use “android:process” attribute. And this is not a solution to your issue.

      So you’re stuck with static open-sourced libraries for now (described in this post). You probably can introduce static close-sourced libraries, but that would be a pain plus you’ll need to distribute those library apk to developers (not to devices through Android Market).

      I’ll do some more research on your and similar scenarios. I’ve seen this question brought up several times now. Probably will do another post if I get some interesting results.

  3. June 20, 2011 at 19:03 | #5

    Thanks for an excellent and very useful article. Regarding Android Libraries, it may be helpful to add that while an Application project can certainly reference drawable, icon and layout resources in an Android Library, it cannot reference assets (yet).

    • June 20, 2011 at 19:50 | #6

      I’ve never really used assets with libraries :) That’s probably why I forgot to mention them here. So thanks :)

      But this is actually an interesting issue. I don’t see anything conceptual that prevents android libraries from using assets. It looks like aapt tool just does not support multiple asset folders. It shouldn’t be too hard to enable this support, but there are some question arise. Like how exactly asset folder should be merged, what should be done when two android libraries have overlapping asset files and so on.

    • June 27, 2011 at 00:45 | #7

      Hi again, I’ve added new post with patches for enabling assets in android libraries. Just in case you might be interested: http://devmaze.wordpress.com/2011/06/26/enabling-assets-in-android-libraries/

  4. June 21, 2011 at 18:57 | #8

    Another thing that I stumbled upon is that you cannot define a style in library project and then use it in the referencing application. So the style needs to be copied over to the application project. This is probably something similar to the AndroidManifest thing.

  5. June 21, 2011 at 22:04 | #9

    Very Good Article..Thanks

  6. July 27, 2011 at 15:15 | #10

    Wait, so does that mean that if I use a library that has a string called “name”, I can’t use this name in my project without overriding it? Or is the package name taken into account somehow? Because that would really suck.

    • July 27, 2011 at 15:20 | #11

      Yes, that how it works now. And you’re right, it might result in some weird resources substitution. That’s why libraries should be very careful about resource naming, and at least use some kind of prefix for resource names.

  7. August 10, 2011 at 08:25 | #12

    Excellent article.

    Another point to mention is using libraries has several side effects:

    a) compilation time is much longer than using jar
    b) the version control in repositories should be much more strict, as modifying source code of a library will imply modifying it for all projects using this library, while jar architecture is usually based on “generated-versions”

    regs

    • August 10, 2011 at 08:44 | #13

      Yes, a) is almost always true, especially for larger projects. But normally if you do not use libraries, each time something is modified the whole project is rebuilt, as opposed to code of one library. So from my experience, libraries are still relatively more usable the monolith project.

      By the way, if autobuild takes too much time, there is a new interesting option in ADT12: http://tools.android.com/recent/finercontroloveradtbuildprocess that can really help sometimes.

  8. October 4, 2011 at 16:19 | #14

    Thanks for the article! I am new to Android and was disappointed that articles about how to create Android Libraries were really sparse in android.google.com. This article helps me understand better!

  9. Roney
    January 6, 2012 at 02:01 | #15

    Excellent article. I was looking for exactly same solution. But my scenario is quite different. I have a library project libprj and have an application, lets say appprj. I understand if I use eclipse, I have to set the dependency inside project properties. But the scenario here is I want to build appprj as a part of custom ROM. Could you please help me with that. How can I specify this dependency in make file? Any help would be greatly appreciated.

  10. Rhobison
    March 21, 2012 at 14:02 | #17

    Excellent article! I have a different scenario and I can’t see a solution! I have 2 libs: lib-a (Android lib with specific Android code) and lib-b (standard java lib with common java code) and an application app (android application). Lib-a depends on lib-b. App depends on lib-a and lib-b. Now comes my problems! In app project properties, in section “Android” I have included lib-a as a dependency. In section “Java build path->projects” I have lib-b as a dependency. When I try to compile app, I get the error “java.lang.IllegalArgumentException: already added: ” and “Conversion to Dalvik format failed with error 1″, because lib-a already included classes from lib-b. If I remove lib-b from section “Java build path->projects” in the app, I can compile, but can’t debug classes in lib-b (error: “Source not found” in debugger).
    Can you help me? How I could workaround this?
    Thank you!

    • Rhobison
      April 4, 2012 at 12:26 | #18

      Problem solved by SDK v17 + ADT v17.

  11. March 22, 2012 at 15:08 | #19

    Brilliant article. One question: I have made a library project which references a JAR file. If I now want to use this library project in one of my applications, I can’t seem to see the classes in the JAR file that the library project is dependant upon? I don’t know if it makes any difference but the JAR file contains a load of JNI classes which allow me to use some native C classes which are also embedded in the library project (obviously these are to be shared as well).

    Any thoughts? From your diagrams it seems that my project should be able to see all of the classes in my library project as well as all of the classes in any of it’s dependencies? Am I correct?

    Thanks,
    Dean

  12. March 22, 2012 at 15:23 | #20

    I notice it has been recorded here too : http://code.google.com/p/android/issues/detail?id=25184#makechanges

    Looks like I am not alone

  13. srinath
    April 18, 2012 at 09:28 | #21

    Brilliant article, but mine is a different scenario.
    I have an android library lib-a which depends on another android library lib-b, am using eclipse and if i refer lib-b in lib-a, it is unable to add lib-b resources in lib-a.

    Any help would be greatly appreciated.
    thanks in advance.

    • April 18, 2012 at 10:05 | #22

      It actually should work just fine. Can you reproduce this on an example project and post it somewhere?

      • srinath
        April 18, 2012 at 13:32 | #23

        Yes, its working fine now.
        Thanks.

  14. October 1, 2013 at 16:25 | #24

    Pl. correct –auto-add-overlay to –auto-add-overlay double -.

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 34 other followers