Suppose I have my Android app’s source code packaged this way:
src/
my/
app/
Module.java
ModuleManager.java
module/
ModuleA.java
ModuleB.java
where Module is:
public abstract class Module {
public abstract void run();
}
, ModuleA and ModuleB extends Module:
public class ModuleA extends Module {
@Override
public void run() { /* do something */ }
}
and ModuleManager has some helper methods, among which one to retrieve all the Modules:
public class ModuleManager {
private final static List<Module> modules;
static {
List<Module> tmp= new ArrayList<Module>();
tmp.add(new ModuleA());
tmp.add(new ModuleB());
modules= Collections.unmodifiableList(tmp);
}
public static List<Module> getModules(){
return modules;
}
}
As you can see I manually filled the list of modules in ModuleManager. Instead, I would like it to be automatically filled with an instance of all the Module‘s subtypes in the module package.
I tried in several ways reflection-based solutions like this, which involve the use of ClassLoader::getResource(String path) to retrieve every .class file inside the module package, but it always returns an empty enumeration. I learnt this is due to the difference between Dalvik’s VM and Java SE’s one, and its optimized packaging of .class files inside classes.dex. I then tried to import the application’s apk from /data/app/ with DexClassLoader or PathClassLoader and unsuccesfully tried their getResource() method again. Anyway I think this is not the right direction, and probably this stuff was already hackish/flawed in Java, and it would be even more in Android.
Could you suggest me a way to do that?
Thank you very much.
One way to do this in a build script, after compilation but before dex is called to create classes.dex, run a small script to get the class names in modules folder and write it to say an application.properties file to read from (or strings.xml in resources).
The disadvantage of this is it is not a pure java method you were asking for, the advantage being it will work for 2 or 10+ subclasses. Hope this helps.