Robust是美团推出的一款热修复框架,我记的之前我们分享过一篇热修复之美团方案,看完这篇文章就动手写了个Demo版项目。果然等了不久,今年三月份美团将已经趋向于稳定的Robust开源,在Andoid开发界也是一致好评。

后面会陆续放出Robust热修复的代码分析。
作为开篇第一篇,这篇文章会介绍怎么使用,使用中需要注意的问题和以及Robust项目介绍。

热修复使用

热修复的步骤

按照它的步骤:

  1. 导入Robust插件
  2. 打出基础包,将生成的Robust相关文件放到指定目录下
  3. 修改代码
  4. 添加自动打补丁包插件
  5. 打出补丁包,并将包放到指定路径
  6. 基础包加载补丁包实现热修复

Robust使用注意事项

不过在实际操作中,发现了如下问题:
1.
auto-patch-plugin只能在打补丁包时打开,也就是上面的第5步,打基础包时,不要打开。

2. 打出基础包后,需要将生成的mapping文件以及build/outputs/robust/methodsMap.robust文件。
为了更好使用写了个Gradel脚本.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
task deleteFiles(type: Delete) {
delete fileTree('output') {
include '**'
}
}

copyFiles {
description = 'copy methodsMap to output file'
from 'build/outputs/robust/methodsMap.robust'
into 'robust/'

from 'build/outputs/mapping/release/mapping.txt'
into 'robust/'

from 'build/outputs/apk/app-release.apk'
into 'robust/'
}
task copyFiles(type: Copy) dependsOn deleteFiles

所以在打基础包后,可以直接运行

1
2

./gradlew copyFiles(Windows:./gradlew.bat copyFiles)

这样在app下就有
methodsMap.robust
mapping.txt
app-release.apk这三个文件。

3. 配置主项目下一定要配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19


```java
<!--需要热补的包名或者类名,这些包名下的所有类都被会插入代码-->
<packname name="hotfixPackage">
<name>com.meituan</name>
<name>com.sankuai</name>
<name>com.dianping</name>
</packname>

<!--不需要热补的包名或者类名,可以在需要热补的包中剔除指定的类或者包-->
<exceptPackname name="exceptPackage">
<name>com.meituan.robust</name>
</exceptPackname>

<!--补丁的包名-->
<patchPackname name="patchPackname">
<name>com.meituan.robust.patch</name>
</patchPackname>

这个需要根据我们的实际情况来配置。hotfixPackage下所有类都会有一桩,也就是说每个类里面都会有一个静态的接口:

1
public static ChangeQuickRedirect     changeQuickRedirect;

Robust项目介绍

在Robust项目下有四个模板:
Robust
– auto-patch-plugin
– gradle-plugin
– patch
– autopatchbase

auto-patch-plugin 这个是自动打包的插件
gradle-plugin 是为类中插桩的插件
patch 辅助管理和加载补丁的基础类
autopatchbase 是Robust最最基础的类,这个里面有我们的ChangeQuickRedirect这个桩接口。其他三个模块都需要依赖这个模块。
其基本流程如下:

  1. 第一次打基础包,我们使用的gradle-plugin,会在打包过程中将我们需要的类插入一个ChangeQuickRedirect桩接口的静态实例,每个函数前插入如下代码:

    1
    2
    3
    4
    5
    if(changeQuickRedirect != null) {    
    //PatchProxy中封装了获取当前className和methodName的逻辑,并在其内部最终调用了changeQuickRedirect的对应函数
    if(PatchProxy.isSupport(new Object[0], this, changeQuickRedirect, false)) {
    return ((Long)PatchProxy.accessDispatch(new Object[0], this, changeQuickRedirect, false)).longValue();
    }
  2. 修改代码,在改动的代码前添加@Add或者@Modify的注释

  3. 使用auto-patch-plugin插件,来生成相对应的补丁。

  4. 加载补丁,通过补丁中的com.meituan.robust.patch.PatchesInfoImpl获取哪个类需要插桩和插入的桩接口对应的实现类。

现在留下几个疑问:

  1. 如何通过gradle-plugin为需要的类插桩?
  2. 打包过程中会有代码混淆,怎么解决代码混淆和对应的补丁问题
  3. 改变代码后,这个注解有什么用,auto-patch-plugin如何通过和之前的文件比较,怎么生成补丁。