美团Robust热更新

官方Github:https://github.com/Meituan-Dianping/Robust

0、前言

    网上关于robust使用的帖子很多,大部分帖子都会忽略某些细节,在没有搞明白robust原理的情况下,往往因为这些细节,导致热更新失败。我在用robust时也是各种碰壁,在此总结和重新梳理robust的应用流程。

1、总体流程

如果我们要写一个robust的demo,实现热更新功能,应该分下面几个步骤。

第一步:写一个有“bug”的demo

第二步:开启热更新,修改代码,

第三步:生成和部署jar包

第四步:测试热更新效果。

2、分步实现

    这里分步实现各个流程。follow me!

2.1、写一个有“bug”的demo

(1)声明权限

首先的首先是建一个android工程,然后声明权限。

    Robust需要在AndroidManifest中声明如下权限(如图1-0)

美团Robust热更新_第1张图片
图1-0

(2)app的gradle文件中引入依赖

apply plugin:'com.android.application'

//apply plugin: 'auto-patch-plugin'(热更新代码后要开启这行,并注释掉下面那行

apply plugin:'robust'

compile'com.meituan.robust:robust:0.4.5'

美团Robust热更新_第2张图片
图-1-1
美团Robust热更新_第3张图片
图-1-2

(3)工程的gradle文件加入classpath

classpath 'com.meituan.robust:gradle-plugin:0.4.5'

classpath 'com.meituan.robust:auto-patch-plugin:0.4.5'


美团Robust热更新_第4张图片
图1-3

(4)手动增加和修改robust.xml文件

注意事项:

1、robust.xml文件和src是同级目录,如下图1-4

美团Robust热更新_第5张图片
图-1-4

2、xml文件是从上面官方github的demo中拷贝过来的。这个xml是热更新的一个配置文件。

3、修改robust.xml文件

一般来说只需要修改三个地方,如下图1-5.

美团Robust热更新_第6张图片
图1-5
美团Robust热更新_第7张图片
图1-6

(5)写demo

用三个class文件(分别是:MainActivity.class, SecondActiviry.class, PatchManipulateImp.class)来写一个简单的demo。

【MainActivity.class】

package com.gzyct.myapplication;

public class MainActivity extends AppCompatActivity {

protected Button load;

protected Button skip;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

super.setContentView(R.layout.main);

initView();

}

/**

*初始化界面

*/

private void initView() {

// 加载patch

load= (Button) findViewById(R.id.load);

load.setOnClickListener(newView.OnClickListener() {

@Override

public voidonClick(View v) {

newPatchExecutor(getApplicationContext(),newPatchManipulateImp(),newcallBack()).start();

}

});

// 页面跳转

skip= (Button) findViewById(R.id.skip);

skip.setOnClickListener(newView.OnClickListener() {

@Override

public voidonClick(View v) {

Intent intent =newIntent(MainActivity.this, SecondActivity.class);

startActivity(intent);

}

});

}

private class callBack  implements RobustCallBack {

@Override

public void onPatchListFetched(booleanresult,booleanisNet, List patches) {

// TODO

}

@Override

public void onPatchFetched(booleanresult,booleanisNet, Patch patch) {

// TODO

}

@Override

public void onPatchApplied(booleanresult, Patch patch) {

// TODO

}

@Override

public void logNotify(String log, String where) {

// TODO

}

@Override

public void exceptionNotify(Throwable throwable, String where) {

// TODO

}

}

}

[MainActivity的UI图]


美团Robust热更新_第8张图片
图1-7

【PatchManipulateImp.class文件代码】

这段代码中要重载三个函数:

protectedList fetchPatchList(Context context)

protected booleanverifyPatch(Context context, Patch patch)

protected booleanensurePatchExist(Patch patch)

.fetchPatchList是作用什么用?

1、保存原始jar包存储的路径以及设置运行的jar包

.verifyPatch做什么用?

you can verify your patches here。官方demo的解释


package com.gzyct.myapplication;

import android.content.Context;

import android.os.Environment;

import com.meituan.robust.Patch;

import com.meituan.robust.PatchManipulate;

importjava.io.File;

importjava.util.ArrayList;

importjava.util.List;

/**

* Created by gt on 2017/11/15.

*/

public class PatchManipulateImp  extends  PatchManipulate {

@Override

protected List 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);

Patch patch =newPatch();

patch.setName("123");

//we recommend LocalPath store the origin patch.jar which may be encrypted,while TempPath is the true runnable jar

// 下面的robust是生成补丁后,存在在手机的robust文件夹在中。如果你改成qwe,生成的补丁就放在qwe文件夹中。所以部署jar包到手机的时候,相关adb命令的参数和这里要对应上。

