听说”双11”是这么解决线上bug的

--Android线上热修复的使用与原理

预备知识和开发环境

Android NDK编程

AndFix浅析

Android线上热修复的原理大同小异,这里只针对目前最火的框架AndFix进行讲解。主要从AndFix的使用原理以及优缺点三个方面进行阐述。

使用方式

介绍

AndFix是一个AndroidApp的在线热补丁框架。使用此框架,我们能够在不重复发版的情况下,在线修改App中的Bug。AndFix就是 “AndroidHot-Fix”的缩写。

就目前来说,AndFix支持Android2.3到6.0版本,并且支持arm与X86系统架构的设备。完美支持Dalvik与ART的Runtime。目前已经应用到支付宝上。是比较成熟的hot-fix框架。

AndFix 的补丁文件是以.apatch 结尾的文件。(来源:网络)

接入流程图:


接入步骤

1) Maven或Gradle下载aar或直接引入源码

Maven:<dependency>    <groupId>com.alipay.euler</groupId>    <artifactId>andfix</artifactId>    <version>0.3.1</version>    <type>aar</type></dependency>Gradle:dependencies {    compile 'com.alipay.euler:andfix:0.3.1@aar'}

2) 初始化PatchManager

patchManager = new PatchManager(context);patchManager.init(appversion);//current version

3) 加载补丁包

patchManager.loadPatch();

4)存在新补丁包

patchManager.addPatch(path);//path of the patch file that was downloaded

5)删除所有补丁包

patchManager.removeAllPatch();

制作apatch文件

1) 工具 :apkpatch(Github下载)

2) 使用方式

打补丁命令:

usage: apkpatch -f <new> -t <old> -o <output> -k <keystore> -p <***> -a <alias> -e <***> -a,--alias <alias>     keystore entry alias. -e,--epassword <***>   keystore entry password. -f,--from <loc>        new Apk file path. -k,--keystore <loc>    keystore path. -n,--name <name>       patch name. -o,--out <dir>         output dir. -p,--kpassword <***>   keystore password. -t,--to <loc>          old Apk file path.
合并补丁命令:

usage: apkpatch -m <apatch_path...> -o <output> -k <keystore> -p <***> -a <alias> -e <***> -a,--alias <alias>     keystore entry alias. -e,--epassword <***>   keystore entry password. -k,--keystore <loc>    keystore path. -m,--merge <loc...>    path of .apatch files. -n,--name <name>       patch name. -o,--out <dir>         output dir. -p,--kpassword <***>   keystore password.

举例:

两个apk文件,一个有问题,一个把问题解决了,如图:

打开cmd,cd到apktool所在路径,执行如下命令:

回车,在C:\Users\xiayong\Desktop\HotFixTest\result目录下生成如下文件

其中,out.apatch便是我们需要的补丁文件。

代码混淆

PS:官方建议使用-applymapping 来打混淆包,保证两次混淆一致。
-keep class * extends java.lang.annotation.Annotation-keepclasseswithmembernames class * {    native <methods>;}

疑问

1、.apatch 文件下载下来以后的存储位置应该在哪里?

2、.apatch文件删除了还有效果吗?

3、hot-fix的安全性怎么保证?

带着疑问,请看原理分析~


原理剖析

原理图:


一句话说明:找到问题安装包中出错的Method,用.apatch文件中修复过的Method进行替换。

举个栗子:

演示代码来源:https://github.com/THEONE10211024/HotFixDemo

.apatch文件:

.apatch文件是hot-fix的关键,那么.apatch文件又是一个什么东西呢?下面,我们来重点分析一下.apatch文件。

1. apatch文件实际上是一个压缩文件

解压apatch文件,一探究竟:


包含了一个dex文件和一个文件夹。先看看文件夹里都有什么文件



重点是PATCH.MF文件,用记事本打开。



AndFix首先会读取这个文件里面的东西。保存在Patch类的一个对象里,备用。

再看看classes.dex文件。用反编译工具反编译后,我们会看到类似如下的文件:



分析好了apatch文件,接下来我们一步步看AndFix是怎么修复的。

把AndFix接入自己的APP只需要四行代码:

mPatchManager = new PatchManager(this);mPatchManager.init("1.0");mPatchManager.loadPatch();mPatchManager.addPatch(patchFileString);

1、mPatchManager = new PatchManager(this);

初始化一些以后会使用的对象。(详见代码)

2、mPatchManager.init("1.0");

