参考资料
https://mp.weixin.qq.com/s?__biz=MzI1MTA1MzM2Nw==&mid=400118620&idx=1&sn=b4fdd5055731290eef12ad0d17f39d4a&scene=1&srcid=1106Imu9ZgwybID13e7y2nEi#wechat_redirect
https://github.com/dodola/HotFix
http://blog.youkuaiyun.com/lmj623565791/article/details/49883661
http://www.cnblogs.com/alibaichuan/p/5863616.html
http://blog.youkuaiyun.com/huachao1001/article/details/51819972
什么是热修复?
1.正常开发流程
从流程来看,传统的开发流程存在很多弊端:
- 重新发布版本代价太大
- 用户下载安装成本太高
- BUG修复不及时,用户体验太差
2.热修复开发流程
热修复的开发流程显得更加灵活,优势很多:
- 无需重新发版,实时高效热修复
- 用户无感知修复,无需下载新的应用,代价小
- 修复成功率高,把损失降到最低
前言
热修复作为当下热门的技术,在业界内比较著名的有阿里巴巴的AndFix、Dexposed,腾讯QQ空间的热补丁动态修复和微信的Tinker。本文基于QQ空间的热补丁动态修复方案。
关于Gradle 1.5版本以前对HotFix的分析文章,网上有很多,推荐鸿洋大大的博客
http://blog.youkuaiyun.com/lmj623565791/article/details/49883661
但在Gradle 1.5开始,preDex和Dex这两个task已经消失,取而代之的是com.android.build.api.transform.Transfrom,这也就导致了目前的Gradle版本有很多问题要处理。
Google Transform API
http://tools.android.com/tech-docs/new-build-system/transform-api
本文旨在让以前从来没有接触过HotFix的同学从零学习,而不需切换到Gradle 1.5以前的版本。
需要掌握的知识
- Groovy语言:掌握基本语法和闭包即可
- Gradle插件开发:掌握当前项目插件开发即可
- Javassist:掌握基本动态改变类结构方法即可
- Dex分包
针对Groovy语言和Javassist相关方法介绍,网上有很多相关资料,在这里不再重复。本文只需掌握Groovy基本语法,闭包以及Javassist动态改变类结构方法即可。
Javassist API
http://jboss-javassist.github.io/javassist/html/index.html
其余知识,下面做一个简单介绍。
Gradle插件开发
关于Gradle插件开发,本文就创建当前项目插件做一个简单总结。
- File->New->New Module->选择Phone Module或Android Library->将Application Name及Module Name改为buildsrc。注意这里如果要创建当前项目插件,必须改为buildsrc,其余名称均不可。
- 将该模块除src/main及build.gradle外文件全部删除,将build.gradle内内容清空。
- 在main目录下创建groovy文件夹。
- 在groovy文件夹下新建包,并新建文件,命名为HotFixInjectPlugin.groovy
- 修改build.gradle文件如下
apply plugin: 'groovy'
dependencies {
compile gradleApi()
compile localGroovy()
}
repositories {
jcenter()
}
新建的HotFixInjectPlugin.groovy需要实现Plugin接口,代码如下。
package zjm.cst.dhu.plugin
import org.gradle.api.Plugin
import org.gradle.api.Project
public class HotFixInjectPlugin implements Plugin<Project> {
@Override
void apply(Project project) {
println("--->Apply HotFixInjectPlugin")
}
}
在App的build.gradle中加入
apply plugin: 包名.HotFixInjectPlugin
当App应用该插件时即会调用apply方法。
注意,若更改插件模块中内容,请先clean工程后再make工程
Dex分包
关于Dex分包基本概念与原理,网上有很多相关资料,这里就不再谈了,但具体实现大多是Gradle 1.5版本以前的。而Gradle 1.5以后版本,由于dex任务取消,导致之前在build.gradle中控制分包参数失效,而替换的则是dexOptions参数。
dexOptions {
javaMaxHeapSize "4g"
preDexLibraries = false
additionalParameters = ['--multi-dex', '--main-dex-list=' + project.rootDir.absolutePath + '/app/maindexlist.txt', '--minimal-main-dex','--set-max-idx-number=30000']
}
其中maindexlist.txt文件为最先加载class列表。将\app\build\intermediates\multi-dex\debug目录下的maindexlist.txt复制到app目录下,并在其中加入我们希望分到主dex的class文件即可。
HotFix原理
关于HotFix基本原理,QQ空间团队的文章已有介绍
这里我总结一下HotFix的原理。
- 类加载器中存放dex的数组位置位于ClassLoader中DexPathList实例 pathList中。具体为DexPathList类中dexElements数组。关于对ClassLoader及DexPathList源码研究,后面在使用反射机制插入dex时也会用到。
BaseDexClassLoader源码
http://androidxref.com/4.4.2_r1/xref/libcore/dalvik/src/main/java