I am trying to learn dynamically loading classes (.dex/.jar) in Android. I assembled the basic ideas from tutorials and Stack Overflow questions (tutorial, this, and this), but I am failing to fulfill my purpose of dynamically loading class files and constantly giving the ClassNotFound
exception.
My steps in brief:
Created a Java file as given in the article.
public class DynamicClass { public static void main(String[] args){ print(); } public static void print() { System.out.println("Hello Dynamic"); } }
Converted java source to .class (result = DynamicClass.class)
javac DynamicClass.java
Created jar file using
dx
tool from Android SDK. (result = dynamic.jar with classes.dex in it)dx --dex --output=dynamic.jar DynamicClass.class
Once I got the .jar file, I pushed it to /sdcard/ (tested on both, emulator as well as device)
Emulator : Android 6.0 and Device : Android 11.0
Brief code for loading the class:
try { String dexPath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "dynamic.jar"; Log.d("DYNAMIC_TEST","dexPath: "+dexPath); final File tmpDir = getDir("dex", 0); // temporary file creation for .exists() check File dexFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "dynamic.jar"); if (dexFile.exists()){ // dexFile location is same as dexPath location Log.d("DYNAMIC_TEST", "File Found"); DexClassLoader dexClassLoader = new DexClassLoader(dexPath, tmpDir.getAbsolutePath(), null, this.getClass().getClassLoader()); Class dynamicClass = dexClassLoader.loadClass("DynamicClass"); Method printMethod = dynamicClass.getMethod("print"); printMethod.invoke(dynamicClass.newInstance()); Log.d("DYNAMIC_TEST","Success"); } else { Log.d("DYNAMIC_TEST", "File NOT Found"); } }catch (Exception e){ Log.d("DYNAMIC_TEST", "Exception: "+ e.toString()); }
I am constantly getting the ClassNotFound
Exception.
What am I missing? Why is it that am not able to load this simple class file :(?
My checklist:
- Made sure that code is able to get the loaded file (<File>.exists()). Code is able to get the file. Only not able to load the class.
- Made sure dynamic.jar contains a classes.dex entry inside it. (This is because DexClassLoader wants a .jar/.apk file with the classes.dex entry in it)
- Tried running code on emulator as well as device (both having different Android versions).
Exception description:
Exception: java.lang.ClassNotFoundException: Didn't find class "DynamicClass" on path: DexPathList[[zip file "/storage/emulated/0/dynamic.jar"],nativeLibraryDirectories=[/system/lib64, /vendor/lib64]]
Exception after including package.
Exception: java.lang.ClassNotFoundException: Didn't find class "mypack.DynamicClass" on path: DexPathList[[zip file "/storage/emulated/0/mypack.jar"],nativeLibraryDirectories=[/system/lib64, /vendor/lib64]]
package
directive). – Heiducpackage mypack;
. Inside DexClassLoader changed the call tomypack.DynamicClass
instead of justDynamicClass
but still the exception stays. – Bibliothecapackage mypack;
in java file and then compiled. – BibliothecaClassNotFound
exception at the end. :'( – Bibliothecaassets
directory and hence using PathClassLoader. In my use-case, I want to load app from sdcard and hence am using DexClassLoader. And therefore, I went with your answer'sUpdate
section code. – Bibliotheca