美文网首页优秀文章搜集
robust 热修复实践

robust 热修复实践

作者: suphu | 来源:发表于2018-06-29 15:46 被阅读22次
    一、导入项目

    在项目根目录的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值
    • 文件加密解密处理

    相关文章

      网友评论

        本文标题:robust 热修复实践

        本文链接:https://www.haomeiwen.com/subject/ljrayftx.html