satya - Thursday, June 24, 2010 11:06:28 PM

Understand library projects

Understand library projects

satya - Friday, June 25, 2010 12:59:53 PM

Library project predicates

Eclipse ADT will merge the library project into the main referenced project

You can have duplicate resource ids between main project and a library project

Resource ids from the main project will take precedence

To distinguish resource ids you can use different resource prefixes

A main project can reference any number of library projects

You can set precedence for the library projects

A library project will not be compiled into its own apk file

A library project can use other jar files

A library project cannot be made into a jar file

The components of a library needs to be defined in the target manifest file

it is not necessary to define the components in a library manifest file

A library project can have its own package name

You set the library project once you create a standard android project and then invoke its properties

You can set the dependent library projects for a main project through "project properties" screen as well

Clearly being a library project many main projects can include that library project

Libray feature is available in ADT 0.9.7, SDK tools r6 or higher, android 2.1 or up

one library project cannot reference another

Library project cannot support AIDL files

Importantly a library project does not support sharable assets directory

satya - Friday, June 25, 2010 1:09:36 PM

And....

A library project's manifest file must declare all of the shared components that it includes, just as would a standard Android application.

satya - Friday, June 25, 2010 2:01:55 PM

Android Libraries

Android Libraries

Search Google for: Android Libraries

Search Android Developers Group for: Android Libraries

Search Android Beginers Group for: Android Libraries

Search Google Code for: Android Libraries

Search Android Issues Database for: Android Libraries

satya - Friday, June 25, 2010 3:19:20 PM

Oh, C*ap, surprises surprises

Library has its own R.java files

Main app has its own R.java file

However the constants are replicated in the main apps' R.java file so that you dont have to refer to the library-r.java with its classpath.

It will get really messed up if you were to name a menu resource file the same in both library project and the main app project

Bottom line: java classes retain their class structure, but resources are merged and you can refer to the library resources in your main app directly through the main apps r.java

satya - Friday, June 25, 2010 3:57:20 PM

Setting a project as a library project

You will first create the project as a regular android project and then you go to the project properties and turn on the "Is Library" flag.

satya - Friday, June 25, 2010 4:00:11 PM

Here is how you add this library to an app

Notice tha "Add.." button. You can use this to add the library above as a reference. You don't need to do anything else.

once this step is done, the library project usually shows up as an additional (in addition to being a library project by itself) node under the main app project. The figure below illustrates this.

satya - Friday, June 25, 2010 4:02:28 PM

Absorbed source tree of the library project

Notice the node that said [Android Library] and also the replicated/referenced java source files. If you were to change these files you are actually changing them i n the library project as well.

Sometimes you don't see this sub node. You may want to restart eclipse in such a case. Eitherway if it works you should see this.

satya - Friday, June 25, 2010 4:06:02 PM

Duplicated R.java files

Another interesting thing is that you will see two R.java files, one for the main app and one for the library.

As you will see in the following diagram the resources from the library r.java file are also available as constants in the main apps r.java file. This is convenience as you don't need to reference the constants using two R.java constants.

The following diagram shows the main app's R.java file. Notice the constants that start with "lib_" showing up in the main apps r.java

satya - Friday, June 25, 2010 4:09:33 PM

Main apps R.java

Notice the constants under "menu", main_menu and lib_main_menu. When I named them the same it played havoc. so be careful with naming.

Moreover notice that the menu ids under "id" uses the menu strings both from "main_menu" and also the "lib_main_menu" as an aggregated set.

I have also noticed that they tend to have the same constant value.

This goes to show that the merging is a compile time process.

Also as mentioned, the main app's R.java absorbs all of the constants from the library R.java. It is a real convenience.

satya - Friday, June 25, 2010 4:12:43 PM

Alright here is the manifest.xml from the library


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.ai.android.library.testlibrary"
      android:versionCode="1"
      android:versionName="1.0.0">
    <uses-sdk android:minSdkVersion="3" />
    <application android:icon="@drawable/icon" 
         android:label="Test Library Project">

        <activity android:name=".HelloWorldLibActivity"
                  android:label="Test Library Helloworld Activity">
        </activity>

    </application>        
</manifest>

Notice how a library java package can have its own name. The activity definition in this library manifest file is optional. Only thing that is used from this manifest file is the package name as of current releases of android.

satya - Friday, June 25, 2010 4:15:17 PM

Here is the manifest file from the main app


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.ai.android.library.testlibraryapp"
      android:versionCode="1"
      android:versionName="1.0.0">
    <application android:icon="@drawable/icon" android:label="Test Library App">
        <activity android:name=".HelloWorld"
                  android:label="Test Library App">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity android:name="com.ai.android.library.testlibrary.HelloWorldLibActivity"
                  android:label="Test Library Activity"/>

</application>
    <uses-sdk android:minSdkVersion="3" />
</manifest>

See how you have to define the activity borrowed from the library project here in the main app manifest file. Also notice how it has to be a fully qualified java class name with out a "." notation.

satya - Friday, June 25, 2010 4:18:21 PM

Here is how you invoke the activity from the library in the main app


import com.ai.android.library.testlibrary.*;
....
....
private void invokeLibActivity(int mid)
{
;
  Intent intent = new Intent(this,HelloWorldLibActivity.class);

  intent.putExtra("com.ai.menuid", mid);
  startActivity(intent);
}

Notice how you refer to the activity just like a local class name, but qualified directly or through an import statement (refering to the package name of the library).

