首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Android中查找包中的所有类

在Android中查找包中的所有类
EN

Stack Overflow用户
提问于 2013-03-16 13:47:42
回答 7查看 20.1K关注 0票数 15

如何在Android上找到一个包中的所有类?我使用PathClassLoader,但是它总是返回一个空的枚举?

更多信息

已尝试建议的反射方法。关于反射库的几个要点。maven central提供的库与Android不兼容,并给出了dex错误。我必须包括源代码和编译dom4j,java-assist。

反射的问题,我最初的解决方案是android中的PathClassLoader返回一个空的package枚举。

方法的问题是Android中的getResource总是返回空枚举。

代码语言:javascript
复制
final String resourceName = aClass.getName().replace(".", "/") + ".class";

for (ClassLoader classLoader : loaders) {
      try {
            final URL url = classLoader.getResource(resourceName);
            if (url != null) {
                final String normalizedUrl = url.toExternalForm().substring(0, url.toExternalForm().lastIndexOf(aClass.getPackage().getName().replace(".", "/")));
                return new URL(normalizedUrl);
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
   }
EN

回答 7

Stack Overflow用户

发布于 2013-04-09 09:56:52

使用DexFile列出apk中的所有类:

代码语言:javascript
复制
    try {
        DexFile df = new DexFile(context.getPackageCodePath());
        for (Enumeration<String> iter = df.entries(); iter.hasMoreElements();) {
            String s = iter.nextElement();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

剩下的就是使用regexp或其他方法来过滤掉您想要的类。

票数 24
EN

Stack Overflow用户

发布于 2015-03-17 18:59:41

实际上我找到了解决方案。感谢你的tao回复。

代码语言:javascript
复制
private String[] getClassesOfPackage(String packageName) {
    ArrayList<String> classes = new ArrayList<String>();
    try {
        String packageCodePath = getPackageCodePath();
        DexFile df = new DexFile(packageCodePath);
        for (Enumeration<String> iter = df.entries(); iter.hasMoreElements(); ) {
            String className = iter.nextElement();
            if (className.contains(packageName)) {
                classes.add(className.substring(className.lastIndexOf(".") + 1, className.length()));
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

    return classes.toArray(new String[classes.size()]);
}

在Android 5.0 Lolipop上测试

票数 16
EN

Stack Overflow用户

发布于 2015-06-27 19:08:44

这是一个解决方案,它不仅为您提供类名,

还包括Class<?>对象。

虽然PathClassLoader.class.getDeclaredField("mDexs")经常失败,

new DexFile(getContext().getPackageCodePath())似乎要稳定得多。

代码语言:javascript
复制
public abstract class ClassScanner {

    private static final String TAG = "ClassScanner"; 
    private Context mContext;

    public ClassScanner(Context context) {
        mContext = context;
    }

    public Context getContext() {
        return mContext;
    }

    void scan() throws IOException, ClassNotFoundException, NoSuchMethodException {
        long timeBegin = System.currentTimeMillis();

        PathClassLoader classLoader = (PathClassLoader) getContext().getClassLoader();
        //PathClassLoader classLoader = (PathClassLoader) Thread.currentThread().getContextClassLoader();//This also works good
        DexFile dexFile = new DexFile(getContext().getPackageCodePath());
        Enumeration<String> classNames = dexFile.entries();
        while (classNames.hasMoreElements()) {
            String className = classNames.nextElement();
            if (isTargetClassName(className)) {
                //Class<?> aClass = Class.forName(className);//java.lang.ExceptionInInitializerError
                //Class<?> aClass = Class.forName(className, false, classLoader);//tested on 魅蓝Note(M463C)_Android4.4.4 and Mi2s_Android5.1.1
                Class<?> aClass = classLoader.loadClass(className);//tested on 魅蓝Note(M463C)_Android4.4.4 and Mi2s_Android5.1.1
                if (isTargetClass(aClass)) {
                    onScanResult(aClass);
                }
            }
        }

        long timeEnd = System.currentTimeMillis();
        long timeElapsed = timeEnd - timeBegin;
        Log.d(TAG, "scan() cost " + timeElapsed + "ms");
    }

    protected abstract boolean isTargetClassName(String className);

    protected abstract boolean isTargetClass(Class clazz);

    protected abstract void onScanResult(Class clazz);
}

下面是一个如何使用的示例:

代码语言:javascript
复制
new ClassScanner(context) {

    @Override
    protected boolean isTargetClassName(String className) {
        return className.startsWith(getContext().getPackageName())//I want classes under my package
                && !className.contains("$");//I don't need none-static inner classes
    }

    @Override
    protected boolean isTargetClass(Class clazz) {
        return AbsFactory.class.isAssignableFrom(clazz)//I want subclasses of AbsFactory
                && !Modifier.isAbstract(clazz.getModifiers());//I don't want abstract classes
    }

    @Override
    protected void onScanResult(Class clazz) {
        Constructor constructor = null;
        try {
            constructor = clazz.getDeclaredConstructor();
            constructor.setAccessible(true);
            constructor.newInstance();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

}.scan();
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15446036

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档