1、添加依赖
a、在App的build.gradle,加入如下依赖
apply plugin: 'com.android.application'
//制作补丁时将这个打开,auto-patch-plugin紧跟着com.android.application
//apply plugin: 'auto-patch-plugin'
apply plugin: 'robust'
compile 'com.meituan.robust:robust:0.4.82'
b、在整个项目的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'
}
}
c、在项目的src同级目录下配置robust.xml文件,具体项请参考DEMOapp/robust.xml
2、生成patch
a、拷贝文件
一定要开启混淆,否则不会生成map文件;需要 被修改版本的两个文件mapping文件和methodsMap.robust;
然后拷贝两个文件mapping文件和methodsMap.robust到和build同级的bobust文件夹下;官网上有一个hash文件,测试下拉,是没有使用到的;
b、修改代码
在改动的方法上面添加@Modify
注解,对于Lambda表达式请在修改的方法里面调用RobustModify.modify()方法
@Modify
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
//或者是被修改的方法里面调用RobustModify.modify()方法
protected void onCreate(Bundle savedInstanceState) {
RobustModify.modify()
super.onCreate(savedInstanceState);
}
新增的方法和字段使用@Add
注解
//增加方法
@Add
public String getString() {
return "Robust";
}
//增加类
@Add
public class NewAddCLass {
public static String get() {
return "robust";
}
}
c、修改build文件
apply plugin: 'com.android.application'
//关闭'robust'并打开'auto-patch-plugin'
//apply plugin: 'robust'
apply plugin: 'auto-patch-plugin'
d、执行IDE中的编译apk文件操作,生成Patch
在build窗口中有上图提示 auto patch end successfully ,并且在build/outputs/robust/下有patch.jar就说明编译patch成功了;
3、使用patch
能使用patch必须在要修复的版本上能够该patch,在类中要调用
new PatchExecutor(getApplicationContext(), new PatchManipulateImp(), new RobustCallBackSample()).start();
其中 PatchManipulateImp是实现如何加载patch包括路径等问题;
RobustCallBackSample是演示加载成功失败等回调;
public class PatchManipulateImp extends PatchManipulate
package com.othershe.dutiltest;
import android.content.Context;
import android.os.Environment;
import android.util.Log;
import com.meituan.robust.Patch;
import com.meituan.robust.PatchManipulate;
import com.meituan.robust.RobustApkHashUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
/**
* Created by mivanzhang on 17/2/27.
*
* We recommend you rewrite your own PatchManipulate class ,adding your special patch Strategy,in the demo we just load the patch directly
*
* <br>
* Pay attention to the difference of patch's LocalPath and patch's TempPath
*
* <br>
* We recommend LocalPath store the origin patch.jar which may be encrypted,while TempPath is the true runnable jar
*<br>
*<br>
* 我们推荐继承PatchManipulate实现你们App独特的A补丁加载策略,其中setLocalPath设置补丁的原始路径,这个路径存储的补丁是加密过得,setTempPath存储解密之后的补丁,是可以执行的jar文件
* <br>
* setTempPath设置的补丁加载完毕即刻删除,如果不需要加密和解密补丁,两者没有啥区别
*/
public class PatchManipulateImp extends PatchManipulate {
private static final String TAG = "robust";
/***
* connect to the network ,get the latest patches
* l联网获取最新的补丁
* @param context
*
* @return
*/
@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.othershe.dutiltest.patch.PatchesInfoImpl");
List patches = new ArrayList<Patch>();
patches.add(patch);
return patches;
}
/**
*
* @param context
* @param patch
* @return
*
* you can verify your patches here
*/
@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 {
Log.w(TAG, "verifyPatch LocalPath: "+patch.getLocalPath() );
Log.w(TAG, "verifyPatch TempPath : "+patch.getTempPath() );
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();
}
}
/**
*
* @param patch
* @return
*
* you may download your patches here, you can check whether patch is in the phone
*/
@Override
protected boolean ensurePatchExist(Patch patch) {
return true;
}
}
package com.othershe.dutiltest;
import android.util.Log;
import com.meituan.robust.Patch;
import com.meituan.robust.RobustCallBack;
import java.util.List;
/**
* Created by hedingxu on 17/11/26.
*/
public class RobustCallBackSample implements RobustCallBack {
@Override
public void onPatchListFetched(boolean result, boolean isNet, List<Patch> patches) {
Log.d("RobustCallBack", "onPatchListFetched result: " + result);
Log.d("RobustCallBack", "onPatchListFetched isNet: " + isNet);
for (Patch patch : patches) {
Log.d("RobustCallBack", "onPatchListFetched patch: " + patch.getName());
}
}
@Override
public void onPatchFetched(boolean result, boolean isNet, Patch patch) {
Log.d("RobustCallBack", "onPatchFetched result: " + result);
Log.d("RobustCallBack", "onPatchFetched isNet: " + isNet);
Log.d("RobustCallBack", "onPatchFetched patch: " + patch.getName());
}
@Override
public void onPatchApplied(boolean result, Patch patch) {
Log.d("RobustCallBack", "onPatchApplied result: " + result);
Log.d("RobustCallBack", "onPatchApplied patch: " + patch.getName());
}
@Override
public void logNotify(String log, String where) {
Log.d("RobustCallBack", "logNotify log: " + log);
Log.d("RobustCallBack", "logNotify where: " + where);
}
@Override
public void exceptionNotify(Throwable throwable, String where) {
Log.e("RobustCallBack", "exceptionNotify where: " + where, throwable);
}
}
以上所有的都是从官网上查到的,只是加了自己的一些理解;