Best practice: Extending or overriding an Android library project class Best practice: Extending or overriding an Android library project class android android

Best practice: Extending or overriding an Android library project class


Library project is referenced as a raw project dependency (source-based mechanism), not as a compiled jar dependency (compiled-code based library mechanism).

@yorkw this is not true for the latest versions of ADT Plugin for Eclipsehttp://developer.android.com/sdk/eclipse-adt.html

From version 17 Change log

New build features Added feature to automatically setup JAR dependencies. Any .jar files in the /libs folder are added to the build configuration (similar to how the Ant build system works). Also, .jar files needed by library projects are also automatically added to projects that depend on those library projects. (more info)

More info http://tools.android.com/recent/dealingwithdependenciesinandroidprojects

Before that, update overwriting of the Activity from Library project was easy, just exclude the class. Now the library is included as jar file, and there is no way to exclude class file from jar dependency.

EDIT:

My solution to overwrete/extend Activity from library jar:

I created a simple util class:

public class ActivityUtil {private static Class getActivityClass(Class clazz) {    // Check for extended activity    String extClassName = clazz.getName() + "Extended";    try {        Class extClass = Class.forName(extClassName);        return extClass;    } catch (ClassNotFoundException e) {        e.printStackTrace();        // Extended class is not found return base        return clazz;    }}public static Intent createIntent(Context context, Class clazz) {    Class activityClass = getActivityClass(clazz);    return new Intent(context, activityClass);}}

In order to overwrite a library's "SampleActivity" class it a the project which depends on that library, create a new class with the name SampleActivityExtended in the project in the same package and add the new activity to your AndroidManifest.xml.

IMPORTANT: all intents referencing overwritten activities should be created through the util class in the following manner:

Intent intent = ActivityUtil.createIntent(MainActivity.this, SampleActivity.class);...startActivity(intent);


behind the scenes, Eclipse creates and references a jar from the referenced library project.

This is not quite accurate. Library project is referenced as a raw project dependency (source-based mechanism), not as a compiled jar dependency (compiled-code based library mechanism). Currently Android SDK does not support exporting a library project to a self-contained JAR file. The library project must always be compiled/built indirectly, by referencing the library in the dependent application and building that application. When build dependent project, the compiled source and raw resources that need to be filtered/merged from Library project are copied and properly included in the final apk file. Note that Android team had started revamping the whole Library Project design (move it from ource-based mechanism to compiled-code based library mechanism) since r14, as mentioned in this earlier blog post.

What are some of the best practices for sharing and extending common classes among Android app targets?

The solution given by Android is Library Project.
The solution given by Java is Inheritance and Polymorphism.
Come together, the best practice IMO is the second option you mentioned in the question:

2.Extend the particular Core class in a target project and override the base (Core) class functions as needed. Then keep a reference to the base-class object in the Core library and instantiate it with an extended class object (from Android library project - How to overwrite a class?)

From my personal experience, I always use Android Library Project (Sometimes with Regular Java Project, for implementing/building common-lib.jar that contains only POJO) manage common code, for instance SuperActivity or SuperService, and extends/implements proper classes/interfaces in the dependent project for Polymorphism.


Solution based on PoisoneR's solution and Turbo's solution.

public static Class<?> getExtendedClass(Context context, String clsName) {    // Check for extended activity    String pkgName = context.getPackageName();    Logger.log("pkgName", pkgName);    String extClassName = pkgName + "." + clsName + "Extended";    Logger.log("extClassName", extClassName);    try {        Class<?> extClass = Class.forName(extClassName);        return extClass;    } catch (ClassNotFoundException e) {        e.printStackTrace();        // Extended class is not found return base        return null;    }}

The benefits of this is that

  1. The extended class can be in the project's package, not the library's package. Thanks to Turbo for this part.

  2. By taking a String as an argument instead of a Class object, this method is able to be used even with ProGuard. getName() is where the problem is with ProGuard, as that will return something like "a" instead of the name of the original class. So in the original solution instead of looking for ClassExtended it will look for aExtended instead, something which does not exist.