robust是美团开发的一套热更新方案,它是基于Instant Run原理开发的一套新框架,相比于Tinker这种改变DexElements加载顺序的方式只能重启生效,robust实现了对代码修改的实时生效(热插拔)。下面来说说Robust的使用。
1.添加依赖
在project中的build.gralde中添加依赖
dependencies {
classpath 'com.android.tools.build:gradle:3.3.2'
//编译apk使用使用
classpath 'com.meituan.robust:gradle-plugin:0.4.90'
//打更新包时使用
classpath 'com.meituan.robust:auto-patch-plugin:0.4.90'
}
在app的build.gradle中添加依赖
apply plugin: 'robust'
//当需要打更新包的时候打开
//apply plugin: 'auto-patch-plugin'
....
implementation 'com.meituan.robust:robust:0.4.90'
2.配置robust.xml
robust使用的时候需要配置一个robust.xml的配置文件,和src目录同级。
<?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>-->
</switch>
<!--需要热补的包名或者类名,这些包名下的所有类都被会插入代码-->
<!--这个配置项是各个APP需要自行配置,就是你们App里面你们自己代码的包名,
这些包名下的类会被Robust插入代码,没有被Robust插入代码的类Robust是无法修复的-->
<packname name="hotfixPackage">
<name>com.app.motion.robustmotion</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>com.app.motion.robustmotion.patch</name>
</patchPackname>
<!--自动化补丁中,不需要反射处理的类,这个配置项慎重选择-->
<noNeedReflectClass name="classes no need to reflect">
</noNeedReflectClass>
</resources>
这里需要配置的主要是两个节点,hotfixpackage
和patchpackname
。hotfixpackage
元素用于标识需要进行热更新类所属的包,也就是在这个包下面的类才可以进行热更新,否则不能。patchpackname
用于标识配置更新包的包名,可以取任意的名字。
3.主体代码
demo的布局比较简单,只有两个button,一个用于加载更新包,一个用于跳转到SecondActivity。
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button mBtnLoadPatch;
private Button mBtnSecond;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBtnLoadPatch = this.findViewById(R.id.btn_loadpatch);
mBtnSecond = this.findViewById(R.id.btn_second);
mBtnLoadPatch.setOnClickListener(this);
mBtnSecond.setOnClickListener(this);
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0x001);
}
@Override
public void onClick(View view) {
if (view.getId() == R.id.btn_loadpatch) {
new PatchExecutor(getApplicationContext(), new PatchManipulateImp(), new Callback()).start();
}
if (view.getId() == R.id.btn_second) {
startActivity(new Intent(this, SecondActivity.class));
}
}
}
class PatchManipulateImp extends PatchManipulate {
@Override
protected List<Patch> fetchPatchList(Context context) {
Patch patch = new Patch();
patch.setName("123");
//设置pacth包的地址
patch.setLocalPath(Environment.getExternalStorageDirectory().getPath() + File.separator + "robust" + File.separator + "patch.jar");
patch.setTempPath(Environment.getExternalStorageDirectory().getPath() + File.separator + "robust" + File.separator + "patch");
//这个包必须和patchpackname设置的要一致,patchpackname + '.pachesInfoImpl'
patch.setPatchesInfoImplClassFullName("com.app.motion.robustmotion.patch.PatchesInfoImpl");
List patches = new ArrayList<Patch>();
patches.add(patch);
return patches;
}
@Override
protected boolean verifyPatch(Context context, Patch patch) {
return true;
}
@Override
protected boolean ensurePatchExist(Patch patch) {
return true;
}
}
class Callback implements RobustCallBack {
@Override
public void onPatchListFetched(boolean result, boolean isNet, List<Patch> patches) {
}
@Override
public void onPatchFetched(boolean result, boolean isNet, Patch patch) {
}
@Override
public void onPatchApplied(boolean result, Patch patch) {
}
@Override
public void logNotify(String log, String where) {
}
@Override
public void exceptionNotify(Throwable throwable, String where) {
}
}
SecondActivity.java
public class SecondActivity extends AppCompatActivity {
private TextView mTextView;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.activity_second);
mTextView = this.findViewById(R.id.tv_content);
mTextView.setText(getContentString());
}
private String getContentString() {
String result = "hello world";
return result;
}
}
使用命令打release包,注意robust只用在打release包时候才有效。gradlew clean assembleRelease
4.打补丁包
现在需要对SecondActivity进行一些修改
public class SecondActivity extends AppCompatActivity {
private TextView mTextView;
@Override
@Modify
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.activity_second);
mTextView = this.findViewById(R.id.tv_content);
//修改内容
mTextView.setText(getNewContent());
}
private String getContentString() {
String result = "hello world";
return result;
}
@Add
private String getNewContent() {
return "hello my robust";
}
}
比较重要的地方是,对于新增的方法需要使用@Add
注解标记,对于引用的方法也需要使用@Modify
注解标记.
然后需要将第一次打包之后生成的outputs/mapping/release/mapping.txt和outputs/robust/methodsMap.robust两个文件复制到src同目录下的robust目录下(没有新建一个)。
最后一步是打开app的build.gradle中的生成patch的插件。
apply plugin: 'com.android.application'
//apply plugin: 'robust'
apply plugin: 'auto-patch-plugin'
使用命令重新打包一次,gradlew assembleRelease
Execution failed for task ':app:transformClassesWithAutoPatchTransformForRelease'.
> auto patch end successfully
打包失败也不要紧,只要有auto patch end successfully
显示表示patch包打包成功
现在只需要把outputs/robust/patch.jar复制到指定的目录即可adb push E:\github_workspace\RobustMotion\app\build\outputs\robust\patch.jar /sdcard/robust/patch_temp.jar
demo代码地址:https://gitee.com/devnew/Robu...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。