循序渐进学HotFix (基于Gradle 1.5+版本)

本文详细介绍了如何从零开始学习HotFix,包括热修复的必要性、Gradle插件开发、Dex分包、HotFix原理、自定义Transform以及Java代码打包成独立Dex包等步骤。通过实践操作,展示了如何实现在不重新发布应用的情况下,进行高效、无感知的热修复。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考资料
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插件开发,本文就创建当前项目插件做一个简单总结。

  1. File->New->New Module->选择Phone Module或Android Library->将Application Name及Module Name改为buildsrc。注意这里如果要创建当前项目插件,必须改为buildsrc,其余名称均不可。
  2. 将该模块除src/main及build.gradle外文件全部删除,将build.gradle内内容清空。
  3. 在main目录下创建groovy文件夹。
  4. 在groovy文件夹下新建包,并新建文件,命名为HotFixInjectPlugin.groovy
  5. 修改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空间团队的文章已有介绍

https://mp.weixin.qq.com/s?__biz=MzI1MTA1MzM2Nw==&mid=400118620&idx=1&sn=b4fdd5055731290eef12ad0d17f39d4a&scene=1&srcid=1106Imu9ZgwybID13e7y2nEi#wechat_redirect

这里我总结一下HotFix的原理。

  • 类加载器中存放dex的数组位置位于ClassLoader中DexPathList实例 pathList中。具体为DexPathList类中dexElements数组。关于对ClassLoader及DexPathList源码研究,后面在使用反射机制插入dex时也会用到。

BaseDexClassLoader源码
http://androidxref.com/4.4.2_r1/xref/libcore/dalvik/src/main/java

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值