前段时间在项目上遇到需要一个app中要集成同一个SDK的多个版本,但是常规方法都会在编译阶段无法兼容,编译报错:

Duplicate class xxxx found in modules xxx.jar and xxx.jar;

于是乎,了解到DexClassLoader,第一次见这个东西,看了官方说明文档,或许是我想要的。于是开始实践。

1.什么是dex?

引用一个通俗的的说明:

简单说就是优化后的android版.exe。每个apk安装包里都有。
相对于PC上的java虚拟机能运行.class;android上的Davlik虚拟机能运行.dex。
为何要研究dex格式?因为dex里面包含了所有app代码,利用反编译工具可以获取java源码。理解并修改dex文件,就能更好的apk破解和防破解。

ClassLoader比较常用的分为两种,PathClassLoader和DexClassLoader,虽然两者继承于BaseDexClassLoader,BaseDexClassLoader继承于ClassLoader,但是前者只能加载已安装的Apk里面的dex文件,后者则支持加载apk、dex以及jar,也可以从SD卡里面加载。

2.如何得到dex?

对于sdk来说(一般是aar或者jar形式),首先需要先将sdk的class转换成Dalvik可识别的dex文件,分两步:

2.1.先从aar找到SDK为jar包的形式,一般将aar格式改为zip解压就可以得到。

2.2.通过android sdk 自带的dx.jar工具转换jar包为包含dex文件的Jar文件。

D:\winTools\Sdk\build-tools\29.0.2>dx --dex --output=out.jar classes.jar

在同目录就会得到含dex的out.jar。

3.什么是DexClassLoader?

DexClassLoader用来加载外部的类,外部类的dexpath路径在构造方法中传入,先看下他的构造函数

public DexClassLoader(String dexPath, String optimizedDirectory, String librarySearchPath,ClassLoader parent) {super((String)null, (File)null, (String)null, (ClassLoader)null);throw new RuntimeException("Stub!");}
参数 含义
dexPath 包含dex文件的jar包或apk文件路径
optimizedDirectory 释放目录,可以理解为缓存目录,必须为应用私有目录,不能为空
librarySearchPath native库的路径(so文件),可为空
parent 父类加载器

通过构造,就可以获得DexClassLoader对象:

DexClassLoader loader = new DexClassLoader(versionFileDir, optimizedDir, libraryDir, context.getClass().getClassLoader());

4.反射类

通过DexClassLoader和对应的类名来反射类对象,先看下loadClass构造

public Class<?> loadClass(String name) throws ClassNotFoundException {return loadClass(name, false);
}
Class<?> classzz= loadClass(mLoader, "mcv.facepass.FacePassHandler");

5.通过类对象反射构造函数

//
Constructor constructor = clazz.getConstructor();
instance = onstructor.newInstance();

6.通过类对象反射类变量和实例

Field[] fields = clazz.getFields();
for (int i = 0; i < fields.length; i++) {if (fields[i].getName().equals(fieldName)) {fields[i].set(object, value);}
}         

7.反射方法

 Method methodInvoke = clazz.getMethod(method, Context.class);Object obj = methodInvoke.invoke(null, arg);

8.反射静态方法

Method mt = clazz.getMethod(method);
Obaject obj = mt.invoke(instance);

至此,即可实现对第三方sdk的全部调用。

回头看下,如何实现多版本的sdk切换呢? 其实很简单

只需要在切换是,重新初始化下DexClassLoader,通过不同路径去加载不同的SDK即可

if (mLoaders.get(versionIndex) == null) {//每个SDK的 DexClassLoader 只能初始化一次DexClassLoader dexClassLoader = initClassLoader(this, VERSIONS[versionIndex]);mLoaders.add(versionIndex, dexClassLoader);
} else {Log.d(TAG, "initSDK DexClassLoader :already exist " + VERSIONS[versionIndex]);
}mLoader = mLoaders.get(versionIndex);

切换的时候,只要通过versionIndex去拿到对应的对象即可,需要注意的是,每个SDK的 DexClassLoader 只能初始化一次!

mLoader = mLoaders.get(versionIndex);

最后看下效果

