本文来自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的加载,其中原来自己做的一个自动化测试框架也是同样原理。
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, 分别为URLClassLoader
、PathClassLoader
、DexClassLoader
。其中
- URLClassLoader 只能用于加载jar文件,但是由于 dalvik 不能直接识别jar,所以在 Android 中无法使用这个加载器。
- PathClassLoader 它只能加载已经安装的apk。因为 PathClassLoader 只会去读取 /data/dalvik-cache 目录下的 dex 文件。例如我们安装一个包名为
com.hujiang.xxx
的 apk,那么当 apk 安装过程中,就会在/data/dalvik-cache
目录下生产一个名为data@app@com.hujiang.xxx-1.apk@classes.dex
的 ODEX 文件。在使用 PathClassLoader 加载 apk 时,它就会去这个文件夹中找相应的 ODEX 文件,如果 apk 没有安装,自然会报ClassNotFoundException
。 - DexClassLoader 是最理想的加载器。它的构造函数包含四个参数,分别为:
- dexPath,指目标类所在的APK或jar文件的路径.类装载器将从该路径中寻找指定的目标类,该类必须是APK或jar的全路径.如果要包含多个路径,路径之间必须使用特定的分割符分隔,特定的分割符可以使用System.getProperty(“path.separtor”)获得.
- dexOutputDir,由于dex文件被包含在APK或者Jar文件中,因此在装载目标类之前需要先从APK或Jar文件中解压出dex文件,该参数就是制定解压出的dex 文件存放的路径.在Android系统中,一个应用程序一般对应一个Linux用户id,应用程序仅对属于自己的数据目录路径有写的权限,因此,该参数可以使用该程序的数据路径.
- libPath,指目标类中所使用的C/C++库存放的路径
- 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待研究项目:
https://github.com/limpoxe/Android-Plugin-Framework
https://github.com/kaedea/android-dynamical-loading