Android热更新技术的研究与实现Sophix

Android热更新,高级Android开发技术 那我们该怎么做才能做到年薪60万+呢,对于程序员来说,只有不断学习,不断提升自己的实力。我之前有篇文章提到过,感兴趣的可以看看,到底要学习哪些知识才能达到年薪60万+。通过职友集数据可以查看,以北京 Android 相关岗位为例,其中 【20k-30k】 薪酬的 Android 工程师,占到了整体从业者的 30.8%!北京 Android 工程师「工资收入水平 」今天重点内容是怎么去学,怎么提高自己的技术。1.合理安排时间2.找对好的系统的学习资料3.有老师带,可以随时解决问题。 阅读详情

所以阿里爸爸一直在进步着呢,知道技术存在问题就要去解决问题,这不,从Dexposed-->AndFix-->HotFix-->Sophix,技术是越来越成熟了。

 

 

Android热更新技术的研究与实现

------必备引言------

之前的比赛中第一篇博文介绍了kotlin语言:,

第二篇是正在重构为kotlin的项目kibo,主要侧重于使用框架的讲解:

本文因为篇幅较长,可能会有错别字出现,望见谅。第一部分重点是对当下热门的热更新方案进行研究,第二部分则是自己动手实现一个自己的热更新框架。

Android热更新技术的研究与实现之研究篇

热更新这个词出现的时间已经很久了,感觉现在要找工作才来看是晚了不少,但是好东西什么时候学习都不晚的。

今天看到一句话,和大家分享下,人一生有三样东西是别人抢不走的:

  1. 吃进胃里的食物

  2. 藏在心中的梦想

  3. 读进大脑里的书

