is it possible to scan the android classpath for annotations?

后端 未结 1 744
执念已碎
执念已碎 2021-02-06 13:28

I want to scan the classpath for certain annotations in Android.

I have only found one solution to this problem: http://mindtherobot.com/blog/737/android-hacks-scan-andr

相关标签:
1条回答
  • 2021-02-06 13:56

    This works for me using android 3.0

    public static <T extends Annotation> List<Class> getClassesAnnotatedWith(Class<T> theAnnotation){
    
        // In theory, the class loader is not required to be a PathClassLoader
        PathClassLoader classLoader = (PathClassLoader) Thread.currentThread().getContextClassLoader();
        Field field = null;
        ArrayList<Class> candidates = new ArrayList<Class>();
    
        try {
            field = PathClassLoader.class.getDeclaredField("mDexs");
            field.setAccessible(true);
        } catch (Exception e) {
            // nobody promised that this field will always be there
            Log.e(TAG, "Failed to get mDexs field", e);
        }
    
        DexFile[] dexFile = null;
        try {
            dexFile = (DexFile[]) field.get(classLoader);
        } catch (Exception e) {
            Log.e(TAG, "Failed to get DexFile", e);
        }
    
        for (DexFile dex : dexFile) {
          Enumeration<String> entries = dex.entries();
          while (entries.hasMoreElements()) {
            // Each entry is a class name, like "foo.bar.MyClass"
            String entry = entries.nextElement();
    
            // Load the class
            Class<?> entryClass = dex.loadClass(entry, classLoader);
            if (entryClass != null && entryClass.getAnnotation(theAnnotation) != null) {
                Log.d(TAG, "Found: " + entryClass.getName());
                candidates.add(entryClass);
            }
          }
        }
    
        return candidates;
    }    
    

    I also created one to determin if a class was derived from X

    public static List<Class> getClassesSuperclassedOf(Class theClass){
    
        // In theory, the class loader is not required to be a PathClassLoader
        PathClassLoader classLoader = (PathClassLoader) Thread.currentThread().getContextClassLoader();
        Field field = null;
        ArrayList<Class> candidates = new ArrayList<Class>();
    
        try {
            field = PathClassLoader.class.getDeclaredField("mDexs");
            field.setAccessible(true);
        } catch (Exception e) {
            // nobody promised that this field will always be there
            Log.e(TAG, "Failed to get mDexs field", e);
        }
    
        DexFile[] dexFile = null;
        try {
            dexFile = (DexFile[]) field.get(classLoader);
        } catch (Exception e) {
            Log.e(TAG, "Failed to get DexFile", e);
        }
    
        for (DexFile dex : dexFile) {
          Enumeration<String> entries = dex.entries();
          while (entries.hasMoreElements()) {
            // Each entry is a class name, like "foo.bar.MyClass"
            String entry = entries.nextElement();
    
            // Load the class
            Class<?> entryClass = dex.loadClass(entry, classLoader);
            if (entryClass != null && entryClass.getSuperclass() == theClass) {
                Log.d(TAG, "Found: " + entryClass.getName());
                candidates.add(entryClass);
            }
          }
        }
    
        return candidates;
    }
    

    enjoy - B

    0 讨论(0)
提交回复
热议问题