一、概述

当一个产品上线后,如果出现了bug,传统的方式是,收集bug,修复,重新发布新版本。这样用户还得重新下载apk,在这介绍的是不用重新安装apk修复bug,这样的技术就称之为热修复技术。

二、热修复原理

principle.png

至于更加具体的原理,请点击这里https://github.com/alibaba/AndFix

三、实现步骤

1、生成补丁包

假如我们收到了用户上传的崩溃信息,我们改完需要修复的Bug,这个时候就会有一个新的的apk我们就叫它为new.apk,原来的那个有Bug的apk你也有我们就叫它old.apk。这个时候我们就可以利用阿里github上面提供的工具生成一个xxxx.apatch包用于修复Bug。

1.命令是:apkpatch.bat -f -t -o -k -p -a -e

2.-f : 没有Bug的新版本apk

3.-t : 有bug的旧版本apk

4.-o : 生成的补丁文件所放的文件夹

5.-k : 签名打包密钥

6.-p : 签名打包密钥密码

7.-a : 签名密钥别名

8.-e : 签名别名密码(这样一般和密钥密码一致)

2、通过补丁包修复bug

怎么获取apatch包呢?我们肯定是请求接口获取下载我们的修复好的apatch包,下载下来之后我们就可以调用方法进行修复了,我们可以暂时放在本地测试一下,在进行这步之前添加依赖https://github.com/alibaba/AndFix,这些代码肯定之前就得写好:

public class BaseApplication extends Application {

// Patch管理类

public static PatchManager mPatchManager;

@Override

public void onCreate() {

super.onCreate();

// 捕捉崩溃信息

ExceptionCrashHandler.getInstance().init(this);

// Ali热修复

try {

mPatchManager = new PatchManager(this);

// 初始化patch版本

String pkName = this.getPackageName();

String versionName = getPackageManager().getPackageInfo(pkName, 0).versionName;

// 初始化版本名称

mPatchManager.init(versionName);

// 加载之前的patch

mPatchManager.loadPatch();

} catch (PackageManager.NameNotFoundException e) {

e.printStackTrace();

}

}

}

public class MainActivity extends BaseSkinActivity {

@Override

protected void initData() {

// 获取上次的崩溃信息

File crashFile = ExceptionCrashHandler.getInstance().getCrashFile();

// 上传到服务器,后面再说.......

}

@Override

protected void initView() {

}

@Override

protected void setContentView() {

setContentView(R.layout.activity_main);

}

@Override

protected void initTitle() {

}

@Onclick(R.id.test)

public void test(View view) {

// 没有修复之前会报异常闪退

Toast.makeText(this, Utils.test(), Toast.LENGTH_LONG).show();

}

@Onclick(R.id.ali_fix)

public void aliHotFix(View view) {

try {

// 测试 目前暂且放在本地

String patchFileString = Environment.getExternalStorageDirectory()+"/fix.apatch";

Log.e("TAG", patchFileString);

// 修复apatch,不需要重启可立即生效

BaseApplication.mPatchManager.addPatch(patchFileString);

Toast.makeText(this, "Bug修复成功", Toast.LENGTH_LONG).show();

} catch (Exception e) {

e.printStackTrace();

Toast.makeText(this, "Bug修复失败", Toast.LENGTH_LONG).show();

}

}

}

3、底层原理

把fix.aptach包解压反编译里面的dex文件

Paste_Image.png

可见它其实是把两个apk进行比较然后找出里面不一样的方法,然后打成一个xxx..aptach包其实就是一个压缩文件,我们究竟怎么去获取dex里面的所有方法呢?解压后其实里面还有一个很重要的文件META-INF\PATCH.MF文件:

Manifest-Version: 1.0

Patch-Name: new

Created-Time: 13 Feb 2017 08:19:23 GMT

From-File: new.apk

To-File: old.apk

Patch-Classes:

// 所有的类都会在这里,有多个就会显示多个,需要用java代码把他解析出来拿到这个内容......

com.example.administrator.exceptioncrashhandler.Utils_C

F

Created-By: 1.0 (ApkPatch)

