美团热修复 Robust 方案接入(一)

声明:本文为博主原创文章,转载请注明出处:小嵩的博客

本系列传送门:
美团热修复 Robust 方案接入(一)
美团热修复 Robust 原理解析(二)

方案介绍

Robust是美团点评技术团队提供的Android热修复解决方案,基于Instant Run方案实现,属于方法级修复。Robust的补丁成功率高达99%,总体而言它是一个比较稳定的热修复方案,对于追求补丁稳定可靠的项目,接入Roubust是一个不错的选择。接下来我们介绍一下如何去接入Robust。

一、接入步骤:

1.1 在整个项目的build.gradle加入classpath:

 buildscript {
    repositories {
        jcenter()
    }
    dependencies {
         classpath 'com.meituan.robust:gradle-plugin:0.4.82'
         classpath 'com.meituan.robust:auto-patch-plugin:0.4.82'
   }
}

1.2 在App的build.gradle,应用robust插件, 然后加入compile依赖:

apply plugin: 'com.android.application'
//制作补丁时将下面这个apply打开,auto-patch-plugin紧跟着com.android.application
//apply plugin: 'auto-patch-plugin'
apply plugin: 'robust'
compile 'com.meituan.robust:robust:0.4.82'

注:最新版本以Robust 的 GitHub项目为准,地址:https://github.com/Meituan-Dianping/Robust

1.3 在app项目的src同级目录下配置一份robust.xml文件:

美团热修复 Robust 方案接入(一)_第1张图片

robust.xml配置文件详细内容:


<resources>

    <switch>
        
        
        <turnOnRobust>trueturnOnRobust>
        

        
        
        
        <manual>falsemanual>

        
        
        
        <forceInsert>falseforceInsert>

        
        <catchReflectException>truecatchReflectException>
        

        
        
        <patchLog>falsepatchLog>

        
        <proguard>trueproguard>
        

        
        <useAsm>trueuseAsm>
        
    switch>

    
    
    <packname name="hotfixPackage">
        <name>com.meituanname>
        <name>com.sankuainame>
        <name>com.dianpingname>
    packname>

    
    <exceptPackname name="exceptPackage">
        <name>com.meituan.robustname>
        <name>com.meituan.sample.extensionname>
    exceptPackname>

    
    <patchPackname name="patchPackname">
        <name>com.meituan.robust.patchname>
    patchPackname>

    
    <noNeedReflectClass name="classes no need to reflect">

    noNeedReflectClass>
resources>

通过以上三个步骤,我们就已经接入Robust,此时就可以正常进行开发工作了。

注意:
在基础包打包前需要在robust.xml配置文件中,设置我们项目需要被插桩的包名或者类名。若没有配置的话,在打补丁包编译时,添加了注解的方法会报以下异常:

Caused by: org.codehaus.groovy.GroovyException: patch method com.example.robust.MainActivity.initView() haven't insert code by Robust.Cannot patch this method, method.signature  ()V
        at com.meituan.robust.autopatch.ReadAnnotation.addPatchMethodAndModifiedClass(ReadAnnotation.groovy:134)
        at com.meituan.robust.autopatch.ReadAnnotation$_scanClassForModifyMethod_closure4.doCall(ReadAnnotation.groovy:85)
        at com.meituan.robust.autopatch.ReadAnnotation.scanClassForModifyMethod(ReadAnnotation.groovy:80)
        at com.meituan.robust.autopatch.ReadAnnotation$_readAnnotation_closure1.doCall(ReadAnnotation.groovy:36)
        ... 49 more

二、修复步骤

通过前面三个接入步骤,我们的APP已经接入了Robust。在打包上线时,会生成一份mapping文件(需要开启混淆规则才会有该文件)以及methodsMap.robust文件(build/output/robust目录下),此时我们需要保存好它,这两个文件在我们修复bug生成补丁包时需要用到。打包上线时的安装包我们称之为基础包,基础包里面的代码Robust已经在打包阶段通过插桩提供了代码修复的功能。

在想要修复bug时,我们需要做如下几个操作:

2.1 拷贝备份文件

在打基础包的时候,我们需要保存好mapping及methodsMap.robust文件,在打补丁包时,我们需要将之前保存的这两份文件 放置在app/robus/目录下以供Robust去对比两个版本的差异来生成补丁。

2.2 apply 补丁插件

在App的build.gradle下将之前注释掉的’auto-patch-plugin’插件给打开。

2.3 修改代码

改代码时,我们需要在改动的方法上面添加 @Modify 注解。对于Lambda表达式,则需要在修改过的方法里面调用RobustModify.modify()方法,普通方法也可以通过调用它来实现。

修复前方法代码:

private void initView() {
        Button btnFix = findViewById(R.id.btn_fix);
        btnFix.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

            }
        });
    }

修复后方法代码:

    @Modify
    private void initView() {
        Button btnFix = findViewById(R.id.btn_fix);
        btnFix.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

            }
        });
        btnFix.setBackgroundColor(ContextCompat.getColor(this,R.color.colorPrimary));
    }

新增方法需要添加@Add注解:

    @Add
    private void testAddMethod() {
     //do something
    }

2.4 生成补丁

改完代码后,运行和生成线上apk同样的命令,即可生成补丁,补丁目录app/build/outputs/robust/patch.jar

美团热修复 Robust 方案接入(一)_第2张图片
额… 补丁生成成功最后也是会显示build failed的。不过查找log,若出现如上输出,则代表补丁生成成功。

2.5 下发补丁

由于Robust并没有提供补丁平台,因此补丁下发的功能,需要自己和团队的后端去协商具体实现方案及策略。app的相关接入代码在PatchManipulateImp类中去实现,可参考官方的demo工程。

2.6 加载补丁

Robust入口代码:

new PatchExecutor(getApplicationContext(), new PatchManipulateImp(), new RobustCallBackSample()).start();

这个是自行控制的,一般来说需要尽早执行它。补丁加载完成后,运行到相关修复的代码时,则会走补丁包里面的代码逻辑。

这里需要注意的是,在补丁包未加载成功前就已经执行过的代码,是不会主动去触发替换逻辑的。虽然Robust不需要重启就能让补丁生效,但在加载补丁成功后,还是需要在下次执行到该方法时,才会触发执行补丁代码逻辑。并不是说打完补丁包后,所有修改过的代码逻辑都会立即替换。

总结

到这里我们已经接入Robust并可以通过它实现热修复的功能了。其中有很多细节需要我们注意,包括备份文件、方法注释、执行时机、补丁下发平台的实现流程及策略等。总体而言,如果不考虑增大apk的体积的话,只是简单的修复代码,不用修复so和资源,那么选择Robust是最稳定的。如果需要更全的功能,如so、资源更新等,那么目前来说选择Tinker是一个不错的方案。

通过这篇文章我们知道如何接入并去使用Robust了,但它的实现原理及精髓是什么呢? 秉着格物致知的精神,带着这个问题,下篇文章我们将会重点讲解一下Robust的实现原理及内部源码逻辑。文章链接:美团热修复 Robust 原理解析(二)

你可能感兴趣的:(Android,热修复,Android热修复系列)