android 热修复阿里,Android热修复(阿里热修复)
一、概述
当一个产品上线后,如果出现了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热修复(阿里热修复)相关推荐
- 阿里 Android 多布局,阿里Android规范-05-UI与布局
1.避免引发全局layout刷新 [正确] (1)设置固定的View大小的宽高 (2)通过修改Canvas位置并且调用 (3)通过设置一个是否允许requestLayout的变量,然后重写控件的req ...
- android热补丁作用,Android热修复之 - 阿里开源的热补丁
这里就有一个概念那就AndFix.apatch补丁用来修复方法,接下来我们看看到底是怎么实现的. 1.2 生成apatch包 假如我们收到了用户上传的崩溃信息,我们改完需要修复的Bug,这个时候就会有 ...
- Android 热修复一(热修复流程原理)
Android热修复一:热修复的流程 下一篇:Android热修复二(手写热修复代码) 在听了lance老师的热修复理论之后,决定写一篇文章,把我理解的全部记下来 之前也多少了解过热修复,当下的热修复 ...
- Android工具修复属性,Android 热修复介绍之代码修复
什么是Android热修复技术 简单来说就是不重新安装apk的情况下,通过补丁,修复bug 正常开发流程 热修复开发流程 目前主流的热修复技术框架 阿里系的: Andfix.Hotfix.Sophix ...
- android 热修复视频,Android热修复
所谓热修复,简单来说就是不以下载新版本apk的方式来修改应用的bug,而是在应用启动后从服务器下拉补丁包实现动态修复bug.所以在应用出现bug后,我们只需要打一个补丁,用户无需下载安装新的版本.主要 ...
- 阿里SopHix热修复框架
2015年以来,Android开发领域里对热修复技术的讨论和分享越来越多,同时也出现了一些不同的解决方案,如QQ空间补丁方案.阿里AndFix以及微信Tinker(Bugly sdk也集成Tikner ...
- 阿里云热修复sophix详解
现在网上有几种常用的app热修复技术,个人感觉阿里云热修复操作比较简单,主要几个步骤,创建app---下载sdk---集成(AS和eclipse)---生成补丁---发布补丁(可以本地调试).下面详细 ...
- 阿里Sophix热修复体验
前言: 之前看了关于热修复的相关文章,想找个代码试试,奈何感觉使用起来有些麻烦,之后就不了了之.看到了阿里的Sophix,嗯,感觉不那么复杂,步骤简单,就着手自己敲了敲.主要记录下自己找了很久,费时步 ...
- 热修复 阿里的AndFix
介绍 大致原理 apkpatch将两个apk做一次对比,然后找出不同的部分. 将生成的apatch文件后缀改成zip再解压开,可以看到里面有一个dex文件. 通过jadx查看一下源码,里面就是被修复的 ...
- 阿里热更新android,阿里最新热更新使用采坑记录
1.必须在AndroidManifest.xml中配置 android:name="com.taobao.android.hotfix.IDSECRET" android:valu ...
最新文章
- 关于css的float
- [轉]MS SQL Server启用AWE用查看内存使用情况
- 【机器学习算法-python实现】Adaboost的实现(1)-单层决策树(decision stump)
- php递归复制文件内容,PHP实现递归复制整个文件夹的类实例_php技巧
- 数据结构:分块-区间加法、区间乘法和单点查询
- 【Calcite】Calcite入门
- vue 刷新嵌套路由_vue router嵌套路由在history模式下刷新无法渲染页面问题的解决方法...
- TURBOMAIL邮件服务器功能—邮件归档
- 信号处理电路整理(RC、运放、TTL)
- 数据可视化大屏真不是个事,这 30 个精美的模板拿走吧
- BlackBerry7290软件安装——电子书阅读Mobipocket
- react native 清除缓存
- python——设计一个简单的购房商贷月供计算器
- 北漂小斌和你分享古建筑斗拱木构件大样拆分图画法
- 通过opencv标记图片以及写入Excel小方法
- ImageNet-1k分类数据集中英对照表 验证集类别解析
- 2015年度个人总结(公司版)
- wordpress创建_您可以使用WordPress创建的19种网站类型
- 2.10 窗口的拆分与隐藏 [原创Excel教程]
- 计算机网络合集(除应用层之外)