BaseApplication.mPatchManager.addPatch(patchFileString)这里面的Java代码中修改过的代码被加上一个注解:

Paste_Image.png

底层的修复c代码实现:

static void replaceMethod(JNIEnv* env, jclass clazz, jobject src,

jobject dest) {

if (isArt) {

art_replaceMethod(env, src, dest);

} else {

dalvik_replaceMethod(env, src, dest);

}

}

由于Android4.4后才用的Art虚拟机,之前的系统都是Dalvik虚拟机,因此Natice层写了2个方法,对不同的系统做不同的处理方式,我就只贴Dalvik部分了都类似,只不过Art需要版本判断不同Api的版本有所不同。

extern jboolean __attribute__ ((visibility ("hidden"))) dalvik_setup(

JNIEnv* env, int apilevel) {

// libdvm.so 加载系统的so库,视频里我们再去看一张图

void* dvm_hand = dlopen("libdvm.so", RTLD_NOW);

if (dvm_hand) {

dvmDecodeIndirectRef_fnPtr = dvm_dlsym(dvm_hand,

apilevel > 10 ?

"_Z20dvmDecodeIndirectRefP6ThreadP8_jobject" :

"dvmDecodeIndirectRef");

if (!dvmDecodeIndirectRef_fnPtr) {

return JNI_FALSE;

}

dvmThreadSelf_fnPtr = dvm_dlsym(dvm_hand,

apilevel > 10 ? "_Z13dvmThreadSelfv" : "dvmThreadSelf");

if (!dvmThreadSelf_fnPtr) {

return JNI_FALSE;

}

jclass clazz = env->FindClass("java/lang/reflect/Method");

jClassMethod = env->GetMethodID(clazz, "getDeclaringClass",

"()Ljava/lang/Class;");

return JNI_TRUE;

} else {

return JNI_FALSE;

}

}

extern void __attribute__ ((visibility ("hidden"))) dalvik_replaceMethod(

JNIEnv* env, jobject src, jobject dest) {

jobject clazz = env->CallObjectMethod(dest, jClassMethod);

ClassObject* clz = (ClassObject*) dvmDecodeIndirectRef_fnPtr(

dvmThreadSelf_fnPtr(), clazz);

clz->status = CLASS_INITIALIZED;

Method* meth = (Method*) env->FromReflectedMethod(src);

Method* target = (Method*) env->FromReflectedMethod(dest);

LOGD("dalvikMethod: %s", meth->name);

// meth->clazz = target->clazz;

meth->accessFlags |= ACC_PUBLIC;

meth->methodIndex = target->methodIndex;

meth->jniArgInfo = target->jniArgInfo;

meth->registersSize = target->registersSize;

meth->outsSize = target->outsSize;

meth->insSize = target->insSize;

meth->prototype = target->prototype;

meth->insns = target->insns;

// 准确的说不能算是修复只能说是指向已修复的方法

meth->nativeFunc = target->nativeFunc;

}

最后,使用该方法修复bug需要注意的几点:

1.每次生成之后一定要测试;

2.尽量的不要分包,不要分多个dex

3.混淆的时候,设计到NDK AndFix.java 不要混淆

4.生成包之后一般会加固什么的,这个时候生成的差分包,一定要在之前去生成。

5.既然是去修复方法,第一个不能增加成员变量,不能增加方法

