I am using the following code to instantiate all the classes included in a certain package.
DexFile df = new DexFile(getPackageCodePath());
for (Enumeration<String> iter = df.entries(); iter.hasMoreElements(); ) {
String className = iter.nextElement();
if (className.contains(packageName) && !className.contains("$")) {
myClasses.add(Class.forName(className).newInstance());
}
}
Unfortunately it is not working properly anymore. Since Android Studio 2 and Gradle 2.0.0, the DexFile entries no longer include all the classes within the app but only the classes belonging to the com.android.tools
package.
Is this a known issue?
Looks like this issue is related to the new InstantRun feature in the Android Plugin for Gradle 2.0.0.
getPackageCodePath()
gets a String pointing towards the base.apk file in the Android file system. If we unzip that apk we can find one or several .dex files inside its root folder. The entries obtained from the methoddf.entries()
iterates over the .dex files found in that root folder in order to obtain all of its compiled classes.However, if we are using the new Android Plugin for Gradle, we will only find the .dex related to the android runtime and instant run (packages
com.tools.android.fd.runtime
,com.tools.android.fd.common
andcom.tools.android.tools.ir.api
). Every other class will be compiled in several .dex files, zipped into a file called instant-run.zip and placed into the root folder of the apk.That's why the code posted in the question is not able to list all the classes within the app. Still, this will only affect Debug builds since the Release ones don't feature InstantRun.
for get all dex files of an app use below method.
//------------ other methods
To access all DexFiles you can do this