views:

78

answers:

3

In native development, you can produce libraries - .so, .dll etc - that other libraries and programs can share.

In Java, you can put your code in a JAR in the classpath and other programs and libraries can use it.

So how can you do modular programs in Android? I get the impression from the documentation that each APK is a self-contained island. Can different APKs share code?

And how does installation work when you have these external dependencies? Can you specify that you rely on library that is not in your APK and get it installed too?

If you can't have 'dynamic linking', can you have 'static linking' by developing your shared code and somehow putting the equiv of a JAR into each APK that requires it?

+2  A: 

Regarding static linking, you can share code amongst Android applications using .jar files in the standard Java manner. However you can't currently use the Android resource system (content under the 'res' directory, and the 'R' class) which hamstrings the idea of control libraries somewhat. It also makes using localizable strings impossible, and you can't have Application or Service definitions, or anything else declared in AndroidManifest.xml.

Regarding dynamic linking, there is a kind of library that is distributed in the Market as an .apk itself, and included dynamically at runtime. Many developers are loath to ask their users to install two .apks. This approach does cause user confusion.

Jim Blackler
Can you explain more how the dynamic linking works, or give some keywords that can be googled?
Will
It's a very reasonable question but I'll be honest, I'm having difficulty finding resources on this technique. I know it can be done because it is done with Market libraries such as Text-To-Speech here: http://code.google.com/p/eyes-free/
Jim Blackler
Hmm, so it has a static library stub that likely uses functionality in the main APK via a service the APK exposes. That's the approach I currently use and that's the approach I'm trying to find an alternative to ;)
Will
A: 

You could make a library in a .jar file like Jim Blackler said and than instancing from class using the full name of the class. In java this is really easy and can be used to make you development very flexible.

Here an example:

Class C is contained in a package called com.test.utils so it's full path is: com.test.utils.C. Now if you want to make an instance of C from any other place you use the Class.forName() method wich works like this:

// Try to create an instance of class 'com.test.utils.C'
try {
    Object instance = Class.forName("com.test.utils.C").newInstance();
} catch (IllegalAccessException e) {
    e.printStackTrace();
} catch (InstantiationException e) {
    e.printStackTrace();
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

Take in account that you class needs at least an empty constructor if not you will an exception.

Moss
how do you call the methods and such if you do that?
Will
You can access the class and iterate over it's methods with getMethods(). Here is an example: http://groups.google.com/group/android-developers/browse_thread/thread/7a6bf77910ca31e0
Moss
A: 

Here is a fully working example using Class.forName():

try { 
    for (Method ele: Class.forName("<MyClassPath>").getMethods()) 
    { 
        try { 
            if (ele.getName().equals("<MyMethod>") ) 
                ele.invoke(null, ArgumentList); 
        } catch (IllegalArgumentException e) { 
            e.printStackTrace(); 
        } catch (IllegalAccessException e) { 
            e.printStackTrace(); 
        } catch (InvocationTargetException e) { 
            e.printStackTrace(); 
        } 
    } 
} catch (ClassNotFoundException e) { 
    e.printStackTrace(); 
}

Here you can find more info about the invoke method: http://java.sun.com/j2se/1.4.2/docs/api/java/lang/reflect/Method.html#invoke(java.lang.Object, java.lang.Object[])

Moss
double answers, and using e.printStackTrace() on android - ouch.
Will
I made another answer because there is comment character limit :D Apart it's just sample code...
Moss