好记性不如铅笔头

android, 操作系统

【转】利用DexClassLoader动态加载dex文件

本文转自【 利用DexClassLoader动态加载dex文件 – 浩荡乾坤 – 博客园 (cnblogs.com) 】,有删改。原文时间较久远,仅供参考。

Java中也有类加载器ClassLoader,其作用是动态装载Class文件,当我们从网络下载Class文件,或者在编译时不参与而在运行时动态调用时就需要用类加载器。由于Android对class文件进行了重新打包和优化,最终APK文件中包含的是dex文件,加载这种文件就需要用到DexClassLoader。

DexClassLoader(dexPath, optimizedDirectory, libraryPath, parent)

dexPath:目标类所在的APK或者jar包,/…/xxx.jar
optimizedDirectory:缓存存放路径
libraryPath:native库路径,可以为null
parent:父类装载器,一般为当前类的装载器

使用示例

定义一个插件类Plugin用于在运行时由宿主程序调用

public class Plugin {
	public int add(int a, int b) {
		return a+b;
	}
}

使用jar命令将其打包成jar文件

jar -cvf plugin.jar com/dl/plugin/Plugin.class

使用dx命令将其转化为android中的类格式dex文件

dx --dex --output=f:\dynamic.jar f:\Plugin.jar

将其放到手机目录中,比如放到根目录

adb push F:\dynamic.jar /

在宿主程序中动态加载调用插件类Plugin,然后通过反射调用add方法,参考代码如下:

DexClassLoader loader = new DexClassLoader("/dynamic.jar", getApplicationInfo().dataDir, null, this.getClass().getClassLoader());
clazz = loader.loadClass("com.dl.plugin.Plugin");
Method add = clazz.getMethod("add", Integer.TYPE,Integer.TYPE);
int result = (Integer) add.invoke(clazz.newInstance(), 1,1);

上面使用反射进行函数调用有些复杂,可以使用接口进行更方便的调用还能保持动态加载的灵活性,参考代码如下:

DexClassLoader loader = new DexClassLoader("/dynamic.jar", getApplicationInfo().dataDir, null, this.getClass().getClassLoader());
clazz = loader.loadClass("com.dl.plugin.Plugin");
IPlugin obj = (IPlugin) clazz.newInstance();
int result = obj.add(1, 1);

 

发表评论

4 × 1 =

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据