张炅轩
,现任360手机卫士主程序架构负责人,RePlugin 项目发起人之一兼技术负责人。9岁学习编程,19年编程生涯,7年以上商业(公司)研发经验。拥有83项国内外发明专利。拥有自己的Deapk项目,参与Cnpack(15岁时)、AndroidAnnotations等知名开源项目的研发
2013年底我们团队决定设计一套属于自己的插件化方案。因为对于用户和开发者而言,插件化都有着使用插件化框架都是大有益处的。
对于用户而言,插件化能做到一切按需,并能随时体验新版。利用插件化方案,可以让您的应用变得“小而精”。只有当用户需要使用某个特定功能时,才可以下载并开启,且可以随时卸载插件。而且不用去应用市场等到大包升级,用户可以随时体验到新版的应用。
对于开发者而言,它更是具有发版灵活、组织结构灵活、Android原生等优势。这意味着他们不用等市场上线,等用户主动升级而错过宝贵的时机,并由原来的“统一作战”变成“百团作战”,每个团队都在开发“自己的插件单品”,制定自己的发版计划,可以让团队形成“模块意识”。当然,插件间、插件与宿主间允许有适度的耦合,但不会是“毫无控制”的那种。和动态化(RN类)不同,您可以使用最熟悉的Java/Kotlin语言,及各种原生API来开发您的插件。
所以,插件化理应做到“飞入寻常应用家”。
但我们在调查中,却发现了一个和这些好处完全不匹配的奇怪现象。GMTC 参会的200多位安卓开发者中,仅有不足5%的比例,使用了插件化方案。超过九成的开发者,目前上没有将插件化应用在软件开发之中。
目前市面上很多人对插件化有一些疑惑和担忧主要源于其不够稳定和灵活。因Hook点较多,导致了插件化不是非常稳定。很多大型项目担心出现应用崩溃、插件无法正常使用等问题,而另一方面一旦插件有较大改动,如新增Activity、Service、进程等,就需要主程序发版。还有一些人认为只有“非核心”模块,才会考虑做成插件,使得插件化的应用范围非常狭窄。
刚才提到插件化不够稳定的主要原因是Hook了太多。那么市面上比较灵活的插件化框架,究竟Hook了哪些呢?
(注意:这里所说的“Hook”是指通过Java反射手段,获取并修改与系统Server等交互的Internal API,来让框架正常工作的行为)
看似灵活,但遇到Android升级、ROM修改和使用不当时,将很有可能导致插件甚至应用,彻底不能工作。基于这些情况,我们团队在2014年初,研究全新占坑插件化框架(注意,此时DroidPlugin类方案还没有出现)时,就定了个“小目标”:让Hook越少越好。经过一次次的研究讨论,最终确定只Hook一个点:ClassLoader,且要求“坚持到底”,所有改动都是基于此来展开。对我们而言,这是里程碑式的决定,即便到现在来看也是如此。
但是就目前市面上的插件化框架而言,若做的足够稳定,则多少会失去一些灵活性。对于我们拥有这么多模块的产品而言,这同样也是不可接受的。
为此,我们在“坚持一个Hook点”原则的前提下,通过不断创新,最终解决了上述问题。我们的核心思路,是2015年以后才开始“老生常谈”的一个词,那就是:坑位。
坑位方案
可以做到“一对多”的关系。例如插件有个XXXActivity,则运行时,主程序可以将自己的N1ST1对应到这个XXXActivity上。一旦该Activity退出,则N1ST1就“空闲”出来。而当YYYActivity进来后,又会重新占用N1ST1。这样就可以做到一个坑位(如N1ST1)对应多个实体。
此外,这个YYYActivity既可以是已有的,也可以是插件新增的。这样无论插件如何升级,主程序都可以不用动,即可支持新的Activity。
当然,我们2014年初设计坑位思想时,也绝不仅仅针对Activity,而是整个四大组件,甚至到了后期,连Theme、进程、Task-Affinity等都做到了“坑位化”,只不过实现方式各异而已。
之所以“功能丰富项目专用”,主要和目前市面上的插件化方案的定位有关,以至于开发者认为:“插件 = 免安装”、“基础放在主程序里更放心”、“插件开发成本高”等。
然而,仔细分析深层原因后发现,其实最为核心的原因,是插件化和相关框架(包括热更新方案等)的“定位”不同。我知道的有组件化、动态插件化、免安装应用和热修复等等,但这些都不是我们的目标。
我们的目标只有一个,那就是全面插件化。就是以RePlugin为代表。其目的是“尽可能多的让模块变成插件”,并在很稳定的前提下,尽可能像开发“单品”那样灵活,并享受插件化方案带来的各种好处
也就是说,无论是UI、核心业务、合作插件、后台服务,还是基础功能,都可以变成插件,并在RePlugin框架内稳定又灵活的运行起来。甚至,不仅大项目能用,小项目——甚至只是个计算器——都可以使用RePlugin来提升自己的灵活性,并最终实现“插件满天下”的神奇效果。
而这一点,则是我们,和目前市面上大多数插件化框架的主要差异。
把插件化的三大挑战攻克后,就是我们今天看到的360手机卫士首款Android开源项目——RePlugin。RePlugin是一套完整的、稳定的、适合全面使用的,占坑类插件化方案。其主要优势有:
-
极其灵活:
主程序无需升级(无需在Manifest中预埋组件),即可支持新增的四大组件,甚至全新的插件
-
非常稳定:
Hook点仅有一处(Classloader)。其崩溃率做到仅为“万分之一”,并完美兼容市面上近乎所有的Android ROM。
-
特性丰富:
支持近乎所有在“单品”开发时的特性,包括静态Receiver、Task-Affinity、自定义Theme、进程坑位、AppCompat等
-
进程任意:
可让各组件跑在UI、常驻,甚至是“任意坑位进程”
-
易于集成:无论插件还是主程序,只需“数行”就能完成接入
-
自由隔离:
想隔离就隔离(如不稳定或占资源的插件,易于释放),不想隔离的模块就混用(如各种基础、UI插件,都跑在UI进程内,性能优异)
-
管理成熟:
拥有成熟稳定的“插件管理方案”,支持插件安装、升级、卸载、版本管理,甚至包括进程通讯、协议版本、安全校验等
-
数亿支撑:
有360手机卫士庞大的数亿用户做支撑,三年多的残酷验证,确保App用到的方案是最稳定、最适合使用的
截止2017年6月底,RePlugin的:
-
插件数已达102个(其中,核心基础插件57个)
-
插件占应用比(指把代码资源铺开,插件占整个应用的比例)高达83%
-
年发版次数高达596次(平均每个工作日发版2-3次)
-
此外,目前 360 公司几乎所有的亿级用户量的APP,以及多款主流第三方APP,都采用了RePlugin方案。
总而言之,你们现在看到的RePlugin,可以说是“久经沙场”、“历经风雨”的方案,是在数亿设备上,历经三年多时间验证的成熟方案,也是可以直接拿来为你们所用的,稳定与灵活兼得的方案。
说到这儿,让我想起了Lody(VirtualApp作者,高中大牛)在接受InfoQ采访,即将结束时所说的那段话:
“插件化技术的成熟程度虽然在最近几年呈上升趋势,但是总体而言仍然处于初、中级阶段。App沙盒技术的出现就是插件化发展的创新和第一阶段的产物。在未来,我相信很多插件化技术会被更多的应用,如果插件化稳定到了一定的程度,甚至可以颠覆App开发的方式。”
这,其实也是RePlugin的终极价值,那就是——让插件化能“飞入寻常应用家”,做到稳定、灵活、自由,大小项目兼用。
当然,在“全面插件化”甚至“全民插件化”的道路上,我们还有太多的路要走,而如此庞大又复杂的RePlugin,也绝不可能是一两个人在战斗,而是十多位研发人员共同努力的成果,且得到了部门领导,和公司技术委员会的大力支持。我相信,RePlugin的开源,是一场新的开始。这不仅仅是一个决定,而是一份信念,让全社区的有志之士能一起参与进来,共同为中国乃至世界App提供一套“全面插件化”的完美方案而努力。
码云地址:https://gitee.com/replugin/RePlugin
更多干货请前往公众号菜单栏“读我”->“干货分享”查看。