I am trying to implement a package scan function similar to Spring component-scan for the Android platform that I am developing. Basically, I would like to be able to specify the base package, for example. com.foo.bar and get all instances of Class that have a specific annotation. I donβt want to register every component with my infrastructure, as this will defeat the purpose of automatic scanning.
Based on my research, it seems that it is not possible for Java to retrieve resources given the package name using reflection. However, I briefly looked at the structure of Reflections , and I wonder if there is an Android compatible equivalent. If not, there may be a slightly less obvious way to accomplish what I want to do.
I looked a bit at Spring's source to see how they accomplished this, but I don't think they will work in the Dalvik runtime.
Update
Currently, the code below was the best I can do to get all classes containing a specific annotation, but frankly, this is a pretty bad solution. This makes some really unsafe assumptions about ClassLoader plus it scans (and loads) all application classes.
public Set<Class<?>> getClassesWithAnnotation(Class<? extends Annotation> annotation) { Set<Class<?>> classes = new HashSet<Class<?>>(); Field dexField = PathClassLoader.class.getDeclaredField("mDexs"); dexField.setAccessible(true); PathClassLoader classLoader = (PathClassLoader) Thread.currentThread().getContextClassLoader(); DexFile[] dexs = (DexFile[]) dexField.get(classLoader); for (DexFile dex : dexs) { Enumeration<String> entries = dex.entries(); while (entries.hasMoreElements()) { String entry = entries.nextElement(); Class<?> entryClass = dex.loadClass(entry, classLoader); if (entryClass != null && entryClass.isAnnotationPresent(annotation)) { classes.add(entryClass); } } } return classes; }
source share