最近心血来潮想玩玩热修复,于是网上找了一堆文章,捣鼓了好久也没捣鼓出来,因为要么是不全要么就是太过于简单,不适合小白学习,最后经过查找,捣鼓出来了,特记下,以便以后学习:
第一步:新建一个工程项目很很普通的一个工程,页面也很简单就两个按钮
第二步:新建bug类
第三步:写修复工具类,代码如下:
public class FixDexUtil {
private static final String DEX_SUFFIX = “.dex”;
private static final String APK_SUFFIX = “.apk”;
private static final String JAR_SUFFIX = “.jar”;
private static final String ZIP_SUFFIX = “.zip”;
public static final String DEX_DIR = “odex”;
private static final String OPTIMIZE_DEX_DIR = “optimize_dex”;
private static HashSet loadedDex = new HashSet<>();

static {loadedDex.clear();
}/*** 加载补丁,使用默认目录:data/data/包名/files/odex** @param context*/
public static void loadFixedDex(Context context) {loadFixedDex(context, null);
}/*** 加载补丁** @param context       上下文* @param patchFilesDir 补丁所在目录*/
public static void loadFixedDex(Context context, File patchFilesDir) {// dex合并之前的dexdoDexInject(context, loadedDex);
}/*** @author bthvi* @time 2018/6/25 0025 15:51* @desc 验证是否需要热修复*/
public static boolean isGoingToFix(@NonNull Context context) {boolean canFix = false;File externalStorageDirectory = Environment.getExternalStorageDirectory();// 遍历所有的修复dex , 因为可能是多个dex修复包File fileDir = externalStorageDirectory != null ? new File(externalStorageDirectory, "007") : new File(context.getFilesDir(), DEX_DIR);// data/data/包名/files/odex(这个可以任意位置)File[] listFiles = fileDir.listFiles();if (listFiles != null) {for (File file : listFiles) {if (file.getName().endsWith(DEX_SUFFIX) || file.getName().endsWith(APK_SUFFIX) || file.getName().endsWith(JAR_SUFFIX) || file.getName().endsWith(ZIP_SUFFIX)) {loadedDex.add(file);// 存入集合// 有目标dex文件, 需要修复canFix = true;}}} return canFix;
}private static void doDexInject(Context appContext, HashSet<File> loadedDex) {String optimizeDir = appContext.getFilesDir().getAbsolutePath() + File.separator + OPTIMIZE_DEX_DIR;// data/data/包名/files/optimize_dex(这个必须是自己程序下的目录)File fopt = new File(optimizeDir);if (!fopt.exists()) {fopt.mkdirs();}try {// 1.加载应用程序dex的LoaderPathClassLoader pathLoader = (PathClassLoader) appContext.getClassLoader();for (File dex : loadedDex) {// 2.加载指定的修复的dex文件的LoaderDexClassLoader dexLoader = new DexClassLoader(dex.getAbsolutePath(),// 修复好的dex(补丁)所在目录fopt.getAbsolutePath(),// 存放dex的解压目录(用于jar、zip、apk格式的补丁)null,// 加载dex时需要的库pathLoader// 父类加载器);// 3.开始合并// 合并的目标是Element[],重新赋值它的值即可/*** BaseDexClassLoader中有 变量: DexPathList pathList* DexPathList中有 变量 Element[] dexElements* 依次反射即可*///3.1 准备好pathList的引用Object dexPathList = getPathList(dexLoader);Object pathPathList = getPathList(pathLoader);//3.2 从pathList中反射出element集合Object leftDexElements = getDexElements(dexPathList);Object rightDexElements = getDexElements(pathPathList);//3.3 合并两个dex数组Object dexElements = combineArray(leftDexElements, rightDexElements);// 重写给PathList里面的Element[] dexElements;赋值Object pathList = getPathList(pathLoader);// 一定要重新获取,不要用pathPathList,会报错setField(pathList, pathList.getClass(), "dexElements", dexElements);}Toast.makeText(appContext, "修复完成", Toast.LENGTH_SHORT).show();} catch (Exception e) {e.printStackTrace();}
}/*** 反射给对象中的属性重新赋值*/
private static void setField(Object obj, Class<?> cl, String field, Object value) throws NoSuchFieldException, IllegalAccessException {Field declaredField = cl.getDeclaredField(field);declaredField.setAccessible(true);declaredField.set(obj, value);
}/*** 反射得到对象中的属性值*/
private static Object getField(Object obj, Class<?> cl, String field) throws NoSuchFieldException, IllegalAccessException {Field localField = cl.getDeclaredField(field); localField.setAccessible(true); return localField.get(obj);
}
/*** 反射得到类加载器中的pathList对象*/
private static Object getPathList(Object baseDexClassLoader) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {return getField(baseDexClassLoader, Class.forName("dalvik.system.BaseDexClassLoader"), "pathList");
}
/*** 反射得到pathList中的dexElements*/
private static Object getDexElements(Object pathList) throws NoSuchFieldException, IllegalAccessException {return getField(pathList, pathList.getClass(), "dexElements");
}/*** 数组合并*/private static Object combineArray(Object arrayLhs, Object arrayRhs) {Class<?> clazz = arrayLhs.getClass().getComponentType();int i = Array.getLength(arrayLhs);// 得到左数组长度(补丁数组)int j = Array.getLength(arrayRhs);// 得到原dex数组长度int k = i + j;// 得到总数组长度(补丁数组+原dex数组)Object result = Array.newInstance(clazz, k);// 创建一个类型为clazz,长度为k的新数组System.arraycopy(arrayLhs, 0, result, 0, i);System.arraycopy(arrayRhs, 0, result, i, j);return result;
}

}
第四步:MainActivity两个按钮操作也贴出来吧:

init()方法如下: File externalStorageDirectory = Environment.getExternalStorageDirectory();
// 遍历所有的修复dex , 因为可能是多个dex修复包
// data/user/0/包名/files/odex(这个可以任意位置)
File fileDir = externalStorageDirectory != null ? new File(externalStorageDirectory, “007”) : new File(getFilesDir(), FixDexUtil.DEX_DIR);
if (!fileDir.exists()) {
fileDir.mkdirs();
}
if (FixDexUtil.isGoingToFix(this)) {
FixDexUtil.loadFixedDex(this,
Environment.getExternalStorageDirectory());
}
此刻运行项目点击按钮bug,项目铁定闪退的。
接下来就是修复了,用心看了,不然一不下心就修复不了的:
一、修改bug类

二、修改工程的安装:

三、Build→Rebuild Project
四、找到第五步:最关键的一步了 ,因为要把class转换成dex
首先新建一个文件夹(任意位置都可以)
其次在新建文件夹一定要和上面的位置相对应不然打不出dex文件
最后了 打开命令 开始键+R →输入 cmd 一定要先进到sdk的这个文件下(其他的也行)输入命令dx --dex --output=D:\dex\out.dex D:\dex ; D:\dex\out.dex是指输出到哪个文件夹下叫什么文件 看有了吧
奇迹就在这了
看到没 把打出的dex文件复制到这个文件夹下 然后重新打开程序 点击修复 再点击bug按钮 程序奇迹般的出来结果了。。。。。
本人小白 写的不好 如有问题请留言 大家一起交流 2622760038