Android 动态加载多版本SDK之DexClassLoader实践相关推荐

  1. Android动态加载进阶 代理Activity模式

    基本信息 作者:kaedea 项目:android-dynamical-loading 技术背景 简单模式中,使用ClassLoader加载外部的Dex或Apk文件,可以加载一些本地APP不存在的类, ...

  2. Android动态加载技术

    基本信息 Author:kaedea GitHub:android-dynamical-loading 我们很早开始就在Android项目中采用了动态加载技术,主要目的是为了达到让用户不用重新安装AP ...

  3. android 动态 dex,Android 动态加载dex

    首先如果仅仅是因为64K method的问题可以直接看这里DexGuard.Proguard.Multi-dex给出的解决方案. 本文主要讨论从编译层面,dex动态加载器选择层面以及安全层面讨论dex ...

  4. Android动态加载技术初探

    一.前言: 现在,已经有实力强大的公司用这个技术开发应用了,比如淘宝,大众点评,百度地图等,之所以采用这个技术,实际上,就是方便更新功能,当然,前提是新旧功能的接口一致,不然会报Not Found等错 ...

  5. android jar 加入图片,Android动态加载外部jar包及jar包中图片等资源文件

    Android动态加载外部jar包及jar包中图片等资源文件 Android应用程序由Java开发,因此Java中许多实用的特性,在Android中也有体现.动态加载Class,也就是外部jar包,在 ...

  6. [转]Android动态加载jar/dex

    本文转自:http://www.cnblogs.com/over140/archive/2011/11/23/2259367.html 前言 在目前的软硬件环境下,Native App与Web App ...

  7. Android动态加载黑科技 动态创建Activity模式

    基本信息 Author:kaedea GitHub:android-dynamical-loading 代理Activity模式的限制 还记得我们在代理Activity模式里谈到启动插件APK里的Ac ...

  8. Android应用开发提高系列(4)——Android动态加载(上)——加载未安装APK中的类...

    前言 近期做换肤功能,由于换肤程度较高,受限于平台本身,实现起来较复杂,暂时搁置了该功能,但也积累了一些经验,将分两篇文章来写这部分的内容,欢迎交流! 关键字:Android动态加载 声明 欢迎转载, ...

  9. android 动态生成fragment,Android动态加载fragment(fragment复用)

    [实例简介] Android动态加载fragment(fragment复用) [实例截图] [核心代码] fm_reuse └── fm_reuse ├── AndroidManifest.xml ├ ...

最新文章

  1. C++ 和C 语言混合代码导致的问题
  2. Linux中内联函数,Windows 7上的内联函数的doParallel问题(适用于Linux)
  3. hibernate在saveOrUpdate时,update报错:a different object with the same identifier value was already assoc
  4. VMware vSphere 6 Enterprise Plus 永久激活许可证-亲测可用
  5. 照片转3d模型_三星使用AI将照片转换为3D模型
  6. 一步一步写算法(之线性堆栈)
  7. 让天下没有难做的研发:解读阿里CI/CD、DevOps、分层自动化技术
  8. 竹林蹊径:深入浅出Windows驱动开发
  9. Kubernetes 之资源管理
  10. 第 10 章 容器监控 - 080 - Weave Scope 容器地图
  11. 发布房源(三)02——获取表单数据- onSelect 处理方法 打印表单数据
  12. 李岩 太极计算机,《高中体育游戏300例》李岩_孔网
  13. mybatis 练习二(vue)
  14. ObjectARX C++自定义实体
  15. 计算机文档排版考试,Word和WPS通用的文档排版技巧
  16. jcr多久更新一次_JCR-2017更新 | 快来看看你的影响影子吧
  17. ZK5.0和客户端+服务器端相结合的编程方式
  18. 深度解析JavaScript原型链
  19. 概论_第3章_二维随机变量__均匀分布
  20. ERROR StatusLogger Log4j2 could not find a logging implementation.

热门文章

  1. Html 课程笔记(1)
  2. 漏洞挖掘之乱拳打死老师傅——Fuzzer
  3. 整个部门就一个研发?
  4. 结合进化心理学,解析陌生交友产品的三大问题
  5. RTK Query(RTKQ)
  6. 精美图标大全_40个精美表情符号和笑脸图标包
  7. 高性价比的车联网数据记录仪-OWA4xx
  8. RecycleView复用错乱常用解决办法
  9. 每天学点英语语法-重头开始8
  10. 脑波设备mindwaveTGC接口示例