Android类加载器
来源:互联网 发布:大学英语单词听力软件 编辑:程序博客网 时间:2024/05/27 02:31
Android动态加载jar/dex——DexClassLoader类加载器
前言:
像eclipse、chrome浏览器中的插件,这些插件都是为了在一个主程序中实现比较通用的功能,把用户自定义扩展的功能不附加在主程序中,主程序可在运行时安装和卸载。还有在实际项目中,有些因为业务频繁的升级,造成了较差的用户体验,而使用以插件的形式会改善这类弊端。在Android如何实现插件已经被广泛使用,实现原理都是实现一套插件接口,把插件实现编成apk或者dex,然后在运行时使用DexClassLoader动态加载进来,不过在这个开发过程中会遇到一点问题,这里就介绍一下两种使用DexClassLoader来实现插件的功能。
一、概念
1.1 首先需要了解一点:在Android中可以动态加载,但无法像Java中那样方便动态加载
原因:Android的虚拟机(Dalvik VM)是不认识Java打出jar的byte code,需要通过dx工具来优化转换成Dalvik byte code才行。这 一点在咱们Android项目打包的apk中可以看出:引入其他Jar的内容都被打包进了classes.dex。所以这条路不通,请大家注意。
1.2 当前哪些API可用于动态加载
1.2.1 DexClassLoader
这个可以加载jar/apk/dex,也可以从SD卡中加载,也是本文的重点。
1.2.3 PathClassLoader
只能加载已经安装到Android系统中的apk文件。
二、实践(两种实现方案)
注意:为了方便,我这里没有写两个工程来测试,两种方案都是在一个工程中完成的!原理都是一样的。
2.1 方案一:(编写接口和实现,通过反射来调用插件程序中的方法)
2.1.1 接口Iinterfacepackage com.putaolab.dex; public interface Iinterface { public String getData(); }2.1.2 实现类Iclasspublic class Iclass implements Iinterface { public Context context; public Iclass(Context context){ this.context = context; } @Override public String getData(){ // TODO Auto-generated method stub return "hello,i am from the method of getData()..."; }}2.1.3 打包并转成dex > **选中工程,常规流程导出即可(一定注意:打包请不要把接口文件打进来,我就是因为把接口文件打包进了,出现了这个异常!** > **java.lang.IllegalAccessError: Class ref in pre-verified class resolved to unexpected implementation**) > **将打包好的jar拷贝到SDK安装目录android-sdk-windows\platform-tools下(注:这个目录没有的话,在build-tools目录会发现dex.bat批处理指令),DOS进入这个目录,执行命名: dx --dex --output=testdex.jar test.jar2.1.4 调用例子(反射调用-->本文我把jar优化后的testdex.jar从assets目录下复制到了SD卡下来反射加载的; 接口插件--->把testdex.jar从assets目录下复制到了data/data/包名/files目录下来处理的) /*法一:把优化后的jar(testdex.jar)复制到SD卡下,通过反射来调用插件的方法*/ FileUtil.copyAssetJarToFile(this, "testdex.jar", "testdex.jar"); File file = new File(Environment.getExternalStorageDirectory().toString() + File.separator + "testdex.jar"); File optimizedDexOutputPath = getDir("temp", Context.MODE_PRIVATE); /** * DexClassLoader类加载器构造的四个参数 * String dexPath:the list of jar/apk files containing classes and resources, delimited by File.pathSeparator, which defaults to ":" on Android * 需要装在的apk或者jar文件的路径,包含多个路径用File.pathSeparator间隔开,在Android上默认是“:” * String optimizedDirectory:directory where optimized dex files should be written; must not be null * 优化后的dex文件存放目录,不能为null * String libraryPath:the list of directories containing native libraries, delimited by File.pathSeparator; may be null * 目标类中使用的c/c++库的列表,每个目录用File.pathSeparator间隔开,可以为null * ClassLoader parent: the parent class loader * 该类装载器的父装载器,一般用当前执行类的装载器 */ DexClassLoader dexClassLoader = new DexClassLoader(file.getAbsolutePath(), optimizedDexOutputPath.getAbsolutePath(), null, getClassLoader()); try { Class<?> loadClass = dexClassLoader.loadClass("com.putaolab.dex.Iclass"); Constructor<?> constructor = loadClass.getConstructor(new Class[]{Context.class}); /*法一:反射调用方法*/ Method method = loadClass.getMethod("getData", null); String data = (String) method.invoke(constructor.newInstance(this), null); Log.e(tag, "data---"+data); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); }
2.2 方案二:(把接口作为联系主程序和插件程序的桥梁,要实现往程序通过接口调用插件的程序,那么主程序和插件程序必须有相同接口的文件,也就两个程序里都有接口的java类文件)
/*法二:把优化后的jar(testdex.jar)复制到data/data/包名/files/目录下,通过接口来*/ FileUtil.copyAssetJarToData(this, "testdex.jar", "testdex.jar"); File file = new File(this.getFilesDir().getAbsolutePath() + File.separator + "testdex.jar"); File optimizedDexOutputPath = getDir("temp", Context.MODE_PRIVATE); DexClassLoader dexClassLoader = new DexClassLoader(file.getAbsolutePath(), optimizedDexOutputPath.getAbsolutePath(), null, getClassLoader()); try { Class<?> loadClass = dexClassLoader.loadClass("com.putaolab.dex.Iclass"); Constructor<?> constructor = loadClass.getConstructor(new Class[]{Context.class}); /*法二:*/ Iinterface newInstance = (Iinterface) constructor.newInstance(this); String data = newInstance.getData(); Log.e(tag, "data---"+data); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); }
源代码下载地址:本文相关代码
1 0
- Android类加载器
- android中的类加载器
- android中的类加载器
- Android中的类加载器
- android类加载器ClassLoader
- Java类加载器及Android类加载器基础
- android中的类加载器,以及加载机制
- Android动态加载学习总结(一):类加载器
- Android之ClassLoader类加载器(MultiDex、动态加载dex)
- android类加载器的讨论
- Android类加载器源码简析
- android基础之ClassLoader类加载器
- Android Loader 加载器
- android动态加载类
- Android类加载
- Android类加载ClassLoader
- android开发-类加载
- Android加载器加载本地图片
- Android 开发学习——Button
- Kinect+OpenNI+VS
- oracle查询某张表某个时间点的数据(表结构未改变前)
- BZOJ 1457 棋盘游戏 SG函数
- Atom飞行手册翻译: 2.13 基本的自定义
- Android类加载器
- 排序(1106)
- 行内元素与块级元素比较全面的区别和转换
- js 与或运算符 || && 妙用
- Android上传文件 服务器端采用php
- 更新最新ADT
- Spring+Hibernate4配置使用cache的问题
- CSS学习笔记
- 构建可克隆的对象(icloneable)