Aandroid最简单最全面的热修复相关推荐

  1. 手动实现最简单的Android热修复(最新最全详细小白教程)

    前言 最近了解到了热修复相关的东西,于是很好奇原理,便一番搜索资料,同时为了加深对热修复的理解,便自己照着网上的例子去实现一个热修复,因为基础相对比较差,而且网上很多例子都是过时的,而且很多细节不注意 ...

  2. Android热修复原理及简单实现

    文章目录 概念 第三方框架 阿里系 腾讯系 美团 简单实现 预期效果 准备 dex分包 实现原理 分析ClassLoader相关源码 生成dex文件 代码实现 概念 我们先假设一个场景,如果一个已经上 ...

  3. Android热修复学习之旅——HotFix完全解析

    在上一篇博客 Android热修复学习之旅开篇--热修复概述中,简单介绍了各个热修复框架的原理,本篇博客我将详细分析QQ空间热修复方案. Android dex分包原理介绍 QQ空间热修复方案基于An ...

  4. Android热修复技术总结

    插件化和热修复技术是Android开发中比较高级的知识点,是中级开发人员通向高级开发中必须掌握的技能,插件化的知识可以查我我之前的介绍:Android插件化.本篇重点讲解热修复,并对当前流行的热修复技 ...

  5. 热修复——Bugly让热修复变得如此简单

    一.简述 在上一篇<热修复--Tinker的集成与使用>中,根据Tinker官方Wiki集成了Tinker,但那仅仅只是本地集成,有一个重要的问题没有解决,那就是补丁从服务器下发到用户手机 ...

  6. 服务器中的热修复怎么做,Android 热修复(全网最简单的热修复讲解)

    首先!我们抛开网上的热修复框架不谈,我们来通过原理手动实现一个热修复工具,在撸码之前我们先通过一张图来了解热修复的流程. Android热修复 ACCCB328-AF5C-4BD9-AD08-6F7D ...

  7. springboot 搭建 简单 web项目 【springboot + freemark模板 + yml 配置文件 + 热修复 + 测试用例】附源码...

    项目 地址:  https://gitee.com/sanmubird/springboot-simpleweb.git 项目介绍: 本项目主要有一下内容: 1: springboot yml 配置 ...

  8. Android-第三方开源框架:Bugly让热修复变得如此简单

    作者:GitLqr 纸上说来终觉浅,时间比较充裕的小伙伴建议去B站观看视频讲解:Android第三方开源库系列-热修复框架使用.原理及项目实战(已完结) 一.简述 在上一篇<热修复--Tinke ...

  9. 阿里最强热修复:Sophix 超高速集成与踩坑

    超高速集成 public class SophixStubApplication extends SophixApplication {private final String TAG = " ...

最新文章

  1. 雷军、张小龙:高手的努力深入而轻松,普通人的努力肤浅而痛苦!
  2. 数据挖掘 —— 模型评估
  3. mysql分页查询limit_MySQL查询语句(where,group by,having,order by,limit)
  4. Response_案例1_路径_绝对路径
  5. 【渝粤教育】21秋期末考试建设工程法规10221k1
  6. eclipse中设置编码格式
  7. 3198元起!魅族16s开启预约:4月28日全渠道首发
  8. npm设置仓库register
  9. Swift给每个开发者赢取500万的机会!不看一生后悔。
  10. CentOS 5 常见的configure error的解决方法
  11. python 代理抓包_python requests代理设置,fiddler抓包
  12. 图像处理学习路线总结 python
  13. Java2实用教程(第五版)/第五章例题
  14. android app 隐藏应用,教你一招,隐藏我们手机中的APP应用!
  15. ADB模拟点击、滑动事件
  16. 影视剪辑,如何进行混剪,镜头流畅衔接
  17. Fire And Motion(英文原版) [转]
  18. 职场修炼--你开口说话的境界在第几层?
  19. 展开关闭页面html,JQUERY实现网页右下角固定位置展开关闭特效的方法
  20. 如何理解智慧Lora技术

热门文章

  1. eclipse导入项目jsp文件报错
  2. 多媒体-用windows自带录音机录音(转载)
  3. 2022款联想小新Pro16,联想小新air15,thinkbook16+选哪个好
  4. 12、计算机如何实现开根号?
  5. 推荐几个值得关注的技术公众号
  6. python培训价目表-培训python大概要多少钱?
  7. 显示一张桌子的信息,包括桌子的形状(长方形、方形、圆形、椭圆形;使用Rect、Square、Circle、Ellipse)、腿数、高度、桌面面积。定义变量来保存桌子的信息,并显示各个信息的值。要点提示
  8. 构建一个适合stm32mp157系列开发板的嵌入式Linux系统
  9. 日常之卸载奇安信相关~
  10. excel提取括号内的内容