Android插件化开发之运行未安装apk的activity(2)

简介: Android插件化开发之运行未安装apk的activity(2)

4、合并PathClassLoader和DexClassLoader中的dexElements数组

我们首先来看一下PathClassLoader和DexClassLoader类加载器的父类BaseDexClassloader的源码:

(这里需要注意的是PathClassLoader和DexClassLoader类的父加载器是BaseClassLoader,他们的父类是BaseDexClassLoader)

1.png

这里有一个DexPathList对象,在来看一下DexPathList.java源码:

1.png

Elements数组,我们看到这个变量他是专门存放加载的dex文件的路径的,系统默认的类加载器是PathClassLoader,本身一个程序加载之后会释放一个dex出来,这时候会将dex路径放到里面,当然DexClassLoader也是一样的,那么我们会想到,我们是否可以将DexClassLoader中的dexElements和PathClassLoader中的dexElements进行合并,然后在设置给PathClassLoader中呢?这也是一个思路。我们来看代码:

/**
 * 以下是一种方式实现的
 * @param loader
 */
private void inject(DexClassLoader loader){
  PathClassLoader pathLoader = (PathClassLoader) getClassLoader();
  try {
    Object dexElements = combineArray(
        getDexElements(getPathList(pathLoader)),
        getDexElements(getPathList(loader)));
    Object pathList = getPathList(pathLoader);
    setField(pathList, pathList.getClass(), "dexElements", dexElements);
  } catch (IllegalArgumentException e) {
    e.printStackTrace();
  } catch (NoSuchFieldException e) {
    e.printStackTrace();
  } catch (IllegalAccessException e) {
    e.printStackTrace();
  } catch (ClassNotFoundException e) {
    e.printStackTrace();
  }
}
private static Object getPathList(Object baseDexClassLoader)
    throws IllegalArgumentException, NoSuchFieldException, IllegalAccessException, ClassNotFoundException {
  ClassLoader bc = (ClassLoader)baseDexClassLoader;
  return getField(baseDexClassLoader, Class.forName("dalvik.system.BaseDexClassLoader"), "pathList");
}
private static Object getField(Object obj, Class<?> cl, String field)
    throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
  Field localField = cl.getDeclaredField(field);
  localField.setAccessible(true);
  return localField.get(obj);
}
private static Object getDexElements(Object paramObject)
    throws IllegalArgumentException, NoSuchFieldException, IllegalAccessException {
  return getField(paramObject, paramObject.getClass(), "dexElements");
}
private static void setField(Object obj, Class<?> cl, String field,
    Object value) throws NoSuchFieldException,
    IllegalArgumentException, IllegalAccessException {
  Field localField = cl.getDeclaredField(field);
  localField.setAccessible(true);
  localField.set(obj, value);
}
private static Object combineArray(Object arrayLhs, Object arrayRhs) {
  Class<?> localClass = arrayLhs.getClass().getComponentType();
  int i = Array.getLength(arrayLhs);
  int j = i + Array.getLength(arrayRhs);
  Object result = Array.newInstance(localClass, j);
  for (int k = 0; k < j; ++k) {
    if (k < i) {
      Array.set(result, k, Array.get(arrayLhs, k));
    } else {
      Array.set(result, k, Array.get(arrayRhs, k - i));
    }
  }
  return result;
}

然后运行的时候把MyApplication.java文件里面的函数loadApkClassLoader(mClassLoader);注释掉,然后把MainActivity.java文件里面的inject(MyApplication.mClassLoader)不要注释,运行效果一样。



总结:

我们在使用反射机制来动态加载Activity的时候,有两个思路:


1>、替换LoadApk类中的mClassLoader变量的值,将我们动态加载类DexClassLoader设置为mClassLoader的值


2>、合并系统默认加载器PathClassLoader和动态加载器DexClassLoader中的dexElements数组


这两个的思路原理都是一样的:就是让我们动态加载进来的Activity能够具备正常的启动流程和生命周期。


我们还没解决资源冲突问题,后面再解决,有点复杂。


相关文章
|
3月前
|
存储 人工智能 Android开发
为什么微信发送的APP安装不了,.apk转化为.apk.1
微信发送的APP文件常被改为.apk.1格式导致无法安装,推荐使用夸克或QQ浏览器解决。
223 14
|
8月前
|
移动开发 安全 Java
Android历史版本与APK文件结构
通过以上内容,您可以全面了解Android的历史版本及其主要特性,同时掌握APK文件的结构和各部分的作用。这些知识对于理解Android应用的开发和发布过程非常重要,也有助于在实际开发中进行高效的应用管理和优化。希望这些内容对您的学习和工作有所帮助。
739 83
|
7月前
|
安全 算法 小程序
【03】微信支付商户申请下户到配置完整流程-微信开放平台创建APP应用-填写上传基础资料-生成安卓证书-获取Apk签名-申请+配置完整流程-优雅草卓伊凡
【03】微信支付商户申请下户到配置完整流程-微信开放平台创建APP应用-填写上传基础资料-生成安卓证书-获取Apk签名-申请+配置完整流程-优雅草卓伊凡
403 28
【03】微信支付商户申请下户到配置完整流程-微信开放平台创建APP应用-填写上传基础资料-生成安卓证书-获取Apk签名-申请+配置完整流程-优雅草卓伊凡
|
8月前
|
前端开发 Java 编译器
当flutter react native 等混开框架-并且用vscode-idea等编译器无法打包apk,打包安卓不成功怎么办-直接用android studio如何打包安卓apk -重要-优雅草卓伊凡
当flutter react native 等混开框架-并且用vscode-idea等编译器无法打包apk,打包安卓不成功怎么办-直接用android studio如何打包安卓apk -重要-优雅草卓伊凡
214 36
当flutter react native 等混开框架-并且用vscode-idea等编译器无法打包apk,打包安卓不成功怎么办-直接用android studio如何打包安卓apk -重要-优雅草卓伊凡
|
7月前
|
监控 Shell Linux
Android调试终极指南:ADB安装+多设备连接+ANR日志抓取全流程解析,覆盖环境变量配置/多设备调试/ANR日志分析全流程,附Win/Mac/Linux三平台解决方案
ADB(Android Debug Bridge)是安卓开发中的重要工具,用于连接电脑与安卓设备,实现文件传输、应用管理、日志抓取等功能。本文介绍了 ADB 的基本概念、安装配置及常用命令。包括:1) 基本命令如 `adb version` 和 `adb devices`;2) 权限操作如 `adb root` 和 `adb shell`;3) APK 操作如安装、卸载应用;4) 文件传输如 `adb push` 和 `adb pull`;5) 日志记录如 `adb logcat`;6) 系统信息获取如屏幕截图和录屏。通过这些功能,用户可高效调试和管理安卓设备。
|
9月前
|
Dart 前端开发 Android开发
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
220 1
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
12月前
|
Android开发
Android面试之Activity启动流程简述
Android面试之Activity启动流程简述
210 6
|
12月前
|
消息中间件 Android开发 索引
Android面试高频知识点(4) 详解Activity的启动流程
Android面试高频知识点(4) 详解Activity的启动流程
157 3
|
12月前
|
缓存 前端开发 Android开发
Android实战之如何截取Activity或者Fragment的内容?
本文首发于公众号“AntDream”,介绍了如何在Android中截取Activity或Fragment的屏幕内容并保存为图片。包括截取整个Activity、特定控件或区域的方法,以及处理包含RecyclerView的复杂情况。
153 3
|
12月前
|
Android开发
Android面试之Activity启动流程简述
Android面试之Activity启动流程简述
115 0

热门文章

最新文章