Intro: I'm trying to load code in run-time from a classes.dex
that's inside a classes.jar. I've done a lot of research and spend a lot of time on this so I really need help.
Problem: When my jar contains a simple class it is loaded successfully. However, in the exact same situation when my jar contains the same class, only now that class implements an interface, loading this class fails with error:
"Didn't find class "com.x.y.z.w.Patch" on path: DexPathList[[zip file "/data/user/0/x.y.z/app_dex/classes_dexed.jar"],nativeLibraryDirectories=[/vendor/lib64, /system/lib64]]"
I also get:
I/dalvikvm: Failed resolving Lcom/x/y/TestClassImpl; interface 4 'Lcom/x/y/TestClassInterface;'
Environment: - Functions used to try loading a class:
(DexClassLoader instance).loadClass & (DexFile instance).loadClass.
Specifically:
Method 1:
DexFile dx = DexFile.loadDex(jarInternalPath, File.createTempFile("opt", "dex",
context.getCacheDir()).getPath(), 0);
Class<?> targetClass = dx.loadClass(className,
ClassLoader.getSystemClassLoader()); // Error
Method 2:
DexClassLoader dexClassLoader = new DexClassLoader(jarInternalPath,
dexOutPath.getAbsolutePath(), null, ClassLoader.getSystemClassLoader());
Class<?> targetClass = dexClassLoader.loadClass(className); // Error
- IDE: Android Studio 2.1.2
- Test devices: Emulator Nexus 4 (with APIs 16, 19 & 23), also Physical Nexus 5 Device with Android 6.0.1
- Most Surprising thing: When I print the classes of the dex file I see the correct class path. I use DexFile to load the dex content and print its classes paths. This method recognizes the correct content! It makes me think there's something to do with either Android permissions or Linux permissions. I don't know..
This is my print method:
try {
DexFile dx = DexFile.loadDex(jarInternalPath, File.createTempFile("opt", "dex",
context.getCacheDir()).getPath(), 0);
// Print all classes in the DexFile
for (Enumeration<String> classNames = dx.entries(); classNames.hasMoreElements();) {
String className = classNames.nextElement();
Log.d(TAG, "Analyzing dex content, fonud class: " + className);
}
} catch (IOException e) {
Log.d(TAG, "Error opening " + jarInternalPath, e);
}
- P.S. Seems irrelevant but maybe it's not: My Host app, the common interface and the implementation of the new content all sit in 3 different modules of the same project. The app has package name of x.y.z, the interface has pkgName of x.y.z.interface and the implementation has pkgName of x.y.z.impl.
A second project I tried with all 3 modules in the same, 1 module failed to work the same way.
Please, help!