android 热修复阿里,Android热修复(阿里热修复)相关推荐

  1. 阿里 Android 多布局,阿里Android规范-05-UI与布局

    1.避免引发全局layout刷新 [正确] (1)设置固定的View大小的宽高 (2)通过修改Canvas位置并且调用 (3)通过设置一个是否允许requestLayout的变量,然后重写控件的req ...

  2. android热补丁作用,Android热修复之 - 阿里开源的热补丁

    这里就有一个概念那就AndFix.apatch补丁用来修复方法,接下来我们看看到底是怎么实现的. 1.2 生成apatch包 假如我们收到了用户上传的崩溃信息,我们改完需要修复的Bug,这个时候就会有 ...

  3. Android 热修复一(热修复流程原理)

    Android热修复一:热修复的流程 下一篇:Android热修复二(手写热修复代码) 在听了lance老师的热修复理论之后,决定写一篇文章,把我理解的全部记下来 之前也多少了解过热修复,当下的热修复 ...

  4. Android工具修复属性,Android 热修复介绍之代码修复

    什么是Android热修复技术 简单来说就是不重新安装apk的情况下,通过补丁,修复bug 正常开发流程 热修复开发流程 目前主流的热修复技术框架 阿里系的: Andfix.Hotfix.Sophix ...

  5. android 热修复视频,Android热修复

    所谓热修复,简单来说就是不以下载新版本apk的方式来修改应用的bug,而是在应用启动后从服务器下拉补丁包实现动态修复bug.所以在应用出现bug后,我们只需要打一个补丁,用户无需下载安装新的版本.主要 ...

  6. 阿里SopHix热修复框架

    2015年以来,Android开发领域里对热修复技术的讨论和分享越来越多,同时也出现了一些不同的解决方案,如QQ空间补丁方案.阿里AndFix以及微信Tinker(Bugly sdk也集成Tikner ...

  7. 阿里云热修复sophix详解

    现在网上有几种常用的app热修复技术,个人感觉阿里云热修复操作比较简单,主要几个步骤,创建app---下载sdk---集成(AS和eclipse)---生成补丁---发布补丁(可以本地调试).下面详细 ...

  8. 阿里Sophix热修复体验

    前言: 之前看了关于热修复的相关文章,想找个代码试试,奈何感觉使用起来有些麻烦,之后就不了了之.看到了阿里的Sophix,嗯,感觉不那么复杂,步骤简单,就着手自己敲了敲.主要记录下自己找了很久,费时步 ...

  9. 热修复 阿里的AndFix

    介绍 大致原理 apkpatch将两个apk做一次对比,然后找出不同的部分. 将生成的apatch文件后缀改成zip再解压开,可以看到里面有一个dex文件. 通过jadx查看一下源码,里面就是被修复的 ...

  10. 阿里热更新android,阿里最新热更新使用采坑记录

    1.必须在AndroidManifest.xml中配置 android:name="com.taobao.android.hotfix.IDSECRET" android:valu ...

最新文章

  1. 关于css的float
  2. [轉]MS SQL Server启用AWE用查看内存使用情况
  3. 【机器学习算法-python实现】Adaboost的实现(1)-单层决策树(decision stump)
  4. php递归复制文件内容,PHP实现递归复制整个文件夹的类实例_php技巧
  5. 数据结构:分块-区间加法、区间乘法和单点查询
  6. 【Calcite】Calcite入门
  7. vue 刷新嵌套路由_vue router嵌套路由在history模式下刷新无法渲染页面问题的解决方法...
  8. TURBOMAIL邮件服务器功能—邮件归档
  9. 信号处理电路整理(RC、运放、TTL)
  10. 数据可视化大屏真不是个事,这 30 个精美的模板拿走吧
  11. BlackBerry7290软件安装——电子书阅读Mobipocket
  12. react native 清除缓存
  13. python——设计一个简单的购房商贷月供计算器
  14. 北漂小斌和你分享古建筑斗拱木构件大样拆分图画法
  15. 通过opencv标记图片以及写入Excel小方法
  16. ImageNet-1k分类数据集中英对照表 验证集类别解析
  17. 2015年度个人总结(公司版)
  18. wordpress创建_您可以使用WordPress创建的19种网站类型
  19. 2.10 窗口的拆分与隐藏 [原创Excel教程]
  20. 计算机网络合集(除应用层之外)

热门文章

  1. 随机过程(一):泊松过程的详细理解
  2. linux下文件属性drwxr-xr-x各是什么意思
  3. 开源地图平台 Mapbender
  4. 在000Webhost架了我滴博客
  5. [Halcon例程学习]增强指纹纹理的coherence_enhancing_diff
  6. 关于 Hypervisor的理解
  7. [TI TDA4 J721E] Sensor 鱼眼摄像头 LDC畸变校正模块LUT的创建和生成——详解
  8. 网站架构资料收集整理
  9. Java是什么,Java是什么意思。
  10. 用计算机弹魂斗罗,魂斗罗30命S弹版电脑版