移动开发的罗曼蒂克消亡史,android 系统开发书籍
张勇敦厚面相中透着机灵,和大部分程序员不一样,他十分健谈,说起自己开发的 DroidPlugin 眼里带着光。和他聊了两个小时,我确信,这是一项安卓开发黑科技。
安卓黑科技
中国的技术都是业务驱动的,先有需求,然后研究怎么能做到,DroidPlugin 诞生的背景也是如此。
14 年左右,中国和国外的 App 理念走上了截然不同的两条道路。在国外,一个 App 最多做两三件事,但在中国,一个 App 恨不得装下所有功能,这就是所谓的超级 App。
超级 App 有很多好处,但是,谷歌在设计安卓的时候,没有考虑到存在超级 App 的情况,在安卓早期版本里,一个 App 里只允许存在 65536 个方法,一旦超过就会报错。65536 已经很大了,就和千年虫问题一样,开发安卓的工程师们根本没想到有 App 会需要那么多的方法。
这个问题在国外被 Facebook 发现了,Facebook 的 App 很大,可能是国外仅有的几个可以称作超级 App 的应用了,它给出了一个暂时绕过的解决办法。
国内开发者不满足这种暂时绕过的方法,早在 2012 年,大众点评的工程师图毅敏在研究 Android 源码的过程中就发现,通过对 AndroidDynamicLoader 方法的应用,可以做到动态加载资源甚至代码。2014 年底,当时在百度的安卓工程师任玉刚开源了 Dynamic-load-apk,将这种方法更进一步。
到张勇这里,他把动态代理发展到了极致,让 Android 系统的四大组件都可以动态加载,这样,安装 App 的时候只用装一个宿主 App 或者叫壳 App,然后在宿主 App 里远程下载代表各个功能模块的 App 就行了。这种技术流派,后来被称为安卓插件化技术。
想象一下,你的手机只用安装一个 App,如果想用其它 App,点击下载之后就可以运行,省去了麻烦的安装过程,甚至你还可以用不同的账号同时打开一个 App,这就是插件化的神奇之处。
安卓插件化的一个变种是组件化技术,它并不用分成不同的 App,而是平时各个模块分开开发,发布的时候一起打包,这种技术的集大成者就是手机淘宝研发的 Atlas 组件化框架,2014 年初伯奎对外首次分享,2017 年 3 月正式开源。
超级 App 还会带来一个问题,就是 App 的更新,当 App 由数十个团队,数百上千人开发,版本控制和更新变成了一个很麻烦的事情,特别是线上版本发现 bug 时需要及时更新版本处理,而国内安卓渠道众多,依赖各个平台更新是不现实的,只有自己处理更新,为了降低更新给用户带来的影响,国内又发明了热更新技术。
早期的热更新技术借鉴了安卓极客最爱的工具 Xposed,2015 年 7 月左右,淘宝的白衣开源了安卓切面编程框架 Dexposed,它在 Xposed 的基础上进行改造,使其不需要 root 就可以任意改变应用的功能。但是,这个技术只支持 Dalvik 运行时,对于新的 ART 运行时无能为力。随后不久,支付宝安卓团队推出了 AndFix,能很好的支持 ART,很快成为阿里系的标准热更新工具。
腾讯这边,QQ 空间在 2015 年分享了它的热补丁技术,它是基于谷歌为了解决方法数溢出而推出的 MultiDex 方案,第二年微信推出了更好的热更新框架 Tinker,也被广大的开发者所喜爱。
2016 年,美团的人告诉我,他们在研究了 Android Studio 2.0 里的 Instant Run 功能后,推出了 Robust 热更新框架,成为安卓热更新的一个新的技术流派。
插件化、组件化、热更新,从 2015 年开始,国内的移动开发技术爆发了井喷式的发展,这些是国内独有的技术,在这一期间涌现出无数开发者,他们抱着极大的热情研究技术并进行开源和分享,那是一个对移动开发者最好的时代。
在这一群人中,我有两个人印象比较深刻。
天才少年
2016 年初,我开始筹办 GMTC 全球移动技术大会,找张勇推荐讲师,他给我介绍了罗迪。从勇哥的描述里,显然他对罗迪的技术极为认同,然而让我大吃一惊的是,罗迪当时才高二,还是个在校学生。
我一度怀疑他的技术水平,不过在通过邮件和微信交流后,我打消了这种怀疑。他当时已经开源了几个 Android 插件化方面的工具,其中包括 ART 运行时的 Hook 工具 Legend,这是当时最前沿的课题。在交流中我也了解到,他对插件化技术发展有深入的洞察,让我十分佩服。
毫无疑问这是一个天才少年。据他自述,他从初二开始自学编程,初三开始学 Java 和安卓开发,业余时间全部用来学习和研究 Android 源码,这一点,就连职业的开发者也难以做到。他的天才并不是说具有学习和编程的
天赋,而是可以静下心来学习在一般人看起来枯燥的技术。
不过,虽然我认同他的技术,但是在权衡之后我还是放弃了让他当讲师的想法,因为不想拔苗助长。但我邀请他来参加 GMTC 大会,以及一个安卓的闭门会议,并在闭门会议上做一个分享。
6 月 24 号,GMTC 如期举行,我也见到了罗迪,他在微信上很活跃,但在现实中看上去比较木讷,讲一句话需要思考一段时间,不太擅长与人打交道。
他说,插件化今后的方向是沙盒和双开,后者又被称为“分身”,曾有一段时间,各种手机游戏小号、微信分身非常火,就是用的这种技术。
值得一提的是,当年那次闭门会议,几乎囊括了当时在安卓插件化方面研究最前沿的一批人,会议结束后,我请他们吃饭,拍照留念,现在一看,全是回忆。
![](https://static001.geekbang.org/infoq/cd/cd1f625cf2e18e7adfaaffc16a7f4571.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
(GMTC2016 安卓插件化闭门会议合影,后排右二是罗迪)
当时的罗迪已经被市场所发现了,我发布了采访他的文章后,有人专门给我写邮件想让我把罗迪介绍给他,张勇还告诉我有老板专门到北京就是为了看他。
再后来我没有他的消息了,不过,他给我带来了一点体会:当一个行业井喷时,会有这样超出常理的天才涌现。
Bang 和他的 JSPatch
上面介绍的技术都是安卓平台的,iOS 和安卓平台的技术差异很大,像插件化这样的技术不太可能实现。在那几年里,iOS 讨论最多的是组件化。
不过,iOS 和安卓有一个共同的需求,那就是热更新,和安卓分发渠道太多不同,iOS 需要热更新,是因为苹果审核太慢,以及审核容易发生意外,虽然苹果有快速审核通道,但那远远不够。我们需要能绕过苹果审核的更新办法。Bang 的 JSPatch 应运而生。
Bang 曾经在百度工作过,后来去了微信读书,JSPatch 就是他在这段时间开发出来,并以个人名义开源的。
Bang 是潮汕人,2016 年我邀请他参加了第一届 GMTC 大会,在短时间的接触中,感觉似乎比较腼腆,但在网络上,他有一个博客,我很喜欢看他的博文,不仅言之有物,而且能切中要害。
Bang 因为 JSPatch 而名声鹊起,GMTC 的时候他的演讲爆满,有人专门过去看他。
JSPatch 并不是第一个 iOS 热更新工具,在之前还有基于 Lua 的 WaxPatch,后来由淘宝的君展维护,但 WaxPatch 需要带一个 Lua 运行时会增大体积,而 JSPatch 则颇为小巧,借助 iOS 平台内嵌的 JS 引擎,代码行数长期保持在 2000 行以下。从 2016 年起,我了解到的国内大多数头部应用,几乎全部使用了 JSPatch,包括互相之间存在竞争的 BAT 巨头们,在注重门户之见的国内,这实在是个了不起的成就。
然而,正因为 JSPatch 的流行,当苹果决定收紧审核政策时,JSPatch 首当其冲,结果让整个中文互联网几乎都受到了影响,这个下面再谈。
百花齐放的时代
2016 年,国内的移动开发技术发展到了最鼎盛的时期。插件化/热更新成为显学,成为高级工程师的必修课。
张勇在乐视最风光的时候去了乐视体育,后来又被人鼓动,以技术入股的形式去做 PC 安卓模拟器的创业。
360 安全卫士的张炅轩等,开发了一个更完美的插件化技术 RePlugin,并在 2017 年的 GMTC 上开源。
微信发布了 Tinker,美团发布了 Robust。
聚划算的朴诚发布了 LuaView,另一个基于 Lua 的 iOS 热更新工具。
刚刚收到苹果投资的滴滴宣布合并 Uber 中国,它招募了当时 iOS 领域的大牛 Sunny 孙源和安卓的任玉刚,开始在移动技术上大展拳脚。过不久,Sunny 就推出 iOS 动态化方案 DynamicCocoa,它比 JSPatch 更加激进,已经有安卓插件化的几分模样;曾鼓捣出 Dynamic-load-apk 的任玉刚则推出安卓插件化方案 VirtualAPK,与 RePlugin 同台竞技。
QQ 还推出了一个号称史上最疯狂的 iOS 动态化方案 OCS,它们开发了一个自己的中间语言 OCScript,还开发了一个自己的虚拟机 OCSVM 去执行它……稍微懂点编程的就知道这是一个多么疯狂的方案。
那的确是一个百花齐放的时代。而身处这个时代甚至参与其中,几乎每天我都活在激动当中。
很多人不知道的是,InfoQ 的使命是推动软件技术发展,这是一个颇显狂妄的说法,技术推动社会发展,而我们要推动技术发展。我将它当作了我的职业信条。在那段时间里,我能感觉到所处领域每天都在往前发展,能感觉到我所作的事情,无论是报道和微信社群,还是线下大会和沙龙,就像拓荒一样,都在一点点地推动这个领域的外延更加扩大。没有比这更好的工作了。
当时我发现一个问题,就是这些黑科技只在国内发展,没有人把它介绍到国外去,国内外之间缺乏交流。于是我给 InfoQ 英文站的社区编辑 Sergio De Simone 写了一封邮件,看看有没有可能对国内的技术做一些报道。Sergio 是一名软件工程师,业余时间帮 InfoQ 英文站写了许多技术报道,其中大部分是移动领域的。
![](https://static001.geekbang.org/infoq/25/25a01e9d493c3f9e57e07c6b6dfefaf8.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
然而 Sergio 的回复让我比较沮丧,他认为这些技术违反苹果和谷歌的规则,不太可能在国外应用,因此报道的兴趣不大。曾经动过想把张勇推荐到国外 QCon 的心思也熄灭了。
2016 年 6 月的闭门会议上,我号召大家多多在国外网站和社区上推广插件化技术,可惜没人听进去,在我了解的范围内,唯一做过这方面的努力的是 LBE 的冯森林,他在参加 Google IO 的时候向国外工程师演示插件化的神奇,据说当时老外惊呆了。后来谷歌推出了自己的免安装应用 Instant Apps,不知道是否有受到启发。
现在回想起来,我当时可以做得更多的,即使未必有用,但总得试一试。
然而还没有等我再次鼓起勇气,苹果的打击到来了。
苹果的一封信
2017 年 3 月,众多 iOS 开发者收到警告邮件,声称其 App 违规使用动态方法,责令限时整改。
这封邮件引起了开发者的恐慌,连 React Native 都遭受池鱼之殃,经过一番寻找之后,发现问题集中出现在两个热更新工具 Rollout 和 JSPatch 上,其中 Rollout 国外用的较多,JSPatch 则主要是国内使用。
在当时的分析文章里,该事件的影响一节里我写道:
在国外,本次警告事情其实受影响并没有那么大,国外 iOS 平台热修复或热更新并不流行,Rollout 的声明里,本次只有数百个 App、数百万最终用户受到影响。
但在国内,这一数字要远远超出。去年以来,凡是公开分享过 iOS 应用架构的,都将热修复作为其基础设施之一,可以说大部分头部应用都有使用 JSPatch 或类似方案。本次受影响的国内 App 数以千计,覆盖的人群则包括几乎所有中国 iOS 用户。
更长远的影响是,热修复对一个团队的开发流程和节奏紧密相关,很多团队都必须修改相应的开发流程来适应变化。
这一判断并没有夸张,**在苹果警告之后,iOS 动态化的工具都转入地下发展,关于这方面的研究和分享也急剧减少,甚至连整个 iOS 技术的分享也变少了。**在另一篇文章里,我写道:苹果的一封邮件像《三体》的智子一样锁死了国内技术。从那以后,“iOS 开发没人要了”成为一个梗,流行起来。
![](https://static001.geekbang.org/infoq/38/38651184da03fc0f0cd78a79acee0e88.jpeg?x-oss-process=image/resize,p_80/auto-orient,1)
在安卓平台,虽然谷歌没有能力像苹果一样干涉国内的开发,但插件化技术从另一方面遭遇了困境。
这一困境就是安卓新版本以及国内各种魔改 ROM 对于底层的改动。安卓插件化技术依赖部分底层方法以及私有 API,而这些在新版本里是很有可能改动的,一旦修改了,插件化就会失效甚至出错。国内各大手机厂商的系统也喜欢对底层进行修改,它们的修改甚至都不会公开告知,因此兼容问题是插件化技术遇到的最大挑战。
评论