一、热修复技术种类
技术对比
二、AndFix的基本介绍
集成阶段:
1、在gradle中添加依赖
2、在代码中完成初始化builde.gradle
MyApplication
AndFixPatchManager
准备阶段:
1、首先我们先builde一个有bug的old.apk安装到手机
2、分析bug并解决bug,builde一个new的apk(需要签名打包的apk不要debug,自行解决)
有bug的代码:
public class MainActivity extends AppCompatActivity {
private static final String FILE_END = ".apatch";
private String patchDir;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//创建文件路径
patchDir = getExternalCacheDir().getAbsolutePath() + "/apatch/";
//创建文件夹
File file = new File(patchDir);
//判断文件夹是否存在
if (file == null || !file.exists()) {
//不存在就创建
file.mkdir();
}
}
public void createBug(View view) {
//打印log信息为null,应用闪退
Utils.printLog();
}
public void fixBug(View view) {
AndFixPatchManager.getInstance().addPatch(getPathName());
}
//构建Patch文件名
private String getPathName() {
return patchDir.concat("smile").concat(FILE_END);
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.smile.mydemotwo.activity.MainActivity">
<Button
android:layout_width="88dp"
android:layout_height="50dp"
android:text="产生bug"
android:onClick="createBug"
tools:layout_editor_absoluteY="0dp"
tools:layout_editor_absoluteX="8dp"
android:layout_margin="10dp"/>
<Button
android:layout_width="88dp"
android:layout_height="50dp"
android:text="修复bug"
android:onClick="fixBug"
tools:layout_editor_absoluteY="0dp"
tools:layout_editor_absoluteX="8dp"
android:layout_margin="10dp"/>
</LinearLayout>
Patch生成阶段:
1、apkpatch命令及参数详解
1、先下载apkpatch工具工具
解压
-f:new.apk的文件路径
-t:是有bug的apk文件的路径
-o:是输出补丁包文件的目录
-k:是签名文件的路径
-p:是签名文件的密码
-a :是签名文件的别名
-e:是签名文件别名的密码2、使用apkpatch命令生成apkpatch包
Patch安装阶段:
将补丁文件通过adb push放入到指定目录(开发中都是下载到指定目录)
点击修复bug按钮,加载补丁文件
再次启动应用,点击创建bug按钮,此时应用不会闪退,并弹出Toast到这基本就完成了更新
总结阶段:
1、实际中不可能用adb push导入补丁,应该是下载
2、能否将AndFix模块组件化,为以后复用将AndFix组件化
AndFixPatchManager :
public class AndFixPatchManager {
private static AndFixPatchManager mInstance = null;
private static PatchManager mPatchManager = null;
private AndFixPatchManager() {
}
public static AndFixPatchManager getInstance() {
if (mInstance == null) {
synchronized (AndFixPatchManager.class) {
if (mInstance == null) {
mInstance = new AndFixPatchManager();
}
}
}
return mInstance;
}
//初始化AndFix方法
public void initPatch(Context context) {
mPatchManager = new PatchManager(context);
mPatchManager.init(Utils.getVersionName(context));
mPatchManager.loadPatch();
}
//加载我们的patch文件,参数patch文件的路径
public void addPatch(String path) {
try {
if (mPatchManager != null) {
mPatchManager.addPatch(path);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
AndFixService
public class AndFixService extends Service {
private static final int UPDATE_PATCH = 0x02;
private static final int DOWNLOAD_PATCH = 0x01;
private static final String FILE_END = ".apatch";
//存放Patch文件的目录
private String mPatchFileDir;
//存放Patch文件
private String mPatchFile;
//消息转发
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case UPDATE_PATCH:
checkPatchUpdate();
break;
case DOWNLOAD_PATCH:
downloadPatch();
break;
}
}
};
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
//初始化
init();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
mHandler.sendEmptyMessage(UPDATE_PATCH);
//这个返回值如果被系统回收之后不会被系统重启
return START_NOT_STICKY;
}
//完成文件目录的构造
private void init() {
mPatchFileDir = getExternalCacheDir().getAbsolutePath() + "/apatch/";
File file = new File(mPatchFileDir);
try {
if (file == null || !file.exists()) {
file.mkdir();
}
} catch (Exception e) {
e.printStackTrace();
stopSelf();
}
}
//检查是否有新的patch文件
private void checkPatchUpdate() {
//网络请求,失败停止服务
}
private void downloadPatch() {
//网络请求,失败停止服务
mPatchFile = mPatchFileDir.concat(System.currentTimeMillis() + "").concat(FILE_END);
}
}