描述
开 本: 16开纸 张: 胶版纸包 装: 平装-胶订是否套装: 否国际标准书号ISBN: 9787111603368
产品特色
编辑推荐
本书不仅详细介绍Android插件化技术如何实现,而且包含大量Android系统的底层知识,有助于App开发人员深入理解Android系统,从而写出更健壮的代码。Android插件化技术不仅适用于快速修复bug,还可以快速上线新功能,从而在时间上和竞争对手抢占用户。本书详细介绍了插件化技术的各种方案,及其实现代码,并给出了应用场景。
内容简介
Android插件化技术广泛应用在移动开发中,通过插件化技术,AndroidApp可以不通过发布新版本而修复线上的bug或者推出新功能,这对于日活千万的App而言是非常重要的,可极大程度提升App开发效率和质量。本书详细介绍了插件化技术的原理、各种方案,及其在AndroidApp中的使用。在介绍插件化技术的同时,还详细介绍了Android底层知识,能帮助AndroidApp开发人员更好地掌握Android的开发技术。本书共22章,先介绍Android插件化技术的历史和现状,系统介绍了Android的底层知识以及反射、代理等技术;然后介绍插件化技术的基本知识,包括各类插件化解决方案及其对比;之后分析了一些插件化框架,如that、Zeus等,深入分析了资源及其在插件化中的应用,以及混淆、增量更新等周边技术的插件化解决方案。
目 录
目录 Contents
序一
序二
序三
前言
部分 预备知识
第1章 插件化技术的昨天、今天与明天2
1.1 插件化技术是什么2
1.2 为什么需要插件化3
1.3 插件化技术的历史3
1.4 插件化技术的用途到底是什么8
1.5 更好的替代品:React Native8
1.6 只有中国这么玩吗9
1.7 四大组件都需要插件化技术吗10
1.8 双开和虚拟机10
1.9 从原生页面到HTML 5的过渡11
1.10 本章小结12
第2章 Android底层知识13
2.1 概述13
2.2 Binder原理14
2.3 AIDL原理16
2.4 AMS20
2.5 Activity工作原理21
2.5.1 App是怎么启动的21
2.5.2 启动App并非那么简单21
2.6 App内部的页面跳转32
2.7 Context家族史34
2.8 Service工作原理36
2.8.1 在新进程启动Service36
2.8.2 启动同一进程的Service39
2.8.3 在同一进程绑定Service39
2.9 BroadcastReceiver工作原理41
2.9.1 注册过程43
2.9.2 发送广播的流程44
2.9.3 广播的种类45
2.10 ContentProvider工作原理46
2.10.1 ContentProvider的本质49
2.10.2 匿名共享内存(ASM)49
2.10.3 ContentProvider与AMS的通信流程50
2.11 PMS及App安装过程52
2.11.1 PMS简介52
2.11.2 App的安装流程52
2.11.3 PackageParser53
2.11.4 ActivityThread与PackageManager54
2.12 ClassLoader家族史55
2.13 双亲委托57
2.14 MultiDex57
2.15 实现一个音乐播放器App59
2.15.1 基于两个Receiver的音乐播放器59
2.15.2 基于一个Receiver的音乐播放器63
2.16 本章小结68
第3章 反射70
3.1 基本反射技术70
3.1.1 根据一个字符串得到一个类70
3.1.2 获取类的成员71
3.1.3 对泛型类的反射75
3.2 jOOR77
3.2.1 根据一个字符串得到一个类78
3.2.2 获取类的成员78
3.2.3 对泛型类的反射79
3.3 对基本反射语法的封装80
3.3.1 反射出一个构造函数81
3.3.2 调用实例方法81
3.3.3 调用静态方法82
3.3.4 获取并设置一个字段的值82
3.3.5 对泛型类的处理83
3.4 对反射的进一步封装84
3.5 本章小结88
第4章 代理模式89
4.1 概述89
4.1.1 远程代理(AIDL)90
4.1.2 保护代理(权限控制)92
4.1.3 虚代理(图片占位)92
4.1.4 协作开发(Mock Class)92
4.1.5 给生活加点料(记日志)93
4.2 静态代理和动态代理94
4.3 对AMN的Hook95
4.4 对PMS的Hook97
4.5 本章小结98
第5章 对startActivity方法进行Hook99
5.1 startActivity方法的两种形式99
5.2 对Activity的startActivity方法进行Hook100
5.2.1 方案1:重写Activity的startActivityForResult方法102
5.2.2 方案2:对Activity的mInstrumentation字段进行Hook102
5.2.3 方案3:对AMN的getDefault方法进行Hook104
5.2.4 方案4:对H类的mCallback字段进行Hook107
5.2.5 方案5:再次对Instrumentation字段进行Hook109
5.3 对Context的startActivity方法进行Hook111
5.3.1 方案6:对ActivityThread的mInstrumentation字段进行Hook111
5.3.2 对AMN的getDafault方法进行Hook是一劳永逸的113
5.4 启动没有在AndroidManifest中声明的Activity113
5.4.1 “欺骗AMS”的策略分析114
5.4.2 Hook的上半场115
5.4.3 Hook的下半场:对H类的mCallback字段进行Hook118
5.4.4 Hook的下半场:对ActivityThread的mInstrumentation字段进行Hook119
5.4.5 “欺骗AMS”的弊端121
5.5 本章小结121
第二部分 解决方案
第6章 插件化技术基础知识124
6.1 加载外部的dex124
6.2 面向接口编程126
6.3 插件的瘦身129
6.4 对插件进行代码调试131
6.5 Application的插件化解决方案133
6.6 本章小结134
第7章 资源初探135
7.1 资源加载机制135
7.1.1 资源分类135
7.1.2 剪不断理还乱:Resources和AssetManager136
7.2 资源的插件化解决方案137
7.3 换肤141
7.4 殊途同归:另一种换肤方式149
7.5 本章小结149
第8章 简单的插件化解决方案150
8.1 在AndroidManifest中声明插件中的组件150
8.2 宿主App加载插件中的类151
8.3 启动插件Service152
8.4 加载插件中的资源152
8.5 本章小结154
第9章 Activity的插件化解决方案155
9.1 启动没有在AndroidManifest中声明的插件Activity155
9.2 基于动态替换的Activity插件化解决方案159
9.2.1 Android启动Activity的原理分析159
9.2.2 故意命中缓存160
9.2.3 加载插件中类的方案1:为每个插件创建一个ClassLoader164
9.2.4 为了圆一个谎言而编造更多的谎言164
9.3 加载插件中类的方案2:合并多个dex166
9.4 为Activity解决资源问题169
9.5 对LaunchMode的支持169
9.6 加载插件中类的方案3:修改App原生的ClassLoader172
9.7 本章小结174
第10章 Service的插件化解决方案175
10.1 Android界的荀彧和荀攸:Service和Activity175
10.2 预先占位176
10.3 startService的解决方案178
10.4 bindService的解决方案183
10.5 本章小结185
第11章 BroadcastReceiver的插件化解决方案186
11.
序一
序二
序三
前言
部分 预备知识
第1章 插件化技术的昨天、今天与明天2
1.1 插件化技术是什么2
1.2 为什么需要插件化3
1.3 插件化技术的历史3
1.4 插件化技术的用途到底是什么8
1.5 更好的替代品:React Native8
1.6 只有中国这么玩吗9
1.7 四大组件都需要插件化技术吗10
1.8 双开和虚拟机10
1.9 从原生页面到HTML 5的过渡11
1.10 本章小结12
第2章 Android底层知识13
2.1 概述13
2.2 Binder原理14
2.3 AIDL原理16
2.4 AMS20
2.5 Activity工作原理21
2.5.1 App是怎么启动的21
2.5.2 启动App并非那么简单21
2.6 App内部的页面跳转32
2.7 Context家族史34
2.8 Service工作原理36
2.8.1 在新进程启动Service36
2.8.2 启动同一进程的Service39
2.8.3 在同一进程绑定Service39
2.9 BroadcastReceiver工作原理41
2.9.1 注册过程43
2.9.2 发送广播的流程44
2.9.3 广播的种类45
2.10 ContentProvider工作原理46
2.10.1 ContentProvider的本质49
2.10.2 匿名共享内存(ASM)49
2.10.3 ContentProvider与AMS的通信流程50
2.11 PMS及App安装过程52
2.11.1 PMS简介52
2.11.2 App的安装流程52
2.11.3 PackageParser53
2.11.4 ActivityThread与PackageManager54
2.12 ClassLoader家族史55
2.13 双亲委托57
2.14 MultiDex57
2.15 实现一个音乐播放器App59
2.15.1 基于两个Receiver的音乐播放器59
2.15.2 基于一个Receiver的音乐播放器63
2.16 本章小结68
第3章 反射70
3.1 基本反射技术70
3.1.1 根据一个字符串得到一个类70
3.1.2 获取类的成员71
3.1.3 对泛型类的反射75
3.2 jOOR77
3.2.1 根据一个字符串得到一个类78
3.2.2 获取类的成员78
3.2.3 对泛型类的反射79
3.3 对基本反射语法的封装80
3.3.1 反射出一个构造函数81
3.3.2 调用实例方法81
3.3.3 调用静态方法82
3.3.4 获取并设置一个字段的值82
3.3.5 对泛型类的处理83
3.4 对反射的进一步封装84
3.5 本章小结88
第4章 代理模式89
4.1 概述89
4.1.1 远程代理(AIDL)90
4.1.2 保护代理(权限控制)92
4.1.3 虚代理(图片占位)92
4.1.4 协作开发(Mock Class)92
4.1.5 给生活加点料(记日志)93
4.2 静态代理和动态代理94
4.3 对AMN的Hook95
4.4 对PMS的Hook97
4.5 本章小结98
第5章 对startActivity方法进行Hook99
5.1 startActivity方法的两种形式99
5.2 对Activity的startActivity方法进行Hook100
5.2.1 方案1:重写Activity的startActivityForResult方法102
5.2.2 方案2:对Activity的mInstrumentation字段进行Hook102
5.2.3 方案3:对AMN的getDefault方法进行Hook104
5.2.4 方案4:对H类的mCallback字段进行Hook107
5.2.5 方案5:再次对Instrumentation字段进行Hook109
5.3 对Context的startActivity方法进行Hook111
5.3.1 方案6:对ActivityThread的mInstrumentation字段进行Hook111
5.3.2 对AMN的getDafault方法进行Hook是一劳永逸的113
5.4 启动没有在AndroidManifest中声明的Activity113
5.4.1 “欺骗AMS”的策略分析114
5.4.2 Hook的上半场115
5.4.3 Hook的下半场:对H类的mCallback字段进行Hook118
5.4.4 Hook的下半场:对ActivityThread的mInstrumentation字段进行Hook119
5.4.5 “欺骗AMS”的弊端121
5.5 本章小结121
第二部分 解决方案
第6章 插件化技术基础知识124
6.1 加载外部的dex124
6.2 面向接口编程126
6.3 插件的瘦身129
6.4 对插件进行代码调试131
6.5 Application的插件化解决方案133
6.6 本章小结134
第7章 资源初探135
7.1 资源加载机制135
7.1.1 资源分类135
7.1.2 剪不断理还乱:Resources和AssetManager136
7.2 资源的插件化解决方案137
7.3 换肤141
7.4 殊途同归:另一种换肤方式149
7.5 本章小结149
第8章 简单的插件化解决方案150
8.1 在AndroidManifest中声明插件中的组件150
8.2 宿主App加载插件中的类151
8.3 启动插件Service152
8.4 加载插件中的资源152
8.5 本章小结154
第9章 Activity的插件化解决方案155
9.1 启动没有在AndroidManifest中声明的插件Activity155
9.2 基于动态替换的Activity插件化解决方案159
9.2.1 Android启动Activity的原理分析159
9.2.2 故意命中缓存160
9.2.3 加载插件中类的方案1:为每个插件创建一个ClassLoader164
9.2.4 为了圆一个谎言而编造更多的谎言164
9.3 加载插件中类的方案2:合并多个dex166
9.4 为Activity解决资源问题169
9.5 对LaunchMode的支持169
9.6 加载插件中类的方案3:修改App原生的ClassLoader172
9.7 本章小结174
第10章 Service的插件化解决方案175
10.1 Android界的荀彧和荀攸:Service和Activity175
10.2 预先占位176
10.3 startService的解决方案178
10.4 bindService的解决方案183
10.5 本章小结185
第11章 BroadcastReceiver的插件化解决方案186
11.
前 言
前 言 Preface这是一本什么书如果只把本书当作纯粹介绍Android插件化技术的书那就错了。本书在研究Android插件化之余,还详细介绍了Android系统的底层知识,包括Binder和AIDL的原理、四大组件的原理、App的安装和启动流程、Context和ClassLoader的家族史。没有罗列大量的Android系统中的源码,而是以一张张UML图把这些知识串起来。
本书详细介绍了Android中的资源机制,包括aapt命令的原理、resource文件的组成以及public.xml的使用方式,顺带还提及了如何自定义一个Gradle插件化。
此外,本书还介绍了so的加载原理,尤其是动态加载so的技术,可以帮助App进行瘦身;探讨了HTML5降级技术,可以实现任何一个原生页面和HTML5页面的互换;介绍了反射技术,以及jOOR这个有趣的开源框架;介绍了Android中的动态代理技术Proxy.newProxyInstance方法。
如果读者能坚持把这本书从头到尾读完,那么不仅掌握了插件化技术,而且也把上述所有这些知识点全都系统地学习了一遍。也许Android插件化会随着Google的限制而有所变化甚至消亡,但我在本书中介绍的其他知识,仍然是大有用武之处的。
如何面对Android P的限制写作这本书的时候,Google推出了Android P preview的操作系统,会限制对@hide api的反射调用。目前会通过log发出警告,用户代码仍然能够获取到正确的Method或Field,在后续版本中获取到的Method或Field极有可能为空。
但是道高一尺,魔高一丈。Google对这次限制,很快就被技术极客们绕过去了,有两种解决方法:
1)把通过反射调用的系统内部类改为直接调用。具体操作办法是,在Android项目中新建一个库,把要反射的类的方法和字段复制一份到这个库中,App对这个库的引用关系设置为provided。那么我们就可以在App中直接调用这个类和方法,同时,在编译的时候,又不会把这些类包含到apk中。
其实早在2015年,hoxkx就在他的插件化框架中实现了这种技术。但是这种解决方案,仅限于Android系统中标记为public的方法和字段,对于protected和private就无能为力了。比如AssetsManager的addAssetPath方法,ActivityThread的currentActivityThread方法。
2)类的每个方法和字段都有一个标记,表明它是不是hide类型的。我们只要在jni层,把这个标记改为不是hide的,就可以绕过检查了。
然而,魔高一丈,道高一丈二。Google在Android P的正式版中势必会推出更严厉的限制方案,到时候,又会有新的解决方案面世,让我们拭目以待。
其实,开发者是无意和Google进行技术对抗的,这是毫无意义的。泛滥成灾的修改导致了App大量的崩溃,Google实在看不下去了,所以才搞出这套限制方案;另一方面,插件化技术是刚需,尤其在中国的互联网行业,App崩溃会直接影响使用,很可能导致经济损失,所以开发者才会不惜一切代价走插件化这条路。
再回到限制方案来,Google也不是清一色不要开发者使用系统底层的标记为hide的API,而是推出了一组黑灰名单,如下所示:
名 单影 响light-greylist 浅灰名单仅打印警告日志,Google尽可能在未来版本提供 public APIdark-greylist 深灰名单第三方App不能访问,开发者可以申请把这份清单中的某些API加入到浅灰名单blacklist 黑名单第三方App不能访问所以,另一种应对策略是,在插件化中使用浅灰名单中的API,比如说ActivityThread的currentActivityThread方法。
Google的这组清单还在持续调整中,据我所知,给各大手机厂商的清单与其在社区中发布的清单略有出入。在Android P的正式版本中,这份清单会终确定下来。所以现在中国的各个插件化框架的开发人员,都在等Android P的正式版本发布后再制定相应的策略。留给中国队的时间不多了。
这本书的来龙去脉这是一本酝酿了3年的书。早在2015年Android插件化技术百家争鸣时,我就看好这个技术,想写一本书介绍这个技术,但当时的积累还不够。那年,我在一场技术大会上发表了《Android插件化从入门到放弃》演讲,四十五分钟介绍了插件化技术的皮毛。后来这个演讲内容被整理成文章发布到网上,流传很广。
2017年1月,有企业要我去讲2天Android插件化技术。为此,我花了一个月时间,准备了四十多个例子。这是我次系统地积累了素材。
2017年6月,我在腾讯课堂做Android线上培训,为了宣传推广我的课程,我写了一系列文章《写给Android App开发人员看的Android底层知识》,共8篇,没列太多代码,完全以UML图的方式向读者普及Binder、AIDL、四大组件、AMS、PMS的知识。本书的第2章就是在这8篇文章的基础之上进行扩充的。
2018年1月,我父亲住院一周。我当时在医院每天晚上值班。老爷子半夜打呼噜,吵得我睡不着,事后我才知道,我睡着了打呼噜声音比他还大。半夜睡不着时就开始了本书的写作,每晚坚持写到凌晨两三点。直到父亲出院,这本书写了将近五分之一。
碰巧的是,这一年5月底我结婚,促使我想在5月初完成这本书的一稿,为此,我宅在家里整整写了3个月。仅以此书作为新婚礼物献给我亲爱的老婆,感谢你的理解,这本书才得以面世。
本书详细介绍了Android中的资源机制,包括aapt命令的原理、resource文件的组成以及public.xml的使用方式,顺带还提及了如何自定义一个Gradle插件化。
此外,本书还介绍了so的加载原理,尤其是动态加载so的技术,可以帮助App进行瘦身;探讨了HTML5降级技术,可以实现任何一个原生页面和HTML5页面的互换;介绍了反射技术,以及jOOR这个有趣的开源框架;介绍了Android中的动态代理技术Proxy.newProxyInstance方法。
如果读者能坚持把这本书从头到尾读完,那么不仅掌握了插件化技术,而且也把上述所有这些知识点全都系统地学习了一遍。也许Android插件化会随着Google的限制而有所变化甚至消亡,但我在本书中介绍的其他知识,仍然是大有用武之处的。
如何面对Android P的限制写作这本书的时候,Google推出了Android P preview的操作系统,会限制对@hide api的反射调用。目前会通过log发出警告,用户代码仍然能够获取到正确的Method或Field,在后续版本中获取到的Method或Field极有可能为空。
但是道高一尺,魔高一丈。Google对这次限制,很快就被技术极客们绕过去了,有两种解决方法:
1)把通过反射调用的系统内部类改为直接调用。具体操作办法是,在Android项目中新建一个库,把要反射的类的方法和字段复制一份到这个库中,App对这个库的引用关系设置为provided。那么我们就可以在App中直接调用这个类和方法,同时,在编译的时候,又不会把这些类包含到apk中。
其实早在2015年,hoxkx就在他的插件化框架中实现了这种技术。但是这种解决方案,仅限于Android系统中标记为public的方法和字段,对于protected和private就无能为力了。比如AssetsManager的addAssetPath方法,ActivityThread的currentActivityThread方法。
2)类的每个方法和字段都有一个标记,表明它是不是hide类型的。我们只要在jni层,把这个标记改为不是hide的,就可以绕过检查了。
然而,魔高一丈,道高一丈二。Google在Android P的正式版中势必会推出更严厉的限制方案,到时候,又会有新的解决方案面世,让我们拭目以待。
其实,开发者是无意和Google进行技术对抗的,这是毫无意义的。泛滥成灾的修改导致了App大量的崩溃,Google实在看不下去了,所以才搞出这套限制方案;另一方面,插件化技术是刚需,尤其在中国的互联网行业,App崩溃会直接影响使用,很可能导致经济损失,所以开发者才会不惜一切代价走插件化这条路。
再回到限制方案来,Google也不是清一色不要开发者使用系统底层的标记为hide的API,而是推出了一组黑灰名单,如下所示:
名 单影 响light-greylist 浅灰名单仅打印警告日志,Google尽可能在未来版本提供 public APIdark-greylist 深灰名单第三方App不能访问,开发者可以申请把这份清单中的某些API加入到浅灰名单blacklist 黑名单第三方App不能访问所以,另一种应对策略是,在插件化中使用浅灰名单中的API,比如说ActivityThread的currentActivityThread方法。
Google的这组清单还在持续调整中,据我所知,给各大手机厂商的清单与其在社区中发布的清单略有出入。在Android P的正式版本中,这份清单会终确定下来。所以现在中国的各个插件化框架的开发人员,都在等Android P的正式版本发布后再制定相应的策略。留给中国队的时间不多了。
这本书的来龙去脉这是一本酝酿了3年的书。早在2015年Android插件化技术百家争鸣时,我就看好这个技术,想写一本书介绍这个技术,但当时的积累还不够。那年,我在一场技术大会上发表了《Android插件化从入门到放弃》演讲,四十五分钟介绍了插件化技术的皮毛。后来这个演讲内容被整理成文章发布到网上,流传很广。
2017年1月,有企业要我去讲2天Android插件化技术。为此,我花了一个月时间,准备了四十多个例子。这是我次系统地积累了素材。
2017年6月,我在腾讯课堂做Android线上培训,为了宣传推广我的课程,我写了一系列文章《写给Android App开发人员看的Android底层知识》,共8篇,没列太多代码,完全以UML图的方式向读者普及Binder、AIDL、四大组件、AMS、PMS的知识。本书的第2章就是在这8篇文章的基础之上进行扩充的。
2018年1月,我父亲住院一周。我当时在医院每天晚上值班。老爷子半夜打呼噜,吵得我睡不着,事后我才知道,我睡着了打呼噜声音比他还大。半夜睡不着时就开始了本书的写作,每晚坚持写到凌晨两三点。直到父亲出院,这本书写了将近五分之一。
碰巧的是,这一年5月底我结婚,促使我想在5月初完成这本书的一稿,为此,我宅在家里整整写了3个月。仅以此书作为新婚礼物献给我亲爱的老婆,感谢你的理解,这本书才得以面世。
评论
还没有评论。