也许你可以试试这个:
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);
}
这是一个如何使用的例子:
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();