robust 热修复实践

一、导入项目

在项目根目录的build.gradle下添加

dependencies {
    classpath 'com.android.tools.build:gradle:3.1.2'
    //robust插件
    classpath "com.meituan.robust:gradle-plugin:${robustVersion}"
    classpath "com.meituan.robust:auto-patch-plugin:${robustVersion}"
    
}

gradle.properties添加版本号(或者写死,可以忽略):

#meituan hotfix
robustVersion = 0.4.82

在app目录下的build.gradle下添加

if(isMakeHot.toBoolean()){
    //制作补丁开启
    apply plugin: 'auto-patch-plugin'
}else{
    //生成apk开启
    apply plugin: 'robust'
}

dependencies {
     compile "com.meituan.robust:robust:${robustVersion}"
}

gradle.properties中添加开关,以后打包或者打补丁只要修改这个参数:

#Make a patch please set true
isMakeHot=false
二、配置文件

在app目录下添加robust.xml配置文件,一般修改patchPackname和hotfixPackage就可以了:

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <switch>
        <!--true代表打开Robust,请注意即使这个值为true,Robust也默认只在Release模式下开启-->
        <!--false代表关闭Robust,无论是Debug还是Release模式都不会运行robust-->
        <turnOnRobust>true</turnOnRobust>
        <!--<turnOnRobust>false</turnOnRobust>-->

        <!--是否开启手动模式,手动模式会去寻找配置项patchPackname包名下的所有类,自动的处理混淆,然后把patchPackname包名下的所有类制作成补丁-->
        <!--这个开关只是把配置项patchPackname包名下的所有类制作成补丁,适用于特殊情况,一般不会遇到-->
        <!--<manual>true</manual>-->
        <manual>false</manual>

        <!--是否强制插入插入代码,Robust默认在debug模式下是关闭的,开启这个选项为true会在debug下插入代码-->
        <!--但是当配置项turnOnRobust是false时,这个配置项不会生效-->
        <!--<forceInsert>true</forceInsert>-->
        <forceInsert>true</forceInsert>

        <!--是否捕获补丁中所有异常,建议上线的时候这个开关的值为true,测试的时候为false-->
        <catchReflectException>true</catchReflectException>
        <!--<catchReflectException>false</catchReflectException>-->

        <!--是否在补丁加上log,建议上线的时候这个开关的值为false,测试的时候为true-->
        <!--<patchLog>true</patchLog>-->
        <patchLog>false</patchLog>

        <!--项目是否支持progaurd-->
        <proguard>true</proguard>
        <!--<proguard>false</proguard>-->

        <!--项目是否支持ASM进行插桩,默认使用ASM,推荐使用ASM,Javaassist在容易和其他字节码工具相互干扰-->
        <useAsm>true</useAsm>
        <!--<useAsm>false</useAsm>-->
    </switch>

    <!--需要热补的包名或者类名,这些包名下的所有类都被会插入代码-->
    <!--这个配置项是各个APP需要自行配置,就是你们App里面你们自己代码的包名,
    这些包名下的类会被Robust插入代码,没有被Robust插入代码的类Robust是无法修复的-->
    <packname name="hotfixPackage">
        <name>包名</name>
    </packname>

    <!--不需要Robust插入代码的包名,Robust库不需要插入代码,如下的配置项请保留,还可以根据各个APP的情况执行添加-->
    <exceptPackname name="exceptPackage">
        <name>com.meituan.robust</name>
        <name>com.meituan.sample.extension</name>
    </exceptPackname>

    <!--补丁的包名,请保持和类PatchManipulateImp中fetchPatchList方法中设置的补丁类名保持一致( setPatchesInfoImplClassFullName("com.meituan.robust.patch.PatchesInfoImpl")),
    各个App可以独立定制,需要确保的是setPatchesInfoImplClassFullName设置的包名是如下的配置项,类名必须是:PatchesInfoImpl-->
    <patchPackname name="patchPackname">
        <name>cn.superh.patch</name>
    </patchPackname>

    <!--自动化补丁中,不需要反射处理的类,这个配置项慎重选择-->
    <noNeedReflectClass name="classes no need to reflect">

    </noNeedReflectClass>
</resources>

三、思路(需要结合项目的实际情况而定)

先说说我们项目中用的原理

首先,接口方面(和美团建议不一致,也没办法,不是我们写 ~ ),后台小伙伴把热修复接口信息,在每个接口中都会返回,啊~~ 这是要干嘛~,所以我是按这样接口返回来写的。

我们把本地的app版本号和补丁版本号在通过Heads传递给后台,来识别是否需要补丁信息。

1.在网络拦截器中,对response进行处理拦截,获取到热修复信息后,去下载。当然在下载的时候,肯定还有多个接口会返回信息,需要做下处理。

2.需要对修复完的版本,本地保存一份,并缓存版本号信息,下次启动需要加载。

3.补丁版本只能针对某一个大版本(app的版本),不能升级应用后,以前的补丁还应用了。

4.安全性的一些考虑。(目前我们只做了文件MD5验证,没有做加密的操作)

四、具体Demo

https://github.com/super-hu/hotfix_android

五、发布流程
正常发布apk
  1. 修改gradle.properties
isMakeHot=false
  1. 去除掉 之前的修复的bug文件含有 @Modify @Add 的注解(如果有)

  2. 保存好outputs/mapping/环境/mapping.txt、outputs/robust/robust.apkhash 文件


发布补丁

1.修改有bug的方法增加@Modify或新增方法或者类@Add

2.把之前保留的mapping.txt和robust.apkhash,复制到app项目下的robust目录

3.修改gradle.properties

isMakeHot=true

4.修改app目录下的robust配置开关(一般不用动,详细看注释)。

5.执行打包命令,最后会在outputs/robust 下生成patch.jar补丁文件,发布到服务器。


注意事项

1.打补丁文件,如果之前未对代码做混淆,需要自行创建mapping.txt(正式环境都是混淆的,可忽略)

如果你们的app没有使用proguard优化代码,那么一切处理起来都比较简单了,Robust插桩部分与Proguard没有依赖关系,所以Robust插桩部分可以放心使用,至于自动化嘛就需要做一些手脚了:

首先需要创建一个mapping.txt文件,请注意文件的命名哈,然后放到app/robust目录下
其他操作和使用说明中的操作一样,只不过需要你在mapping文件中加入几行,比如说我们需要对com.meituan.mainactivity这个类修改bug 需要在mapping文件添加如下代码:
com.meituan.mainactivity ->com.meituan.mainactivity:
                int field ->field
其中com.meituan.mainactivity就是你要修改的类,field是你类中的任一字段,类中的方法名不需要填写(包括修改的方法),mapping文件只能包含这两行,不能有多余的空行,多余空格也不行

2.支持的修复

支持方法级别的修复,支持静态方法
支持新增方法和类

3.不支持的修复

接口、无方法类、构造方法、抽象方法、native方法、synthetic方法等不插住代码

so不支持:

新增字段
修复构造方法
资源和 so 修复
返回值是 this 的方法支持不太好(需要看情况处理)
可能会出现深度方法内联导致的不可预知的错误(几率很小可以忽略)

4.TODO

没有安全校验,需要在加载补丁之前自己做验证

  • 初步是检验文件MD5值
  • 文件加密解密处理
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,830评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,992评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,875评论 0 331
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,837评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,734评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,091评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,550评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,217评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,368评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,298评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,350评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,027评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,623评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,706评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,940评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,349评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,936评论 2 341

推荐阅读更多精彩内容