satya - Saturday, June 26, 2010 4:04:55 PM

Here is the zip file with two projects

Download the zip file

One project is a library project and the other a main application project using the library as a dependency.

satya - Monday, November 14, 2011 2:05:28 PM

The URL for library project information has changed

The URL for library project information has changed

satya - Monday, November 14, 2011 2:17:52 PM

android library changes in ICS

android library changes in ICS

Search for: android library changes in ICS

satya - Monday, November 14, 2011 2:18:36 PM

android blog on library changes in ics

android blog on library changes in ics

satya - Monday, November 14, 2011 2:33:07 PM

differences in the generation of R.java files for library projects

differences in the generation of R.java files for library projects

satya - Tuesday, November 15, 2011 9:11:02 AM

library r.java

library r.java

Search Google for: library r.java

Search Android Developers Group for: library r.java

Search Android Beginers Group for: library r.java

Search Google Code for: library r.java

Search Android Issues Database for: library r.java

satya - Tuesday, November 15, 2011 9:13:14 AM

Here is a thread with some issues in library generation

Here is a thread with some issues in library generation

satya - Tuesday, November 15, 2011 9:27:43 AM

warning: R.java manually generated. Reverting to generated version

This seem to come if I clean and rebuild the library project and the application project at the same time. It seem to go away if I build the application again.

library code continues to be fragile

satya - Tuesday, November 15, 2011 11:30:04 AM

Summary of what has changed

Previously the source from the libraries is absorbed (or included) in the target application and the entire thing recompiled. This was the reason why previously you would have seen library sources as part of your application source under the src directory.

In the new scheme the libraries are precompiled and included in the target application as jar files.

This compilation assimiliation of libraries poses a challenge. Previously the R.java is regenerated when things get compiled in the target. However these values get frozen if the libraries are included as compiled jar files. so what you will ask? if two libraries are included then it is possilbe that their generated R.java constatns will collide.

To compensate for the compiled R.java constants, the new scheme makes the R.java constants non-final in the library compile. However the main application compilation regenerates another R.java for that library and the constants this time are final.

Let's talk about the switch statements as applicable to R.java constants. Because a switch statement requires a pure constant (final) much like a "c" based "#define" the code in the library will not be able to use R.java constants in a switch statement. You have to use "if" and "else". You don't need to particularly remember this fact, because compiler will complain anyway and you will quickly see what happened.

The interesting thing though is, same constants are final in the application where you can use the switch statements. Talk about confusion.

The code that was compiled in the library portion obviously uses the R.java constant that is "library.R.id.some_id". However in the app you will use "your-app.R.id.some_id". Somehow, somewhere they must be pointing to the same "number"?? Not sure yet how this happens?

satya - Tuesday, November 15, 2011 11:51:18 AM

Although the libraries are included as jar files...

You still need the whole library project to be available at compile time of the main app. Although libaries are included in the main app compilation unit as a jar file, the jar file right now contains only the java classes.

The resources are still in the dependent library project. They are not carried over to the application project. They physically reside with the library projects until at run time they become part of the apk file.

So the java classes that are compiled with references to R.java in the library must be somehow get resolved when compiled into the new "app" world and its constants. This is why a new R.java needs to be compiled which has the same constants as the old R.java where the libraries came from. This is why you have an R.java replicated for the library.

In fact the R.java in the application context "app.R.id..." seem to be just copied over as is (with all the app constants and the library constatns) over and over for each library and the main library.

Bottom line

Same R.java for the app and each library
  in the application project.
Resources stay put during compiles
Java classes from the libray becomes .class files
  in the app. Saves compile time.

satya - Tuesday, November 15, 2011 11:56:33 AM

Soooo why non-final R.java in libraries...

now it becomes clear why the R.java constants are non-final. Remember we are includign the compiled .class files in the application target project. which means these files are already compiled.

if the R.java were final in libraries then those numbers such as 0x719992 become part of the compilation unit.

This must be stopped so that the same "java" class files can refer to a "final" version of constants for the R.java of libraries.

This also answers the question if there is a process that overwrites R.java class variables from the library. The answer is no. No one needs to overwrite them because a new compilation unit of R.java (R.class) gets included only in the app project. So the R.class of library is discarded when compiled in.

satya - Tuesday, November 15, 2011 1:07:57 PM

Here are some pictures of library and app projects in ICS

Here are some pictures of library and app projects in ICS

satya - Tuesday, November 15, 2011 1:09:42 PM

Here is how a libary is exposed as a java class jar in the app project

In previous SDKs the source was copied and recompiled instead. Now no recompilation of library projects saving time.

satya - Tuesday, November 15, 2011 1:12:43 PM

The R.java continues to be duplicated

See the placement of R.java for the java package of the library. Let us see now the contents of the R.java in the library vs the same file in the app context

satya - Tuesday, November 15, 2011 1:14:28 PM

The non-final R.java in the library

Notice that the constants are not final. This will allow the compiled java classes in the library to not hard code these constants and expect a separate class file for R.java to be used

satya - Tuesday, November 15, 2011 1:15:55 PM

Lets see the same constants redefined in the app under this java package name of library

Notice how this file has all the constants of the library but also all the constants of the main app as well. It is not clear why the later is important

satya - Tuesday, November 15, 2011 1:17:43 PM

Here is the main apps R.java file which is idential to the library version except for the package name

Notice that, other than the package name at the top the previous two images, one belonging to the app, and one belonging to the library, the R.java files are identical.