欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

美团Robust热修复工具使用记录

程序员文章站 2022-04-12 19:30:09
配置项project的gradle文件中添加两个插件dependencies { classpath 'com.android.tools.build:gradle:3.2.0'//美团robust classpath 'com.meituan.robust:gradle-plugin:0.4.99' classpath 'com.meituan.robust:auto-patch-plugin:0.4.99' }app的gradle文件...

配置项

project的gradle文件中添加两个插件

dependencies {
        classpath 'com.android.tools.build:gradle:3.2.0'
		//美团robust
        classpath 'com.meituan.robust:gradle-plugin:0.4.99'
        classpath 'com.meituan.robust:auto-patch-plugin:0.4.99'
    }

app的gradle文件中添加依赖

需要生成apk发布版本的时候,把apply plugin: 'auto-patch-plugin’注释掉,这个插件是生成patch用的。

dependencies {
    apply plugin: 'com.android.application'
    //生成补丁
    apply plugin: 'auto-patch-plugin'
    apply plugin: 'robust'
    implementation 'com.meituan.robust:robust:0.4.99'
}

下载robust的Demo

美团的demo
demo\app中的robust文件夹(内容不需重要)和robust.xml拷贝到自己app对应目录下
美团Robust热修复工具使用记录

robust.xml的配置

<?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>false</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>-->

        <!--针对Java8级别的Lambda表达式,编译为private级别的javac函数,此时由开发者决定是否进行插桩处理-->
        <forceInsertLambda>true</forceInsertLambda>
<!--        <forceInsertLambda>false</forceInsertLambda>-->
    </switch>

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

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

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

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

    </noNeedReflectClass>
</resources>

重点配置节点

	//打开关闭robust
	<turnOnRobust>true</turnOnRobust>
	//关闭混淆,这个设置成true就需要在app/robust下面放mapping.txt
	<proguard>false</proguard>
	//debug版打开robust,在turnOnRobust节点配置成true时才有效
	<forceInsert>false</forceInsert>
	 
	//这个节点配置需要热更新的包,也就是自己项目的包
	<packname name="hotfixPackage">
        <name>com.test.robust</name>
    </packname>
	//这个节点配置不需要热更新的包,第三方包或者确定不会出bug的包
	<exceptPackname name="exceptPackage">
    </exceptPackname>
    //可以不动
    <patchPackname name="patchPackname">
        <name>com.meituan.robust.patch</name>
    </patchPackname>
    

把PatchManipulateImp、RobustCallBackSample两个类拷到自己app中

PatchManipulateImp类

public class PatchManipulateImp extends PatchManipulate {
  
    @Override
    protected List<Patch> fetchPatchList(Context context) {
        //将app自己的robustApkHash上报给服务端,服务端根据robustApkHash来区分每一次apk build来给app下发补丁
        //apkhash is the unique identifier for  apk,so you cannnot patch wrong apk.
        String robustApkHash = RobustApkHashUtils.readRobustApkHash(context);
        Log.w("robust","robustApkHash :" + robustApkHash);
        //connect to network to get patch list on servers
        //在这里去联网获取补丁列表
        Patch patch = new Patch();
        patch.setName("123");
        //we recommend LocalPath store the origin patch.jar which may be encrypted,while TempPath is the true runnable jar
        //LocalPath是存储原始的补丁文件,这个文件应该是加密过的,TempPath是加密之后的,TempPath下的补丁加载完毕就删除,保证安全性
        //这里面需要设置一些补丁的信息,主要是联网的获取的补丁信息。重要的如MD5,进行原始补丁文件的简单校验,以及补丁存储的位置,这边推荐把补丁的储存位置放置到应用的私有目录下,保证安全性
        patch.setLocalPath(Environment.getExternalStorageDirectory().getPath()+ File.separator+"robust"+File.separator + "patch");

        //setPatchesInfoImplClassFullName 设置项各个App可以独立定制,需要确保的是setPatchesInfoImplClassFullName设置的包名是和xml配置项patchPackname保持一致,而且类名必须是:PatchesInfoImpl
        //请注意这里的设置
        patch.setPatchesInfoImplClassFullName("com.meituan.robust.patch.PatchesInfoImpl");
        List patches = new ArrayList<Patch>();
        patches.add(patch);
        return patches;
    }

  
    @Override
    protected boolean verifyPatch(Context context, Patch patch) {
        //do your verification, put the real patch to patch
        //放到app的私有目录
        patch.setTempPath(context.getCacheDir()+ File.separator+"robust"+File.separator + "patch");
        //in the sample we just copy the file
        try {
            copy(patch.getLocalPath(), patch.getTempPath());
        }catch (Exception e){
            e.printStackTrace();
            throw new RuntimeException("copy source patch to local patch error, no patch execute in path "+patch.getTempPath());
        }

        return true;
    }
    public void copy(String srcPath, String dstPath) throws IOException {
        File src=new File(srcPath);
        if(!src.exists()){
            throw new RuntimeException("source patch does not exist ");
        }
        File dst=new File(dstPath);
        if(!dst.getParentFile().exists()){
            dst.getParentFile().mkdirs();
        }
        InputStream in = new FileInputStream(src);
        try {
            OutputStream out = new FileOutputStream(dst);
            try {
                // Transfer bytes from in to out
                byte[] buf = new byte[1024];
                int len;
                while ((len = in.read(buf)) > 0) {
                    out.write(buf, 0, len);
                }
            } finally {
                out.close();
            }
        } finally {
            in.close();
        }
    }
  
    @Override
    protected boolean ensurePatchExist(Patch patch) {
        return true;
    }
}

RobustCallBackSample

RobustCallBackSample加载patch的一些回调,暂时不需要改动。

生成apk

前期准备工作做好,假设我们要发布一个app它安装了robust框架。

  1. 首先吧apply plugin: 'auto-patch-plugin’注释掉
dependencies {
    apply plugin: 'com.android.application'
    //生成补丁
    //apply plugin: 'auto-patch-plugin'
    apply plugin: 'robust'
    implementation 'com.meituan.robust:robust:0.4.99'
}
  1. 添加加载补丁代码,我在Application中调用,这个方法是异步加载的,一定要确保在出现bug之前的地方能加载完成,越早调用越好。
new PatchExecutor(getApplicationContext(), new PatchManipulateImp(), new RobustCallBackSample()).start();
  1. 我们假设某个方法出现了bug
public class BugActivity extends Activity{
	 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setText();
    }

	private void setText(){
		 ((TextView)findViewById(R.id.text)).setText("bug");
	}
}
  1. 生成apk,安装
    美团Robust热修复工具使用记录

生成补丁

  1. 修改bug
	@Modify
    public void setText(){
        ((TextView)findViewById(R.id.text)).setText("修复bug");
    }
  1. 打开apply plugin: ‘auto-patch-plugin’
dependencies {
    apply plugin: 'com.android.application'
    //生成补丁
    apply plugin: 'auto-patch-plugin'
    apply plugin: 'robust'
    implementation 'com.meituan.robust:robust:0.4.99'
}
  1. 把生成apk时outputs里的methodsMap.robust文件拷贝到app/robust目录中
    美团Robust热修复工具使用记录
  2. 生成apk,在build到一半的时候会报错,出现这句表示补丁生成成功了
    美团Robust热修复工具使用记录
    美团Robust热修复工具使用记录
    在android studio terminal中输入命令,把patch.jar传到手机中
adb push app/build/outputs/robust/patch.jar /sdcard/robust/patch.jar

重新进入应用,bug修复成功
美团Robust热修复工具使用记录

本文地址:https://blog.csdn.net/qq_44381427/article/details/107531878

相关标签: Adnroid解决方案