Android高级之十三讲-HotFix、热加载和热更新


   本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处!

组件化与插件化:前者对功能进行拆分后,独立开发,打成一个包发布;后者对功能拆分,使用主包+分包,可以分别独立发布。


热更新:两种方式,一种是multidex,一种是修改指针;前者需要重新启动,后者无需重新启动。指下载patch包,修复错误的一种方式。

热加载:即针对插件化的实现,当用户用到此功能,再去下载对应patch包的一种实现方式。

         热部署:无需要重启Application和Activity(修改指针更新方式)

         温部署:需要重启Activity(修改指针更新方式)

         冷部署:需要重启Application(multidex更新方式)

Android热加载出现的原因在于:第一5.1出现之前没有好的办法解决App方法数超过65536的问题,第二启动特别慢,因为加载的模块比较多。本质上还是虚拟机支持JIT的加载机制。

 AndroidDynamicLoader 最早分析的动态加载框架,主要使用activity当壳fragment当内容的方式,来使用空壳activity的应用,将满是fragment的apk加载进来,使用activity的生命周期来控制fragment的加载,其中原来自己做的一个自动化测试框架也是同样原理。

扫描二维码关注公众号,回复: 193928 查看本文章

small 目前最新的热加载框架,支持切割dex实现动态加载,方便业务模块、公共的升级。

multiDex使用时,会判断系统是否支持multiDex,然后判断有无二级dex要安装,将二级dex解压到secondary-dexes目录,通过反射注入ClassLoader的pathList中,完成完整安装。


HotFix出现的原因在于:从出现Bug,解决Bug,再发版,再升级,这个过程过于漫长,而且有的用户不愿意升级,影响功能的使用以及产品的体验。

        AndFix 采用差分包的方式,将要修复的文件打成dex包,通过注解的方式定位到要修改的文件,最终用jni在c层替换掉原文件的指针达到热修复的目的(这是一种So库的Hook方式,其他Hook方式多采用反射方式实现)。

 nuwa QQ空间使用类似办法,通过往classloader的pathlist里加入一个dex,采用覆盖的方式来替换到原来的模块。


增量更新是谷歌提出的一种App更新方式,Instant Run主要应对更新包过大,耗费流量的问题。

老版本2.0,新版本2.1,使用bsdiff工具分解出两者的差异包patch.jar,将patch发布,在客户端使用native的patch方法将data/app目录下的拿出的apk与patch.jar合并,之后再重新安装即可;此时的apk与原2.1的apk的md5一致。

优点:下载包小,流量耗费少

缺点:patch时间有点长,需要异步处理

Tinker,原理跟增量更新一样



相比而言类似Qzone的Nuwa是最好的

关于热修复,也被称为插件,目前比较流行的有HotFix、Nuwa、DroidFix、AndFix等,这些框架均可以在github或其他地方找到,原理如上,方法多样,有覆盖的、有重定向的等等,通过配置、设置action等方式;而作为插件需要满足以下条件:

1、可以独立安装,但不可独立运行

2、具有向下兼容性,即可拓展性

3、只能运行在宿主程序中,而且可以被禁用、替换

使用场景包括修复线上bug、做手机皮肤、开发应用商店等系统提供的接口

Android 中有三个 ClassLoader, 分别为URLClassLoaderPathClassLoaderDexClassLoader。其中

  • URLClassLoader 只能用于加载jar文件,但是由于 dalvik 不能直接识别jar,所以在 Android 中无法使用这个加载器。
  • PathClassLoader 它只能加载已经安装的apk。因为 PathClassLoader 只会去读取 /data/dalvik-cache 目录下的 dex 文件。例如我们安装一个包名为com.hujiang.xxx的 apk,那么当 apk 安装过程中,就会在/data/dalvik-cache目录下生产一个名为data@[email protected]@classes.dex的 ODEX 文件。在使用 PathClassLoader 加载 apk 时,它就会去这个文件夹中找相应的 ODEX 文件,如果 apk 没有安装,自然会报ClassNotFoundException
  • DexClassLoader 是最理想的加载器。它的构造函数包含四个参数,分别为:
    1. dexPath,指目标类所在的APK或jar文件的路径.类装载器将从该路径中寻找指定的目标类,该类必须是APK或jar的全路径.如果要包含多个路径,路径之间必须使用特定的分割符分隔,特定的分割符可以使用System.getProperty(“path.separtor”)获得.
    2. dexOutputDir,由于dex文件被包含在APK或者Jar文件中,因此在装载目标类之前需要先从APK或Jar文件中解压出dex文件,该参数就是制定解压出的dex 文件存放的路径.在Android系统中,一个应用程序一般对应一个Linux用户id,应用程序仅对属于自己的数据目录路径有写的权限,因此,该参数可以使用该程序的数据路径.
    3. libPath,指目标类中所使用的C/C++库存放的路径
    4. classload,是指该装载器的父装载器,一般为当前执行类的装载器

Tinker后台搭建:https://github.com/baidao/tinker-manager

Android6.0以后的内联策略会给热修复带来一定的影响:http://dwz.cn/4O15FS

每次构建时 ProGuard 都会输出下列文件:

dump.txt
说明 APK 中所有类文件的内部结构。
mapping.txt
提供原始与混淆过的类、方法和字段名称之间的转换。
seeds.txt
列出未进行混淆的类和成员。
usage.txt
列出从 APK 移除的代码。

压缩APK:

1、减少ProGuard的keep数量,例:去掉openmobileapi明显26M降到25M

2、官方https://developer.android.com/topic/performance/reduce-apk-size.html

简单Hook方式:https://www.diycode.cc/topics/568

原理:Java高级之虚拟机加载机制

待研究项目:

https://github.com/limpoxe/Android-Plugin-Framework

https://github.com/kaedea/android-dynamical-loading

猜你喜欢

转载自blog.csdn.net/liuxian13183/article/details/53641127