patch.setLocalPath(Environment.getExternalStorageDirectory().getPath() + File.separator+"robust"+ File.separator+"patch.jar");

patch.setTempPath(Environment.getExternalStorageDirectory().getPath() + File.separator+"robust"+ File.separator+"patch");

//setPatchesInfoImplClassFullName的包名是图1-5第三个红色框中的包名+PatchesInfoImpl, 这样robust可以通过xml文件找到当前类

patch.setPatchesInfoImplClassFullName("com.gzyct.myapplication.PatchesInfoImpl");

List patches =newArrayList();

patches.add(patch);

returnpatches;

}

@Override

protected booleanverifyPatch(Context context, Patch patch) {

return true;

}

@Override

protected booleanensurePatchExist(Patch patch) {

return true;

}

}

【SecondActivity.class的代码】

public class  SecondActivity  extends  Activity {

@Override

protected void onCreate(@NullableBundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.second);

title= (TextView) findViewById(R.id.title);

title.setText("hello , this is patched activity,and patch is success-13231313131123441412---");

title.setOnClickListener(newView.OnClickListener() {

@Override

public void onClick(View v) {

Toast.makeText(getApplicationContext(),"asfawdfawf", Toast.LENGTH_LONG).show();

}

});

init();

}

TextViewtitle;

private voidinitView() {

title= (TextView) findViewById(R.id.title);

title.setText("hello , this is patched activity");

}

【SecondActivity.classUI图】

美团Robust热更新_第9张图片
图1-8

至此一个有“bug”的demo就写完了。

写完代码后,开始打包,下面将介绍如何打包以及热更新的准备工作。


2.2 打包


.(1)开启混淆

在app的gradle文件中开发混淆

美团Robust热更新_第10张图片
图1-9

.(2)打包

可以通过命令方式或者传统方式打包。(我是用传统方式打包滴)

.通过命令打包

gradlew clean  assembleRelease --stacktrace --no-daemon

美团Robust热更新_第11张图片
图1-10

.传统方式打包

美团Robust热更新_第12张图片
图1-11

.2.3、开始热更新和修改代码

开启热更新前,有些准备工作要做,如下

(1)准备工作

.新建robust文件夹

src的同级目录新建robust文件夹


美团Robust热更新_第13张图片
图1-12

.拷贝上面红线的文件到robust文件夹

在打包后(借用人家的图),在output下面将这几个文件夹拷贝到刚才我们新建的robust文件夹中。


美团Robust热更新_第14张图片
图1-13


美团Robust热更新_第15张图片
图1-14

(2)开启“热更新模式”

在app的gradle文件中,修改配置,入下图1-15,注释掉第三行,并开启第二行,和写bug代码时刚好相反。

图1-15

(3)修改“bug”

在secondactivity.class中修改“bug”

美团Robust热更新_第16张图片
图1-16

2.4、生成和部署补丁包

(1)生成补丁包

补丁包可以通过命令生成,也可以用传统的签名打包方式生成。这里介绍用命令方式生成补丁,具体如下:

通过命令:gradlew clean  assembleRelease --stacktrace --no-daemon生成补丁(如下图1-17):

美团Robust热更新_第17张图片
图 1-17

执行结束后,出现BUILD FAILED,没有关系。只要patch end successfully就ok啦!~~(图下图1-18)

美团Robust热更新_第18张图片
图1-18

        接下来,我们可以发现:在app->build->output->robust目录下生成patch.jar以及patch.dex两个文件(如下图1-19)。

美团Robust热更新_第19张图片
图1-19

(2)热更新部署

 上面的patch.jar是我们需要的热更新文件。通过adb命令将jar包传到手机(如下图1-20)

图1-20

用adb将jar传到手机时可能会遇到几个坑。

坑1

报错:Unable to create Debug Bridge: Unable to start adb server: error: could not install *smartsocket* listener: cannot bind to 127.0.0.1:5037: 通常每个套接字地址(协议/网络地址/端口)只允许使用一次。

原因:端口被占用

解决办法:

step1、通过netstat -aon|findstr “5037” 找出占用5037端口号的对应pid号。

step2、通过任务管理器kill进程

step3:重启adb


图1-21

坑2

报错:no device *** command ***

没有安装手机驱动:(

4、测试


美团Robust热更新_第20张图片
T 1-21


美团Robust热更新_第21张图片
T1-22


在没有load patch,直接skip new activity时的UI如下:


美团Robust热更新_第22张图片
T1-23

load patch之后


美团Robust热更新_第23张图片
T1-24

测试结论:

热更新成功

你可能感兴趣的:(美团Robust热更新)