在Android 5.0之前,我能够使用DexClassLoader动态加载DEX文件并调用loadClass()
方法,但使用最新的Android版本,我得到ClassNotFoundException
。
这是我正在做的事情:
生成DEX文件。
../android-sdk/android-sdk-linux_86/build-tools/21.1.1/dx --dex --output=bin/output.dex bin/output.jar
创建一个DexClassLoader。
DexClassLoader cl = new DexClassLoader(
dexFile.getAbsolutePath(),
odexFile.getAbsolutePath(),
null,
mContext.getClassLoader());
致电cl.loadClass("myMethod");
我知道ART使用dex2oat来生成一个由ART加载的ELF文件,但在第2步中我生成了一个ODEX文件,因此我不需要在ART中运行以在运行时加载DEX文件,有谁可以帮助我?
答案 0 :(得分:6)
这适用于Dalvik和ART:new DexClassLoader(jarredDex.getAbsolutePath(), context.getDir("outdex", Context.MODE_PRIVATE).getAbsolutePath(), null, context.getClassLoader());
其中jarredDex
是带有classes.dex
的jar文件。可以通过运行dx --dex --output=filename.jar your/classes/dir
来获取Jar。
我从this article获取了代码示例。但ART使用PathClassLoader
代替Dalvik的DexClassLoader
。此代码在使用Android 6的模拟器和使用Android 5.1的小米上进行测试,并且工作正常:
// Before the secondary dex file can be processed by the DexClassLoader,
// it has to be first copied from asset resource to a storage location.
File dexInternalStoragePath = new File(getDir("dex", Context.MODE_PRIVATE), SECONDARY_DEX_NAME);
try (BufferedInputStream bis = new BufferedInputStream(getAssets().open(SECONDARY_DEX_NAME));
OutputStream dexWriter = new BufferedOutputStream(new FileOutputStream(dexInternalStoragePath))) {
byte[] buf = new byte[BUF_SIZE];
int len;
while((len = bis.read(buf, 0, BUF_SIZE)) > 0) {
dexWriter.write(buf, 0, len);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
try {
PathClassLoader loader = new PathClassLoader(dexInternalStoragePath.getAbsolutePath(), getClassLoader());
Class<?> toasterClass = loader.loadClass("my.package.ToasterImpl");
Toaster toaster = (Toaster) toasterClass.newInstance();
toaster.show(this, "Success!");
} catch (ReflectiveOperationException e) {
throw new RuntimeException(e);
}
答案 1 :(得分:1)
这是制作dex文件的问题。如下更改命令,然后即可在所有版本的android中使用。
dx.bat --dex --output path/output.jar path/input.jar
Windows中的上述方法将生成一个.jar文件,该jar文件中包含classes.dex文件。 DexClassLoader在内部搜索classes.dex文件,这就是为什么它抛出ClassNotFoundException