首先判断传入的版本号“1.0”是否是已有补丁对应的版本号。不是,说明APP版本已经升级,需要把老版本的clean掉。然后初始化补丁包:遍历APP的私有目录(/data/data/xxx.xxx.xxx/file/apatch)下所有文件,找到以“apatch”为后缀的文件。解析文件->读取文件必要信息(主要是PATCH.MF中)->存放在mPatchs(类型:SortedSet<Patch>)中。

3. mPatchManager.loadPatch();

遍历mPatchs,针对每个补丁文件:安全校验->解析dex->加载类->找到含有MethodReplace注解的方法->hook替换。

核心的hook替换是调用C++实现的:


Dalvik虚拟机:


Art虚拟机:


Art虚拟的原理与Dalvik不一样,Art主要是修改“ArtMethod”的属性,让虚拟机“误认为”修改后的方法即是原来的方法。以5.0为例:


优势与亮点

1.提炼精华,简洁,轻便,适配广。完美的支持了Android 2.3到6.0系统,以及x86框架,机型覆盖率广。提供根据两个apk生成patch的工具,因而使用者只需正向编程,通过工具生成patch文件,下发给客户端即可,编程效率高。是完善的、高可用的热修复方案。

2.与业界其他方案对比:QQ空间、大众点评等采用的是动态加载dex方式。“后者纯java实现,但需要hack类的优化流程,将打CLASS_ISPREVERIFIED标签的类,去除此标签,以解决类与类引用不在一个dex中的异常问题。这会放弃dex optimize对启动运行速度的优化。原则上,这对于方法数没有大到需要multidex的应用,损失更明显。而前者不触犯原有的优化流程,只点杀需要hook的方法,更为纯粹、有效。”

不足与缺陷

1.仅仅支持android 方法的替换,不支持资源文件、xml的修复

2.慎用android:onClick="showToast"形式的事件注册。

3.有人反应和“EventBus”不兼容。(自己测试良好)

4.有人反应fix之后部分手机出现ANR。(自己遇见过)

集成注意事项

1.两手准备:一旦发现问题。1)服务器下发补丁包;2)服务器上把有问题的包替换成最新包

2.注意避免本地多次拉取补丁包。如果x版本存在y补丁,则不再下载该补丁。

资料链接

1) google的NDK例子

https://github.com/googlesamples/android-ndk

2) 几个开源热修复或插件化解决方案(排名不分先后)

https://github.com/lzyzsd/AndroidHotFixExamples

https://github.com/simpleton/dalvik_patch

https://github.com/dodola/HotFix

https://github.com/jasonross/Nuwa

https://github.com/alibaba/AndFix

https://github.com/rovo89/Xposed

https://github.com/alibaba/dexposed

https://github.com/bunnyblue/DroidFix

https://github.com/CtripMobile/DynamicAPK

3) 技术原理博客(排名不分先后)

http://bugly.qq.com/blog/?p=781(QQ空间的解决方案)

https://m.oschina.net/blog/308583(Android Dex分包方案)

http://lirenlong.github.io/hotfix/(浅析xposed、dexposed和AndFix的原理)

http://blog.csdn.net/lmj623565791/article/details/49883661(鸿洋)

http://blog.csdn.net/vipzjyno1/article/details/21039349/(android反编译) 最后,该篇文章所讲的内容我已经以demo的形式放在了github上,需要的朋友请看 这里

更多相关文章

  1. [置顶] Android(安卓)实现对话框圆角功能
  2. Android(安卓)DataBinding 找不到生成的binding类的原因
  3. Android创建文件夹
  4. Android(安卓)xmlns 的作用及其自定义
  5. [Android] 该文件包与具有同一名称的现有文件包存在冲突
  6. Android多分辨率适配
  7. 分析Android(安卓)根文件系统启动过程(init守护进程分析)
  8. Android(安卓)UI设计技巧
  9. NPM 和webpack 的基础使用

随机推荐

  1. android 平台设置默认home后按home键弹出
  2. android中文api(89)——ViewManager
  3. Android官方入门文档[1]创建一个Android
  4. Android - Manifest 文件 详解
  5. Android version and Linux Kernel versi
  6. Android 热点开关状态的判断和获取热点ss
  7. Android平台上优秀的开源项目
  8. Android之菜单总结
  9. android ndk编译x264开源(用于android的f
  10. [RK3399][Android7.1.1] WifiAp:开机默认