标签:异常 开发 wifi 存在 比例 学习 组件 打补丁 兼容性问题
“RePlugin将在6月底开源,这将是我们献给安卓世界最好的礼物。”当我们宣布这一消息时,心中的激动,无以言表。是的,三年的“厚积”,如今的“薄发”,看似平凡的话,实际上却饱含了我们太多的激动、辛酸与泪。
那么今天,我们就来详细的和您聊一聊,这个从2014年中旬,正式在手机卫士上启用,并即将开源的360 RePlugin,究竟能为我们,更为您能带来什么。
GitHub地址:https://github.com/Qihoo360/RePlugin。欢迎您为RePlugin项目加Star、发送Pull Request,提Issue。我们会竭尽所能回答您们的疑惑。
RePlugin是一套完整的、稳定的、适合全面使用的,占坑类插件化方案。其主要优势有:
RePlugin的核心优势
RePlugin与现有插件化框架的对比
在讲述我们团队为何要在2013年底,设计一套属于自己的插件化之前,我们先来简单谈谈,有了插件化方案后,能为我们带来多大的便利,它究竟解决了什么问题。
如上所述,无论是对用户,还是对开发者而言,使用插件化框架都是大有益处的,理应做到“飞入寻常应用家”。
然而,在实际调查过程中,我们却发现了一个和这些好处完全不匹配的奇怪现象。究竟是什么呢?
虽然我事先已做好功课,然而在一次技术大会上的调查结果却让人大跌眼镜——在参会的200多位安卓开发者中,仅有不足5%的比例,使用了插件化方案。超过九成的开发者,目前上没有将插件化应用在软件开发之中。
实际上,这和我们在线下观察到的结果基本吻合。结合之前的调查,我们发现,有三大挑战制约了插件化在Android开发界的普及:
然而,通过我们多年的实践证明,以上三大挑战,其实是可以被攻克的。这也是我们今天要为您介绍的,360手机卫士首款Android开源项目——RePlugin。
既然这么大胆,那么,我们究竟是怎么做到的呢?
前文提到,不够稳定的主要原因是Hook了太多。那么市面上比较灵活的插件化框架,究竟Hook了哪些呢?
注意:这里所说的“Hook”是指通过Java反射手段,获取并修改与系统Server等交互的Internal API,来让框架正常工作的行为,如上面所列部分。正常情况下的反射(例如反射类内部自己的字段)不属于Hook。
看似灵活,然而下列三种情况,将很有可能导致插件甚至应用,彻底不能工作:
基于上述的情况,我们团队在2014年初,研究全新占坑插件化框架(注意,此时DroidPlugin类方案还没有出现)时,就定了个“小目标”:让Hook越少越好。经过一次次的研究讨论,最终确定只Hook一个点:ClassLoader,且要求“坚持到底”,所有改动都是基于此来展开。
对我们而言,这是里程碑式的决定,即便到现在来看也是如此。
修改ClassLoader的点其实不难,如上图所示逐步反射即可。然而需要注意的是,这个ClassLoader一定得继承自PathClassLoader,防止Android 7.x因使用addDexPath而有问题。
除此之外,此ClassLoader所在位置也非常稳定。目前来看,从Android 2.1至今都没有发生过位置、名称上的变化,可以长期使用。
关于这一点,我们之后会有一篇文章来详述,敬请期待。
前文提到,就目前市面上的插件化框架而言,若做的足够稳定,则多少会失去一些灵活性。对于我们拥有这么多模块的产品而言,这同样也是不可接受的。
为此,我们在“坚持一个Hook点”原则的前提下,通过不断创新,最终解决了上述问题。
我们的核心思路,是2015年以后才开始“老生常谈”的一个词,那就是:坑位。
当然,我们当初设计坑位思想(恕我再强调,是2014年初)时,也绝不仅仅针对Activity,而是整个四大组件,甚至到了后期,连Theme、进程、Task-Affinity等都做到了“坑位化”,只不过实现方式各异而已。
因篇幅所限,这里仅以常用的Activity来简述。有关更详细的内容,欢迎继续关注我们的《RePlugin深度剖析》系列文章。
目前市面上的完整坑位方案,Hook的地段可以说是“各有千秋”,从AMS、Instrumentation到ContextImpl都有,并以此让插件变得更灵活。
而我们的方案和他们有些不同:除了ClassLoader是Hook的,其余一律不需要。那么我们究竟是如何开启一个插件的Activity呢?
简单来说,我们有五个核心步骤:
其中,PM.startActivity可以由插件/宿主直接调用。若在插件内部,则可以直接通过startActivity方法来打开,更为方便。
当然,这只是核心思路,而每一步我们都会做各免费催收系统软件种逻辑处理,尤其是“寻找坑”一节,这也是我们的核心之一。
找坑是有非常多的注意点:
篇幅所限,以后会写详细介绍,敬请期待。
通过刚才的叙述,像PM.startActivity等确实可通过一些方法,来让插件“无成本使用”。但是,像Provider的调用(本质是IContentProvider),Service的stopSelf(是final的),以及因涉及坑位分配,而不得不需复写相应方法的Activity等。这里面存在两个矛盾点:
利弊相间,令人头疼。
针对这个问题,我们的核心理念是:“绝不在Hook及稳定性上做任何妥协”,转而创新性的做一套“动态编译方案”,力图从“编译期”来解决这个难题。
大体而言,就是把一些我们认为需要开发者修改的类和方法,借助神奇的JavaAssist来做自动化修改,这样可节省开发者的改动成本,达到想要的效果。
一图以蔽之:
而做到了这一点以后,你会发现,下面的“梦想”就变成了现实:
例如,有个名叫“360桌面”的应用,它想把自己变成“插件”跑起来。那么,有了“动态编译方案”,结合“插件类库”和框架的支持,最终的效果是——只需改几行Gradle,就能直接生成一个APK。这个APK:
是的,就是这么的神奇!
当然远不止这些。我在曾演示过一段视频,将庞大又复杂的360桌面变成插件,运行在360手机卫士中。
试想,一个桌面插件涉及到的功能是“方方面面”的,小到TaskDesription和SO的使用,大到四大组件、Task-Affinity坑位、静态Receiver和进程坑位的处理,都需一一兼顾。所以,要做到这一点,绝不仅仅是前面所说的那几点就能搞定的。
当然,“让360桌面变成插件”,还不是最有意义的。真正让RePlugin变得更有意义的,就是拿我们的360手机卫士来“开刀”,让数百个——甚至说,近乎一切——的模块,都成为RePlugin的插件,并完美的运行起来。
前文提到,之所以“功能丰富项目专用”,主要和目前市面上的插件化方案的定位有关,以至于开发者认为:“插件 = 免安装”、“基础放在主程序里更放心”、“插件开发成本高”等。
然而,仔细分析深层原因后发现,其实最为核心的原因,是插件化和相关框架(包括热更新方案等)的“定位”不同。我知道的有:
那么,我们是这三种目标之一吗?
显然,都不是。那么,我们的目标究竟是什么?
我们的目标只有一个:全面插件化。
也就是说,无论是UI、核心业务、合作插件、后台服务,还是基础功能,都可以变成插件,并在RePlugin框架内稳定又灵活的运行起来。甚至,不仅大项目能用,小项目——甚至只是个计算器——都可以使用RePlugin来提升自己的灵活性,并最终实现“插件满天下”的神奇效果。
而这一点,则是我们,和目前市面上大多数插件化框架的主要差异。
目前手机卫士已有的插件,可以分为以下几类,供各App开发者参考:
而这样的插件,我们有102个。可以想见,一旦这些插件不能用,那么手机卫士瞬间变空壳。三年已过,回头想想,值得回味。
说到这儿,让我想起了Lody(VirtualApp作者,高中大牛)在一次采访时说过一段话:
“插件化技术的成熟程度虽然在最近几年呈上升趋势,但是总体而言仍然处于初、中级阶段。App沙盒技术的出现就是插件化发展的创新和第一阶段的产物。在未来,我相信很多插件化技术会被更多的应用,如果插件化稳定到了一定的程度,甚至可以颠覆App开发的方式。”
这,其实也是RePlugin的终极价值,那就是——让插件化能“飞入寻常应用家”,做到稳定、灵活、自由,大小项目兼用。
当然,在“全面插件化”甚至“全民插件化”的道路上,我们还有太多的路要走,而如此庞大又复杂的RePlugin,是十多位研发人员共同努力的成果,且得到了部门领导,和公司技术委员会的大力支持。我相信,RePlugin的开源,是一场新的开始
标签:异常 开发 wifi 存在 比例 学习 组件 打补丁 兼容性问题
原文地址:http://www.cnblogs.com/redis2017/p/7100728.html