所以趁着我们的时光正好,多学点东西肯定是赚翻的!!(当然多吃点也没错,不配点图感觉好突兀

言归正传,首先我们要了解与热更新相关的一些概念吧!

---------概念讲解--------热更新 相关概念

  • 组件化----就是将一个app分成多个模块,每个模块都是一个组件(Module),开发的过程中我们可以让这些组件相互依赖或者单独调试部分组件等,但是最终发布的时候是将这些组件合并统一成一个apk,这就是组件化开发。我之前的开发方式基本上都是这一种。具体可以参考Android组件化方案

  • 插件化--将整个app拆分成很多模块,这些模块包括一个宿主和多个插件,每个模块都是一个apk(组件化的每个模块是个lib),最终打包的时候将宿主apk和插件apk分开或者联合打包。开发中,往往会堆积很多的需求进项目,超过 65535 后,插件化就是一个解决方案。

具体组件化和插件化分析大家可以看这个系列,讲解和例子以及源码都很清楚:APP项目如何与插件化无缝结合

放张图帮大家理解:

  • 热更新– 更新的类或者插件粒度较小的时候,我们会称之为热修复,一般用于修复bug!!比如更新一个bug方法或者紧急修改lib包,甚至一个类等。2016 Google 的 Android Studio 推出了Instant Run 功能 同时提出了3个名词;

    1. “热部署” – 方法内的简单修改,无需重启app和Activity。

    2. “暖部署” – app无需重启,但是activity需要重启,比如资源的修改。

    3. “冷部署” – app需要重启,比如继承关系的改变或方法的签名变化等。

  • 增量更新,与热更新区别最大的一个,其实这个大家应该很好理解,安卓上的有些很大的应用,特别是游戏,大则好几个G的多如牛毛,但是每次更新的时候却不是要去下载最新版,而只是下载一个几十兆的增量包就可以完成更新了,而这所使用的技术就是增量更新了。实现的过程大概是这个样子的:我们手机上安装着某个大应用,下载增量包之后,手机上的apk和增量包合并形成新的包,然后会再次安装,这个安装过程可能是可见的,或者应用本身有足够的权限直接在后台安装完成。

今天碰到Android Studio的更新,这应该就是增量更新啦!补丁包只有51M,如果下载新版本有1G多。

而热更新究竟是什么呢?

有一些这样的情况, 当一个App发布之后,突然发现了一个严重bug需要进行紧急修复,这时候公司各方就会忙得焦头烂额:重新打包App、测试、向各个应用市场和渠道换包、提示用户升级、用户下载、覆盖安装。有时候仅仅是为了修改了一行代码,也要付出巨大的成本进行换包和重新发布。老是发布版本用户会疯掉的!!!(好吧 猿猿们也会疯掉。。)

这时候就提出一个问题:有没有办法以补丁的方式动态修复紧急Bug,不再需要重新发布App,不再需要用户重新下载,覆盖安装?

这种需要替换运行时新的类和资源文件的加载,就可以认为是热操作了。而在热更新出现之前,通过反射注解、反射调用和反射注入等方式已经可以实现类的动态加载了。而热更新框架的出现就是为了解决这样一个问题的。

从某种意义上来说,热更新就是要做一件事,替换。当替换的东西属于大块内容的时候,就是模块化了,当你去替换方法的时候,叫热更新,当你替换类的时候,加热插件,而且重某种意义上讲,所有的热更新方案,都是一种热插件,因为热更新方案就是在app之外去干这个事。就这么简单的理解。无论是替换一个类,还是一个方法,都是在干替换这件事请。。这里的替换,也算是几种hook操作,无论在什么代码等级上,都是一种侵入性的操作。

所以总结一句话简单理解热更新就是改变app运行行为的技术!(或者说就是对已发布app进行bug修复的技术) 此时的猿猿们顿时眼前一亮,用户也笑了。。

好的,现在我们已经知道热更新为何物了,那么我们就先看看热更新都有哪些成熟的方案在使用了。

热更新方案介绍

热更新方案发展至今,有很多团队开发过不同的解决方案,包括Dexposed、AndFix,(HotFix)Sophix,Qzone超级补丁的类Nuwa方式,微信的Tinker, 大众点评的nuwa、百度金融的rocooFix, 饿了么的amigo以及美团的robust、腾讯的Bugly热更新。

苹果公司现在已经禁止了热更新,不过估计也组织不了开发者们的热情吧!

我先讲几种方案具体如何使用,说下原理,最后再讲如何实现一个自己的热更新方案!

--Dexposed & AndFix & (HotFix)SopHix --阿里热更新方案Dexposed (阿里热更新方案一)

"Dexposed" 是大厂阿里以前的一个开源热更新项目,基于 Xposed "Xposed"的AOP框架,方法级粒度,可以进行AOP编程、插桩、热补丁、SDK hook等功能。

Xposeed 大家如果不熟悉的话可以看下: Xposed源码剖析——概述,我以前用 Xposed 做过一些小东西(其实就是获取 root 权限后hook 修改一些手机数据,比如支付宝步数,qq 微信步数等,当然了,余额啥的是改不了滴),在这里就不献丑了,毕竟重点也不是这个。我们可以看出 Xposed 有一个缺陷就是需要 root ,而 Dexposed 就是一个不需要 root 权限的 hook 框架。以前阿里的主流 app ,例如手机淘宝,支付宝,天猫都使用了 Dexposed 支持在线热更新,现在已经不用了,用最新的 Sophix 了,后面讲。

Dexposed 中的 AOP 原理来自于 Xposed。在 Dalvik 虚拟机下,主要是通过改变一个方法对象方法在 Dalvik 虚拟机中的定义来实现,具体做法就是将该方法的类型改变为 native 并且将这个方法的实现链接到一个通用的 Native Dispatch 方法上。这个 Dispatch 方法通过 JNI 回调到 Java 端的一个统一处理方法,最后在统一处理方法中调用 before , after 函数来实现AOP。在 Art 虚拟机上目前也是是通过改变一个 ArtMethod 的入口函数来实现。

可惜 android 4.4之后的版本都用 Art 取代了 Dalvik ,所以要 hook Android4.4 以后的版本就必须去适配 Art 虚拟机的机制。目前官方表示,为了适配 Art 的 dexposed_l 只是 beta 版,所以最好不要在正式的线上产品中使用它。

现在阿里已经抛弃 Dexposed 了,原因很明显,4.4 以后不支持了,我们就不细细分析这个方案了,感兴趣的朋友可以通过"这里"了解。简单讲下它的实现方式:

  1. 引入一个名为 patchloader 的 jar 包,这个函数库实现了一个热更新框架,宿主 apk (可能含有 bug 的上线版本)在发布时会将这个 jar 包一起打包进 apk 中;

  2. 补丁 apk (已修复线上版本 bug 的版本)只是在编译时需要这个 jar 包,但打包成 apk 时不包含这个 jar 包,以免补丁 apk 集成到宿主 apk 中时发生冲突;

  3. 补丁 apk 将会以 provided 的形式依赖 dexposedbridge.jar 和 patchloader.jar;

  4. 通过在线下载的方式从服务器下载补丁 apk ,补丁 apk 集成到宿主 apk 中,使用补丁 apk 中的函数替换原来的函数,从而实现在线修复 bug 的功能。

AndFix (阿里热更新方案二)

AndFix 是一个 Android App 的在线热补丁框架。使用此框架,我们能够在不重复发版的情况下,在线修改 App 中的 Bug 。AndFix 就是 “Android Hot-Fix”的缩写。支持 Android 2.3到6.0版本,并且支持 arm 与 X86 系统架构的设备。完美支持 Dalvik 与 ART 的 Runtime。AndFix 的补丁文件是以 .apatch 结尾的文件。它从你的服务器分发到你的客户端来修复你 App 的 bug 。

AndFix 更新实现过程(画的丑勿怪⊙﹏⊙):

  1. 首先添加依赖

    `compile 'com.alipay.euler:andfix:0.3.1@aar'`

  2. 然后在 Application.onCreate() 中添加以下代码

    `patchManager = new PatchManager(context);``patchManager.init(appversion);//current version``patchManager.loadPatch();`

  3. 可以用这句话获取 appversion,每次 appversion 变更都会导致所有补丁被删除,如果 appversion 没有改变,则会加载已经保存的所有补丁。

    `String appversion= getPackageManager().getPackageInfo(getPackageName(), 0).versionName;`

  4. 然后在需要的地方调用 PatchManager 的 addPatch 方法加载新补丁,比如可以在下载补丁文件之后调用。

  5. 之后就是打补丁的过程了,首先生成一个 apk 文件,然后更改代码,在修复 bug 后生成另一个 apk。通过官方提供的工具 apkpatch 生成一个 .apatch 格式的补丁文件,需要提供原 apk,修复后的 apk,以及一个签名文件。

  6. 通过网络传输或者 adb push 的方式将 apatch 文件传到手机上,然后运行到 addPatch 的时候就会加载补丁。

AndFix 更新的原理:

  1. 首先通过虚拟机的 JarFile 加载补丁文件,然后读取 PATCH.MF 文件得到补丁类的名称

  2. 使用 DexFile 读取 patch 文件中的 dex 文件,得到后根据注解来获取补丁方法,然后根据注解中得到雷鸣和方法名,使用 classLoader 获取到 Class,然后根据反射得到 bug 方法。

  3. jni 层使用 C++ 的指针替换 bug 方法对象的属性来修复 bug。

具体的实现主要都是我们在 Application 中初始化的PatchManager中(具体分析在后面的注释可以看到)。

publicPatchManager(Context context){ mContext = context; mAndFixManager = newAndFixManager(mContext);//初始化AndFixManagermPatchDir = newFile(mContext.getFilesDir(), DIR);//初始化存放patch补丁文件的文件夹mPatchs = newConcurrentSkipListSet<Patch>();//初始化存在Patch类的集合,此类适合大并发mLoaders = newConcurrentHashMap<String, ClassLoader>();//初始化存放类对应的类加载器集合}

其中mAndFixManager = new AndFixManager(mContext);的实现:

publicAndFixManager(Context context){ mContext = context; mSupport = Compat.isSupport();//判断Android机型是否适支持AndFixif(mSupport) { mSecurityChecker = newSecurityChecker(mContext);//初始化签名判断类mOptDir = newFile(mContext.getFilesDir(), DIR);//初始化patch文件存放的文件夹if(!mOptDir.exists() && !mOptDir.mkdirs()) {// make directory failmSupport = false; Log.e(TAG, "opt dir create error."); } elseif(!mOptDir.isDirectory()) {// not directorymOptDir.delete();//如果不是文件目录就删除mSupport = false; } }}。。。。。。。。。。。。

然后是对版本的初始化mPatchManager.init(appversion),init(String appVersion)代码如下:

publicvoidinit(String appVersion){

if(!mPatchDir.exists() && !mPatchDir.mkdirs()) {// make directory failLog.e(TAG, "patch dir create error.");

return; } elseif(!mPatchDir.isDirectory()) {// not directorymPatchDir.delete();

return; } SharedPreferences sp = mContext.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);//存储关于patch文件的信息//根据你传入的版本号和之前的对比,做不同的处理String ver = sp.getString(SP_VERSION, null);

if(ver == null|| !ver.equalsIgnoreCase(appVersion)) { cleanPatch();//删除本地patch文件sp.edit().putString(SP_VERSION, appVersion).commit();//并把传入的版本号保存} else{ initPatchs();//初始化patch列表,把本地的patch文件加载到内存}}/*************省略初始化、删除、加载具体方法实现*****************/

init 初始化主要是对 patch 补丁文件信息进行保存或者删除以及加载。

那么 patch 补丁文件是如何加载的呢?其实 patch 补丁文件本质上是一个 jar 包,使用 JarFile 来读取即可:

publicPatch(File file)throwsIOException { mFile = file; init();}@SuppressWarnings("deprecation")privatevoidinit()throwsIOException { JarFile jarFile = null; InputStream inputStream = null;

try{ jarFile = newJarFile(mFile);//使用JarFile读取Patch文件JarEntry entry = jarFile.getJarEntry(ENTRY_NAME);//获取META-INF/PATCH.MF文件inputStream = jarFile.getInputStream(entry); Manifest manifest = newManifest(inputStream); Attributes main = manifest.getMainAttributes(); mName = main.getValue(PATCH_NAME);//获取PATCH.MF属性Patch-NamemTime = newDate(main.getValue(CREATED_TIME));//获取PATCH.MF属性Created-TimemClassesMap = newHashMap<String, List<String>>(); Attributes.Name attrName; String name; List<String> strings;

for(Iterator<?> it = main.keySet().iterator(); it.hasNext();) { attrName = (Attributes.Name) it.next(); name = attrName.toString();

//判断name的后缀是否是-Classes,并把name对应的值加入到集合中,对应的值就是class类名的列表if(name.endsWith(CLASSES)) { strings = Arrays.asList(main.getValue(attrName).split(","));

if(name.equalsIgnoreCase(PATCH_CLASSES)) { mClassesMap.put(mName, strings); } else{ mClassesMap.put( name.trim().substring(0, name.length() - 8),// remove// "-Classes"strings); } } } } finally{ if(jarFile != null) { jarFile.close(); } if(inputStream != null) { inputStream.close(); } }}

然后就是最重要的patchManager.loadPatch():

publicvoidloadPatch(){ mLoaders.put("*", mContext.getClassLoader());// wildcardSet<String> patchNames; List<String> classes;

for(Patch patch : mPatchs) { patchNames = patch.getPatchNames();

for(String patchName : patchNames) { classes = patch.getClasses(patchName);//获取patch对应的class类的集合ListmAndFixManager.fix(patch.getFile(), mContext.getClassLoader(), classes);//修复bug方法} }}

循环获取补丁对应的 class 类来修复 bug 方法,mAndFixManager.fix(patch.getFile(), mContext.getClassLoader(),classes):

从上面的 bug 修复源码可以看出,就是在找补丁包中有 @MethodReplace 注解的方法,然后反射获取原 apk 中方法的位置,最后进行替换。

而最后调用的 replaceMethod(Method dest,Method src) 则是 native 方法,源码中有两个 replaceMethod:

externvoiddalvik_replaceMethod(JNIEnv* env, jobject src, jobject dest);//Dalvik

externvoidart_replaceMethod(JNIEnv* env, jobject src, jobject dest);//Art

从源码的注释也能看出来,因为安卓 4.4 版本之后使用的不再是 Dalvik 虚拟机,而是 Art 虚拟机,所以需要对不同的手机系统做不同的处理。

首先看 Dalvik 替换方法的实现:

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->jniArgInfo = 0x80000000; meth->accessFlags |= ACC_NATIVE;//把Method的属性设置成Native方法int argsSize = dvmComputeMethodArgsSize_fnPtr(meth);

if(!dvmIsStaticMethod(meth)) argsSize++; meth->registersSize = meth->insSize = argsSize; meth->insns = (void*) target; meth->nativeFunc = dalvik_dispatcher;//把方法的实现替换成native方法}

Art 替换方法的实现:

//不同的art系统版本不同处理也不同extern void __attribute__ ((visibility ("hidden"))) art_replaceMethod( JNIEnv* env, jobject src, jobject dest) {

if(apilevel > 22) { replace_6_0(env, src, dest); } elseif(apilevel > 21) { replace_5_1(env, src, dest); } else{ replace_5_0(env, src, dest); }}//以5.0为例:void replace_5_0(JNIEnv* env, jobject src, jobject dest) { art::mirror::ArtMethod* smeth = (art::mirror::ArtMethod*) env->FromReflectedMethod(src); art::mirror::ArtMethod* dmeth = (art::mirror::ArtMethod*) env->FromReflectedMethod(dest); dmeth->declaring_class_->class_loader_ = smeth->declaring_class_->class_loader_; //for plugin classloaderdmeth->declaring_class_->clinit_thread_id_ = smeth->declaring_class_->clinit_thread_id_; dmeth->declaring_class_->status_ = (void *)((int)smeth->declaring_class_->status_-1);

//把一些参数的指针给补丁方法smeth->declaring_class_ = dmeth->declaring_class_; smeth->access_flags_ = dmeth->access_flags_; smeth->frame_size_in_bytes_ = dmeth->frame_size_in_bytes_; smeth->dex_cache_initialized_static_storage_ = dmeth->dex_cache_initialized_static_storage_; smeth->dex_cache_resolved_types_ = dmeth->dex_cache_resolved_types_; smeth->dex_cache_resolved_methods_ = dmeth->dex_cache_resolved_methods_; smeth->vmap_table_ = dmeth->vmap_table_; smeth->core_spill_mask_ = dmeth->core_spill_mask_; smeth->fp_spill_mask_ = dmeth->fp_spill_mask_; smeth->mapping_table_ = dmeth->mapping_table_; smeth->code_item_offset_ = dmeth->code_item_offset_; smeth->entry_point_from_compiled_code_ = dmeth->entry_point_from_compiled_code_; smeth->entry_point_from_interpreter_ = dmeth->entry_point_from_interpreter_; smeth->native_method_ = dmeth->native_method_;//把补丁方法替换掉smeth->method_index_ = dmeth->method_index_; smeth->method_dex_index_ = dmeth->method_dex_index_; LOGD("replace_5_0: %d , %d", smeth->entry_point_from_compiled_code_, dmeth->entry_point_from_compiled_code_);}

其实这个替换过程可以看做三步完成

  1. 打开链接库得到操作句柄,获取 native 层的内部函数,得到 ClassObject 对象

  2. 修改访问权限的属性为 public

  3. 得到新旧方法的指针,新方法指向目标方法,实现方法的替换。

如果我们想知道补丁包中到底替换了哪些方法,可以直接方便易 patch 文件,然后看到的所有含有 @ReplaceMethod 注解的方法基本上就都是需要替换的方法了。

最近我在学习 C++,顿时感觉到还是这种可以控制底层的语言是多么强大,不过安卓可以通过 JNI 调用 C++,也就没什么可吐槽的了!

好的,现在 AndFix 我们分析了一遍它的实现过程和原理,其优点是不需要重启即可应用补丁,遗憾的是它还是有不少缺陷的,这直接导致阿里再次抛弃了它,缺陷如下:

  1. 并不能支持所有的方法修复

  2. 不支持 YunOS

  3. 无法添加新类和新的字段

  4. 需要使用加固前的 apk 制作补丁,但是补丁文件很容易被反编译,也就是修改过的类源码容易泄露。

  5. 使用加固平台可能会使热补丁功能失效(看到有人在 360 加固提了这个问题,自己还未验证)。

Sophix---阿里终极热修复方案

不过阿里作为大厂咋可能没有个自己的热更新框架呢,所以阿里爸爸最近还是做了一个新的热更新框架 SopHix

巴巴再次证明我是最强的,谁都没我厉害!!!因为我啥都支持,而且没缺点。。简直就是无懈可击!

那么我们就来项目集成下看看具体的使用效果吧!具体就拿支持的方法级替换来演示吧!

先去创建个应用:

获取 AppId:24582808-1,和 AppSecret:da283640306b464ff68ce3b13e036a6e 以及 RSA 密钥**。三个参数配置在 application 节点下面:

<meta-dataandroid:name="com.taobao.android.hotfix.IDSECRET"android:value="24582808-1"/><meta-dataandroid:name="com.taobao.android.hotfix.APPSECRET"android:value="da283640306b464ff68ce3b13e036a6e"/><meta-dataandroid:name="com.taobao.android.hotfix.RSASECRET"android:value="MIIEvAIBA**********"/>

添加 maven 仓库地址:

repositories { maven { url "http://maven.aliyun.com/nexus/content/repositories/releases"}}

添加 gradle 坐标版本依赖:

compile 'com.aliyun.ams:alicloud-android-hotfix:3.1.0'

项目结构也很简单:

MainActivity:

publicclassMainActivityextendsAppCompatActivity{

@OverrideprotectedvoidonCreate(Bundle savedInstanceState){

super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ((TextView)findViewById(R.id.tv)).setText(String.valueOf(BuildConfig.VERSION_NAME)); findViewById(R.id.btn_click).setOnClickListener(newView.OnClickListener() { @OverridepublicvoidonClick(View v){ Intent intent; intent = newIntent(MainActivity.this,SecondActivity.class); startActivity(intent); } }); }}

其实就是有一个文本框显示当前版本,还有一个按钮用来跳转到 SecondActivity

而SecondActivity的内容:

publicclassSecondActivityextendsAppCompatActivity{

@OverrideprotectedvoidonCreate(Bundle savedInstanceState){

super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); String s = null; findViewById(R.id.btn).setOnClickListener(newView.OnClickListener() {

@OverridepublicvoidonClick(View v){ Toast.makeText(SecondActivity.this, "弹出框内容弹出错啦!", Toast.LENGTH_SHORT).show(); } }); }}

也很简单,只有一个按钮,按钮点击之后弹出一个 Toast 显示“弹出框内容弹出错啦!”

就这样,我们的一个上线 app 完成了(粗糙是粗糙了点),下面来看下效果吧(请谅解我第一次录屏的渣渣技术,以后会做的越来越好)

然后我们的用户开始用了,发现一个bug!“弹出框弹出的内容是错误的!”,用户可不管别的,马上给我改好啊!

此时的开发er估计心头千万头草泥马在奔腾了,求神拜佛上线不要出问题,刚上线就出问题了,“where is my 测试er!!!”不说了,赶紧修吧,最暴力的方法就是 SecondActivity 的 Toast 中弹出“弹出框内容弹正常啦!”一句代码搞定!bingo!

如果没有热更新,可能就要搞个临时版本或者甚至发布一个新版本,但是现在我们有了 Sophix ,就不需要这么麻烦了。

首先我们去下载补丁打包工具(不得不说,工具确实比较粗糙(丑)。。。)

旧包:<必填> 选择基线包路径(有问题的 APK)。

新包:<必填> 选择新包路径(修复过该问题 APK)。

日志:打开日志输出窗口。

高级:展开高级选项

设置:配置其他信息。

GO!:开始生成补丁。

所以首先我们把旧包和新包添加上之后,配置好之后看看会发生什么吧!

强制冷启动是补丁打完后重启才生效。

时间看情况吧,因为项目本身内容比较少,所以生成补丁的速度比较快,等一下就好了。项目比较大的话估计需要等的时间长一点

我们来看看到底生成了什么?打开补丁生成目录

这个就是我们生成的补丁文件了,下一步补丁如何使用?

我们打开阿里的管理控制台,将补丁上传到控制台,就可以发布了.

这里有个坑,我用自己的中兴手机发现在使用补丁调试工具的时候一直获取包名错误,然后就借了别人的华为手机测试然后就可以了。最后我是在模拟器上完成录制的。

我们首先下载调试工具来看看效果吧,首先连接应用(坑就在这里,有的手机可能会提示包名错误,但是其实是没有错的,虽然官网给出了解决方案,可依旧没有解决,不得已只能用模拟器了)

然后有两种方式可以加载补丁包,一种是扫二维码,还有一种是加载本地补丁jar包,模拟器上实在不好操作啊!!!最后我屈服了,借了同学的手机扫二维码加载补丁包了。。。然后就会有 log 提示

从图中的 log 提示我们可以看出首先下载了补丁包,然后打补丁完成,要求我们重启 APP,那我们就重启呗,看到的当然就应该是补丁打好的 1.1 版本和 Toast 弹出正常啦!!

当然了,目前我们还是在调试工具上加载的补丁包,我们接下来将补丁包发布后就可以不用调试工具,直接打开 app 就可以实现打补丁了,这样就完成了 bug 的修复!

其实这么看起来确实是非常简单就实现了热修复,主要我们的生成补丁工作都是交给阿里提供的工具实现了,其实我们也能看得出来,Sophix 和前面介绍的 AndFix 很像,不同的地方是补丁文件已经给出工具可以一键生成了,而且支持的东西更多了。其他比如 so 库和 library 以及资源文件的更新大家可以查看官方文档了解。

其实 Sophix 主要是在阿里百川 HotFix 的版本上的一个更新,而 HotFix 又是什么呢?

所以阿里爸爸一直在进步着呢,知道技术存在问题就要去解决问题,这不,从Dexposed-->AndFix-->HotFix-->Sophix,技术是越来越成熟了。

下面介绍另外一个大厂的几种热更新方案

热更新方案的对比

好了,上面我们也说了几种热更新的方案了,其他的热更新方案大家可以去搜索了解。

上面阿里给出了AndFix和HotFix以及Sophix的对比,现在我们就对时下的几种热更新方案进行对比,看看到底哪种好:

从对比中我们也能发现Sophix和Tinker作为两大巨头的最新热更新方案,都是比较厉害的,大家如果有需要的话可以去尝试下。

因为时间关系,实现自己的热更新方案还没有写完,暂时不放上来了,等我写完了会放上下一篇的链接的。谢谢大家的捧场支持!

篇幅所限,所载部分只占全文的三分之一,省略作者对于Qzone超级补丁 & 微信Tinker 腾讯热更新方案的详细对比,可以点击左下角“阅读原文”查看全部,大量内容不容错过。

Android热更新技术的研究与实现(一) 1——必备引言——本文因为篇幅较长,可能会有错别字出现,望见谅。第一部分重点是将当下热门的热更新方案实现之后再研究,第二部分则是自己动手实现一个自己的热更新框架。Android热更新技术的研究与实现之研究篇———概念讲解——–热更新 相关概念这个词出现的时间已经很久了,感觉现在要找工作才来看是晚了不少,但是好东西什么时候学习都不晚的。 今天看到一句话,和大家分享下,人一生有三样东西是别人抢不走 阅读详情

相关推荐

2024年Android最全Bugly Android热更新总结篇,安卓面试准备

其实Android开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。上面分享的,博主还把这些技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含,由于篇幅有限,上面只是以图片的形式给大家展示一部分。知识不体系?这里还有整理出来的Android进阶学习的思维脑图,给大家参考一个方向。**Android部分精讲视频领取学习后更加是如虎添翼!**进军BATJ大厂等(备战)!

2401_84564025的博客 460

android中的热更新

主要通过在classload中,创建一个dexelements的dex文件数组,根据线上的crash定位,找到对应的类文件。然后把这个类文件打包成一个dex文件后,放到这个dex文件数组的最前方。这样就会使dexclassloader在加载dex文件的时候就不会加载那个有问题的dex文件。而只会加载我们修复完了的dex文件。可以hook我们自定义的函数也可以hook安卓的函数。通过遍历dex,相同的dex时候,就会选择最前面的。阿里巴巴的无侵入热更新框架。主流的热更新框架介绍。基于DEX分包的问题。

Crazy Android 4162

热更新技术分析与治理策略研究

通过研究热更新技术的机制原理,梳理当前主流热更新框架特点,对热更新技术引发的用户权益和个人隐私安全问题进行调研,并从标准规范、技术监督、行业自律等方面提出热更新问题治理方案,期待促进热更新技术在移动互联网行业中的良性使用。具体措施包括对热更新行为进行明示告知并取得授权同意、加强对热更新下载和删除的管理、加强对热更新行为的报备等。开发者或运营者进行热更新前需向用户明示告知其更新目的、更新方式、更新内容、权限或个人信息处理规则是否变化。可将常用的热更新技术方案分为资源热替换、代码热替换和动态库替换三类。

罗伯特技术屋 1081

Android热更新

android热更新,插件化,组件化,反射

linglingchenchen的专栏 3978

实战指南:基于ELK与Grafana构建天融信防火墙日志可视化看板

本文详细介绍了如何基于ELK与Grafana构建天融信防火墙日志可视化看板,包括环境准备、日志收集与解析配置、Elasticsearch存储优化、Grafana看板设计等关键步骤。通过实战案例和优化技巧,帮助用户高效处理天融信防火墙日志,实现安全态势的可视化监控与分析。

weixin_34246529的博客 226

I2C通信协议SCL与SDA引脚特性:核心要点总结

深入讲解I2C通信协议中SCL和SDA引脚的工作机制与电气特性,帮助理解i2c通信协议的稳定传输原理,掌握上拉电阻配置与信号时序控制要点。

weixin_42103128的博客 2732

Android热更新研究与实现

第一部分重点是将当下热门的热更新方案实现之后再研究,第二部分则是自己动手实现一个自己的热更新框架。 Android热更新技术的研究与实现之研究篇 ———概念讲解——– 热更新 相关概念 这个词出现的时间已经很久了,感觉现在要找工作才来看是晚了不少,但是好东西什么时候学习都不晚的。 今天看到一句话,和大家分享下,人一生有三样东西是别人抢不走的: 吃进胃里的食物 藏在心中的梦想 读进...

csdn_zxw的博客 1万+

【WorkBuddy】WorkBuddy 智能体快速上手:从零到一的实践指南

文章摘要: 传统自动化脚本难以应对灵活多变的自然语言需求,导致逻辑复杂、维护成本高。智能体(Agent)通过理解语义意图、动态决策和松耦合组件解决了这些问题。WorkBuddy采用声明式配置,通过可视化界面定义意图、实体和对话策略,无需编码即可快速构建智能体。其核心组件包括意图分类、实体提取、对话策略、故事样本和回退机制,适用于客服支持、知识问答等高频场景。通过环境准备(Python/Node.js/Redis)和简单配置,用户可以快速搭建可运行的智能体,显著提升自动化效率。

ruiqideng的博客 1623

Android热更新技术的研究与实现(二)

Sophix—阿里终极热修复方案不过阿里作为大厂咋可能没有个自己的热更新框架呢,所以阿里爸爸最近还是做了一个新的热更新框架SopHix巴巴再次证明我是最强的,谁都没我厉害!!!因为我啥都支持,而且没缺点。。简直就是无懈可击!那么我们就来项目集成下看看具体的使用效果吧! 先去创建个应用:获取AppId:24582808-1,和AppSecret:da283640306b464ff68ce3b13

Tomcat的Tom 1万+

ubuntu通过qemu安装银河麒麟V10_Arm_v8 (kylin_v10_飞腾/鲲鹏版)

一、windows下安装vmware虚拟机 二、ubuntu下载地址 https://mirrors.tuna.tsinghua.edu.cn/ubuntu-releases/20.04/ubuntu-20.04.3-live-server-amd64.iso 三、vmware中新建虚拟机,并使用ubuntu-20.04.3-live-server-amd64.iso作为启用盘 。。。在虚拟机中安装ubuntu(略) 四、配置ssh(如果ssh登录不上时配置) 修改openssh的配置 vi /etc/s

u010533742的博客 8703

工程创新训练大赛智能网联车辆赛道LKA+自动驾驶9000+分数分案例

/获取主车在主车路径上的ST坐标。if (status == AVPStatus::eForwarding) // approaching the parking space接近阶段。if (status == AVPStatus::eForwarding) // approaching the parking space接近阶段。if (status == AVPStatus::eForwarding) // approaching the parking space接近阶段。

handsomeboyou的博客 1131

Android热更新学习记录

热更新重点 1. dex热更新,即Java代码热更新 阿里系(AndFix,Hotfix)走的底层替换方案,好处在于实时生效,腾讯系(Tinker)走的是类加载方案,好处在于高兼容性。 阿里百川系(Sophix)就有点机智了,两种方案都有使用,还进行了一定的升级,优先走底层替换方案,底层替换方案走不下去了就走类加载方案。 AndFix(HotFix)的底层替换方案已过时,Sophix的无视底层具体结构的底层替换方案较新。 Tinker的类加载方案,需要重启应用后让Classloader去加载新类

jb_home的博客 343

波分复用技术原理

波分复用原理 把不同波长的光信号复用到同一根光纤中进行传送,这种方式我们把它叫做波分复用( Wavelength Division Multiplexing ) 一根光纤被划分为多个波道,多个波长以一定的间隔隔开,在光纤中独立传输。 波分复用应用演示 如果将WDM系统看作交通系统,光纤可以看作是多个车道的公用道路。 各种类型的业务就像货物一样,被打包装载到车辆中。 车辆按照分配的车道行驶至目的地,完成货物的运输。 想要提高波分复用系统的传输容量,就要增加波道数量或是提升单波传...

m0_63251770的博客 9997

Android热更新五:四大热修复方案对比分析

很早之前就想深入的研究和学习一下热修复,由于时间的原因一直拖着,现在才执笔弄起来。 Android而更新系列:Android热更新一:JAVA的类加载机制Android热更新二:理解Java反射Android热更新三:Android类加载机制Android热更新四:热修复机制Android热更新五:四大热修复方案分析Android热更新六:Qzone热更新原理Android热更新七:Tinker热更新原理Android热更新八:AndFix热更新原理Android热更新九:Robust热更新原理Andro

Gabriel的专栏 3918

PyRoki:机器人运动学优化库入门教程

PyRoki:模块化机器人运动学优化工具包 本文介绍了PyRoki,一个模块化、可扩展且跨平台的机器人运动学优化工具包。PyRoki通过统一变量和成本函数接口,简化了逆运动学、轨迹优化和运动重定向等任务的实现,支持CPU、GPU和TPU加速。实验表明,PyRoki在批量逆运动学任务中比现有GPU加速库cuRobo快1.4-1.7倍,且收敛误差更低。其模块化设计支持快速集成新成本函数,并通过交互式可视化工具优化参数配置。PyRoki开源发布,为机器人运动优化提供了灵活高效的解决方案。

机器人控制与仿真应用 1291

PX4从放弃到精通(二十二):日志

文章目录前言一、下载日志二、ulog转CSV三、利用flightplot软件分析PX4的ulog日志1 windos安装2 ubuntu18.04安装四、使用PlotJuggler分析PX4日志五、设置日志记录条件六、添加自定义日志消息 前言 PX4 1.10以上固件 QGC 一、下载日志 将飞控链接地面站,在下图页面点击“刷新”,即可看到保存的日志(前提是要有TF卡) 选择需要下载的日志,点击右侧的“下载”,然后选择目录即可进行下载,如果想擦除所有的日志,可以点击右侧的“擦除全部” 二、ulog转CS

超维空间科技的博客 6793

简单使用阿里sophix热修复

APP上线了,妈呀,几个bug测试没测出来,真TM蛋疼,又得重新打包审核提交上线,受不了,于是研究下热更新。 具体了解了下,目前比较火的热修复方案主要有: 1、阿里系:Sophix、AndFix 。 2、腾讯系:Tinker。 3、美团系:Robust。 这里我就从阿里的Sophix着手。 阿里云热修复的快速入门:https://help.aliyun.com/document_det...

qq_22780533的博客 435

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Android热修复—阿里的新一代热修复技术Sophix

前言 热修复作为当下热门的技术,在业界内比较著名的有阿里的AndFix、Dexposed,腾讯QQ空间的超级补丁技术和微信的Tinker。但是我对热修复基本没怎么研究过,由于最近一段时间了解到阿里发布了新一代热修复技术—Sophix。于是我决定折腾一波… 一、开通移动热修复服务 1、注册阿里云账号,选择移动热修复服务  选择之后需要开通此功能,点击立即开通即可:

dengpeng_的博客 508

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

阿里推出业界首个非侵入式热修复方案Sophix,颠覆移动端传统发版更新流程!...

阿里巴巴对Android热修复技术已经进行了长达多年的探索。 最开始,是手淘基于Xposed进行了改进,产生了针对Android Dalvik虚拟机运行时的Java Method Hook技术,Dexposed。但这个方案由于对底层Dalvik结构过于依赖,最终无法继续兼容Android5.0以后ART虚拟机,因此作罢。 后来支付宝提出了新的热修复方案A...

weixin_33801856的博客 279

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

荐书丨深入探索Android热修复技术原理

点击上方“程序人生”,选择“置顶公众号”第一时间关注程序猿(媛)身边的故事Android 系统热修复技术之作|移动开发人员人手一本查阅|详解Sophix 热修复开发实践过...

程序人生的博客 1891

Android Mobile Hotfix(阿里云——移动热修复接入)

首先你需要注册并登陆 阿里云移动研发平台,查看官方文档,下载SDK等,集成过程并不复杂。本文主要记录接入流程跟遇到的问题 什么是热修复 热修复,是一种使用补丁来更新修复的手段。不需要通过重新发布App,下载安装等一系列繁琐的过程。 热修复原理 总结参考文档,修复框架很多,但热修复框架的核心技术主要有三类 代码修复 资源修复 动态链接库修复 代码修复主要有三个方案,分别是底层替换方案、...

Android_man_me的专栏 1454

项目记录11---unity热更新探讨

unity热更新探讨 1.整个安装包更新,客户端和服务端各种有规定一个版本号,客户端登录时候重服务端下载进行匹配,需要更新时候整个更新。(手游里面一般不这样做,每个版本更新都会丢失用户),如果真要使用就必须测试好游戏,保证没有bug,才更新上去。(算不上热更新,只能叫更新) 2.资源的更新,不支持代码更新。同理在客户端和服务端约定好一个版本,里面包含用assetBundle打包生产的资

u010665359的专栏 2135

《深入理解Android热修复技术原理》实体书正式出版!给你一个更充实全面的热修复技术视角...

热修复技术,可以看作 Android 平台发展成熟至一定阶段的必然产物。随着移动端业务复杂程度的增加,传统的版本更新流程显然无法满足业务和开发者的需求,热修复技术的推出在很大程度上改善了这一局面。 热修复技术近年来的飞速发展,尤其是在 Instant Run 方案推出后,各种热修复技术百花齐放,国内大部分成熟的主流 App 都拥有自己的热更新技术,像手淘...

weixin_34392435的博客 201

探索Android的HOOK之旅

探索Android的HOOK之旅 因为项目需求,最近在研究Android的hook方法,总结一下研究的结果,做一个笔记。   因为我只研究了Android中Java层的代码hook,Native层的hook还未实际研究与应用。   一、Hook是什么   Hook的中文翻译是“钩子”,简单的说就是,钩住你的代码,对你的方法执行前后做一些操作,例如:改变方法返回值,改变传入方法

qq_36018900的博客 1454

android热更新设计方案,Android热更新五:四大热修复方案对比分析

很早之前就想深入的研究和学习一下热修复,由于时间的原因一直拖着,现在才执笔弄起来。一. 实现套路总所周知,目前热修复的实现套路基本上离不开以下两种:实现套路描述代表底层替换方案底层替换方案限制颇多,但时效性最好,加载轻快,立即见效阿里系的AndFix、Sophix类加载方案类加载方案时效性差,需要重新冷启动才能见效,但修复范围广,限制少QZone超级补丁、微信Tinker二. 方案对比分析虽然热修...

weixin_39790877的博客 447

2024年Android最新身为Android开发者,理当知晓的2024开发趋势及需要掌握的技术,阿里p7面试要求

在这里我和身边一些朋友特意整理了一份快速进阶为Android高级工程师的系统且全面的学习资料。涵盖了Android初级——Android高级架构师进阶必备的一些学习技能。附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。

2301_82244125的博客 1040
上一篇: socket
下一篇: AndroidStudio多版本共存(2.3与3.0 )
code_dream_wq
博客等级 码龄10年 51粉丝 199原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值