安卓开发SDK全局热更新方案
作者:互联网
一、背景
App热更新
目前市面上成熟的商业热更新方案不少,有腾讯Bugly的Tinker封装,有阿里云的Sophix,也有游戏垂直行业的卓盟乐变。这些成熟方案,都有一个适用范围,即对App、对游戏整包进行热更新。前两者是和包名绑定在一起的,所以只适用于App热更新;而卓盟乐变则专注于游戏行业,可支持多渠道包热更新。其实最好的还是Sophix,可惜没有开源,虽有公开原理,但是公开资料里也透露了探索与开发周期长达9个月。
在社区,比较流行的热更新有Tinker、QZone、AndFix(HotFix)、Sophix、Robust、Dexposed、Nuwa、Amigo,同商业热更新方案一样,也是适用于App整包热更新。在这些方案里,影响力最大的是微信的Tinker方案,13048个Star,拥有完善的文档,整个框架注重高可用性,最重要的是官方持续维护,在2018年12月,merge7次。相比之下,其他有在Github上开源的框架,star数都是7000以下,上次更新时间都在1年前,甚至2年前。
SDK热更新
SDK热更新,这是一个极少被关注的问题,Google、百度上相关的文章一篇都没有。我们首先进行思考,SDK热更新同App热更新有什么不同?,SDK热更新要做什么?
SDK热更新同App热更新有什么不同?
•App热更新,输入的是一个基准包和一个新版包,输出的是差分包(或补丁),将这个差分包(或补丁)下载到客户端,客户端加载后生效。•SDK热更新,输入的是一个基准SDK和一个新版SDK,输出的也是差分包(或补丁),不同的是,SDK会被集成到不同的游戏包中,这个游戏包也会被分成各式各样的渠道包,我们要将这个差分包(或补丁)下载到所有游戏、所有渠道包,并加载生效。
SDK热更新要做什么?
1. 对SDK的代码、资源进行标识,我们要进行热更新的对象,就是这些代码、资源。
比如,我们可以进行这样标识:所有在com.divin.包名之下的java类,所有assets/divin/文件夹之下的Assets文件,所有以divin_开头的Res文件,所有/res/values/文件,所有以divin_开头的so文件。
2. 在热更新的整个流程,对上述代码、资源进行特别操作。
包括build(计算差分)、patch(合并差分)、load(加载差分)。
十分感谢微信Tinker的开源,对外开放了完整的热更新过程,站在伟人肩上,下面的SDK热更新,都是基于Tinker开源库进行的修改。
热更新重点
1. dex热更新,即Java代码热更新。
阿里系(AndFix,Hotfix)走的底层替换方案,好处在于实时生效,腾讯系(Tinker)走的是类加载方案,好处在于高兼容性。阿里百川系(Sophix)就有点机智了,两种方案都有使用,还进行了一定的升级,优先走底层替换方案,底层替换方案走不下去了就走类加载方案。
AndFix(HotFix)的底层替换方案已过时,Sophix的无视底层具体结构的底层替换方案较新。感兴趣的同学可以深入了解下,追寻极致的代码热替换[1]。
Tinker的类加载方案,需要重启应用后让Classloader去加载新类。因为Android上无法对一个类进行卸载,不重启,则无法加载新类。
2. 资源文件热更新。
这里也是有两个流派,一个流派是参考Instant Run通过addAssetPath加载新的资源包到AssetsManager,然后再替换Resource中的AssetsManager;一个流派是构造新的R文件资源地址以0x66开头的资源包,再通过addAssetPath加载新的资源包到AssetsManager,因为新的R文件资源地址以0x66开头,新的Java代码里,也引用0x66开头的资源,这样就可以新旧资源不干扰且都能生效。
Tinker属于第一个流派[2],Sophix属于第二个流派[3]。
非常遗憾的是,在我们基于Tinker实现SDK资源更新(即指定资源更新)时,只知道第一个流派,并不知道第二个流派(那篇文章没细读,印象不深)。所以后文中所提到的SDK资源更新(指定资源更新),其实是自己摸索出来的,可以理解成流派二的拼多多版,实现了资源新增、更改,但暂未支持R文件直接引用。
3. so文件热更新。
说到这里,是真感谢这世界上有数组这玩意。so文件的热更新,也是把补丁so库的路径插入到nativeLibraryDirectories数组的最前面。
二、Tinker
开源
Tinker已开源,Tencent/tinker[4],同时有详细的使用Wiki,Tinker使用Wiki[5]。
热更新过程
Tinker的整个热更新过程,可以理解成四个步骤。
1. Tinker集成
集成Tinker分两大块,一块是Application改造,一块是定制化功能。第一块较为简单,使用Annotation Processor在编译时生成新Application;第二块非常复杂。
2. build(计算差分)
build有两种模式,一种是供Android Studio开发使用的Gradle模式,一种是使用Java实现的命令行模式。二者最底层,其实都是使用的tinker-patch-lib,一个用Java实现的核心库。
3. patch(合并差分)
4. load(加载差分)
源码结构
Tinker的源码分为这么几大块:
1. tinker-sample-android
顾名思义,这是一个demo,庞大!庞大!庞大!从未见过一个第三方SDK,暴露了如此多的api,可以定制如此多的功能!难怪Sophix在其官方文档中对热更新方案做横向对比时,把自己描述为“傻瓜式接入”,把Amigo描述为“一般”,却把Tinker描述为“复杂”。其实微信官方也有描述,Tinker为了实现“高可用”的目标,在接入成本上做了妥协。热补丁并不简单,在使用之前请务必先仔细阅读XXXX。总的来说,感谢腾讯baba。
demo里,示例了:
①如何控制热更新的请求过滤、合并过程、加载过程、合并后的后续处理、升级热更新模块本身的代码。
②如何改造Application。
③Gradle集成模式的42个参考配置。 42个参考配置!42个参考配置!42个参考配置!
这里让大家放心的是,复杂的是Tinker的定制化开发,而不是给到cp的SDK。我们可以对外隐藏这些定制化开发的细节。
2. tinker-build
这是热更新过程中build步骤的源码,有三个子模块,tinker-patch-lilb是核心代码,tinker-patch-cli是命令行模式的源码,tinker-patch-gradle-plugin是Gradle模式的源码。
3. tinker-android
这是热更新过程中patch和load步骤的源码,随Apk、游戏运行在客户端。也有Application改造时用到的Annotation Processor库的源码。
4. tinker-commons
tinker-build所用到的基础库。
5. third-party
tinker-build所用到的第三方库。
————————————————
版权声明:本文为CSDN博主「安卓进化论」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/d29h1jqy3akvx/article/details/88984620
标签:安卓,更新,Tinker,差分,tinker,全局,SDK,加载 来源: https://www.cnblogs.com/i1lii1il/p/16294373.html