Android之ClassLoader和插件
Android中的ClassLoader本质上跟JRE中的一样,但Android的字节码格式不一样,Android下的ClassLoader不能直接加载普通的jar包,需要使用dex2jar工具中的d2j-jar2dex.bat, 把jar转换为classes.dex,然后把classes.dex放到jar文件中作为ClassLoader的源数据;
1)我们先生成一个Android需要的JAR;
源码:
1package test; 2 3public class AnPluginDemo { 4 public int getValue() { 5 return 100; 6 } 7}
2)打包成jar;
3)使用dex2jar工具中的d2j-jar2dex.bat, 把jar转换为classes.dex;
4)把classes.dex放到一个新的jar中, AnPluginDemo.jar;
5)建立一个Android工程;
6)把AnPluginDemo.jar放到assets下;
7)加载插件并运行
1void loadAndInvoke(String name) { 2 try { 3 File dir = getDir("plugin", Context.MODE_PRIVATE); 4 5 byte[] bs = readDataFromAsserts("plugin/" + name);// 读取插件数据 6 String path = new File(dir, name).getAbsolutePath();// 插件保存的位置 7 Files.writeFile(path, bs);// 保存插件 8 9 // 创建类加载器,把dex加载到虚拟机中 10 DexClassLoader loader = new DexClassLoader(// 11 path,//插件路径,可以用冒号分隔多个, 可以是jar(内有classes.dex)或apk格式 12 dir.getAbsolutePath(),//优化后保存的目录 13 null,//so文件位置 14 this.getClass().getClassLoader()//父ClassLoader 15 ); 16 17 Class<?> c = loader.loadClass("test/AnPluginDemo");// 加载需要使用的类 18 Method m = c.getMethod("getValue");// 取得方法 19 Object o = c.newInstance();// 创建对象 20 Object r = m.invoke(o);// 调用方法 21 showTipDialog("R:" + r);//显示执行结果 22 } catch (Exception e) { 23 e.printStackTrace(); 24 showTipDialog("R:" + e.getClass()); 25 } 26 }