views:

99

answers:

1

I have a public transport app for one country and I want to create a separate app for another country. Most of the code will be shared, but I need some classes to have different implementations for example TransitProvider.

Is it possible to share code using Android Library Project? Can I do the following?

  1. Have TransitProvider (that extends AbstractTransitProvider) in the library project. The class has methods left unimplemented.
  2. In application project > AndroidManifest.xml I have different package name than in library's manifest. I have also TransitProvider in this project, that is in the same package as the library's TransitProvider.
  3. When I use TP in library project code, the implementation from app. project should be used (ie application project's TP overrides library's TP).
+4  A: 

Is it possible to share code using Android Library Project?

Yes. That is the primary purpose of a library project. If you do not need Android resources, you can also use an ordinary JAR, created in a separate project.

Can I do the following?

You cannot have the same class (in the same package) defined in two places, if I understand your proposed steps properly.

You should:

  1. Define AbstractTransitProvider in the library project or JAR
  2. Optionally have one or more concrete implementations of AbstractTransitProvider, for straight-up reuse, in the library project or JAR
  3. Apps using the library project or JAR can have their own concrete implementations of AbstractTransitProvider, in their own Java packages, in addition to using any concrete implementations supplied by the library project or JAR
CommonsWare
Thanks for answer. Most of the resources will be common for my apps, so I'll be using library project. I need to do something like this from library project's Activity: `Journey result = new TransitProvider().findJourney();` How can I make sure, that the application project's `TransitProvider` implementation is used?
fhucho
@fhucho: "How can I make sure, that the application project's TransitProvider implementation is used?" -- by only having one class named `TransitProvider`. Do not have a class named `TransitProvider` in the library project. Put the common code in `AbstractTransitProvider` in the library project (and/or other utility classes), and the custom implementation in `TransitProvider` in the application project.
CommonsWare
But the library project doesn't seem to know about the TransitProvider that is located in app project. App can use classes from lib but not the other way around I think.
fhucho
@fhucho: "But the library project doesn't seem to know about the TransitProvider that is located in app project." -- it should not need to. The library knows about `AbstractTransitProvider`, and so long as `TransitProvider` extends `AbstractTransitProvider`, that's all that matters.
CommonsWare
I have `new TransitProvider()` in lib > MainActivity. Compiler says "TransitProvider cannot be resolved to a type" and neither app or lib can be built.
fhucho
@fhucho: "I have new TransitProvider() in lib > MainActivity" -- I have no idea what this means. If you are saying that `MainActivity` exists in the *library*, and it is the one trying to call `new TransitProvider()`, that is not going to work. The code that calls `new TransitProvider()` needs to be in the app, not the library. For example, `MainActivity` could be abstract, requiring a `getTransitProvider()` method. The app would extend `MainActivity` supplying that method implementation, and the manifest would point to the app's `MainActivity` subclass.
CommonsWare
Yes, every Activity is in the library. Only about 3 classes are app-specific.
fhucho
The problem is that my code could get quite messy using this approach. So maybe a more suitable solution is to have only one project with a my.package.appspecific subpackage. In this subpackage I would have app-specific classes. Some script would switch between apps by changing content of appspecific subpackage and by changing the package name in manifest.
fhucho
@fhucho: That seems messier to me, but it's your code. Bear in mind that the pattern I described is a fairly common one in Java, particularly Android. You supply concrete implementations of interfaces and abstract classes all of the time (`OnClickListener`, `ServiceConnection`, `Runnable`, etc.) triggered by callbacks you override in an Activity subclass (`onCreate()`, `onListItemClick()`, etc.).
CommonsWare