写点什么

专访 DroidPlugin 作者张勇:安卓黑科技是怎样炼成的

2015 年 9 月 29 日

前段时间,奇虎 360 在 Github 上发布了一个 Android 开源项目 DroidPlugin ,这是一个实现动态加载的 Android 插件框架,可以免安装、免修改的运行第三方 APK。一时间,它被誉为安卓黑科技,引起行业内的关注。

据其官方文档介绍,DroidPlugin 的目的是改进大型 APP 的架构,实现多团队协作开发。它的部分特性如下:

  • 支持 Android 2.3 - 6.0(Android M)系统版本。
  • 集成简单,将 DroidPlugin 引入到项目后仅需很少代码集成。
  • 高度隔离,宿主 App 和插件 App 之间的是完全隔离的。
  • 插件管理,插件的空进程等会被及时处理,静态广播会被当作动态处理。

DroidPlugin 的原理是利用 Android 一个进程可以运行多个 APK 的机制,通 过 API 欺骗让系统以为只有宿主 App 存在,同时通过预先占坑来创造插件 App 的运行环境,最后通过动态代理实现函数 hook、Binder 代理绕过部分系统服务限制,从而实现应用的组件化。

据 InfoQ 了解,它的作者是 360 高级工程师张勇,InfoQ 记者对其进行了采访,了解了项目背后的更多信息。同时,张勇也接受 InfoQ 邀请,将于 12 月 18 日在 ArchSummit 北京 2015 架构师大会上作“分拆:DroidPlugin 的实现原理及其应用”的分享。

受访嘉宾介绍

张勇,从2009 年开始从事Android 的研发工作,分别在机锋网、金山、360 从事过桌面、安全、市场等Android APP 的研发管理工作。2011 年加入360 手机助手团队,目前在奇虎从事360 手机助手Android 客户端的研发工作,专注于Android APP 安全、架构领域。

InfoQ:请介绍一下 DroidPlugin 项目的背景,你们为什么要开发这样一个框架呢?

张勇:之所以开发这个项目,应该算是现实的驱动,我们手助(360 手机助手)的团队并不大,但是业务特别 多,并且还有跨部门的对接,这些业务对应着手助里面不同的产品模块。我们开发和发布的节奏是“搭火车”的模式,一般每周发布个小版本,然后每个月发布一个 大版本,各个产品模块独立研发,然后在每周的固定时间整合到主应用里面发布。但这样会遇到一个问题是,各个产品模块的研发进度、时间并不统一,有的产品周 一已经开发完了,有的产品周四还没开始做,通过这样“搭火车”就有不少时间会被浪费掉。

另外,客户端发版有不少成本,一次应用更新从发布到有一定的覆盖量,通常需要一到两周时间,而新产品从上线到有一定量的反馈,也需要时间,这对于一个快速迭代的产品来说也不够高效。

所以我就想着调整我们应用的架构,将一些业务模块做成可拆分的,并且做到彻底隔离,以实现独立发版、快速放量。另外手助中的一些功能模块,公司 的其它团队也在做,并且做的比我们好,那我就想能不能把他这个模块拿过来放到手助里面,他们只需要交付一个 APK 就可以,这样既会解决掉我们重复造轮子的 问题,也不会存在开发成本、进度和版本管理等问题。

InfoQ:能介绍一下 DroidPlugin 的开发过程吗?它是如何应用到手机助手里的?

张勇:我大概从 14 年 6 月份就有想法,但当时没有时间开发,不过一直在构思怎么做,然后 14 年 12 月份我才能够把更多精力花在改善手助的架构上来。真正开发的时间不长,大概到 3 月份就做完了,但因有一些兼容性担忧,所以直到 15 年 4 月份到 5 月份,才开始慢慢应用到手机助手里面去。

一开始我还不是很自信,因为这对我们的手助改动比较大,同时 Droid Plugin 会涉及到很多系统底层的修改。不过我的领导、手助的技术负责人韩三普非常支持我,所以我就开始尝试着去做了。

实际应用的的契机不是重构,而是 App 瘦身。当时手助的 APK 越来越大,早期能控制在 2M 以内,但最后都接近 10M 了。我们知道 App 的体积对 安装的成功率影响很大,比如内存不足、dexopt 优化导致的安装失败会增加,安装失败对用户造成的挫败感特别强。同时更小的体积也会便于用户下载,所以 我们就使用了 Droid Plugin 将一些模块拆分出去、动态加载。从而实现了对手助 App 的瘦身。

在完成后,我们用灰度发布的方式来逐渐尝试。开始就试着放了几千的量,发现没什么问题,然后就是几万,十万,然后终于有一些反馈过来。主要问题 还是在适配方面,虽然我们在发布前在不同型号的手机上都做了适配性测试,但放出去还是有问题。后来我们就让用户把他们的手机寄过来,调试、修复完 bug 之 后再给他寄回去,然后继续放量、解决用户反馈,通过这样的循环,到现在已经基本没什么问题了。

InfoQ:别人都叫它安卓黑科技,您自己对它是怎么看的?

张勇:我觉得它并算是多么的“黑”,因为它还是有一些限制的,并不是百分之百的完美。在项目介绍里我也提 到,它不能发自定义的通知栏,以及 Launch Mode 的 bug,这些都表明它其实并不够完善。如果真正完善了我觉得可以称得上是黑科技,但目前来说还算不上。不过,我把它开源出来是希望对更多的 Android 开发者有帮助,如果黑科技指的是一些恶意用途的话,那我宁愿它永远不是。

InfoQ:那 DroidPlugin 的主要应用场景是什么?

张勇:其实它主要目的刚才已经提到,就是拆分模块。如果是小团队,几个人甚至独立开发应用的,那么并没有使 用它的必要,相反还会增加产品复杂性、降低代码复用率。但是对于那些平台类的大型产品,是由很多子产品组成的, 而各个子产品又是不同的团队在做,甚至在一些公司会是不同的事业部在做。像这种情况就需要这样的一款框架,因为每个子产品都有自己的开发团队,要将它们整 合起来、实现同步开发比较困难,所以最好有这样一个架子,或者说平台,让各产品团队平时可以各开发各的,他们只需要遵守一些约定即可,在集成时不需要耗费 额外的工作量。

InfoQ:Android 的动态加载有不少的实现方式,您为何选择采用动态代理技术来实现?

张勇:其实在 DroidPlugin 之前,我还做过一个 Android 的 Hook 项目,叫 ZHook ,我也把它的二进制文件放在了 GitHub 上,它可以实现对任意 Java 方法的 hook,原理和 Xposed 一样。但 ZHook 只支持 Dalvik 虚拟机,不支持 ART,并且在 Dalvik 模式下面也还有一些缺陷,所以我就转到使用动态代理。

动态代理相比较起来更可控,稳定性更好,并且 Dalvik 和 ART 两个运行时都支持、适配范围更广,比如 Android 6.0 刚出来不久,我们测试一下也都是支持的。

InfoQ:从项目介绍里我们看到宿主 App 和插件 App 是彻底隔离的,为何这样设计?

张勇:所谓彻底隔离就是说,插件 APP 直接无法直接访问、调用彼此的代码、资源,这不只是编译层面的隔离, 在运行时通过过 Java 反射等手段也无法做到,反过来框架也不关心插件里运行的代码。DroidPlugin 实现的目标之一就是彻底的拆分模块,做到插件 App 不仅能在 DroidPlugin 中运行,也能安装到系统独立运行。这样我们就可以让插件之间、框架和插件之间尽可能的减少依赖、耦合性。真正实现插 件的独立的研发、测试和发布,而不必过多的考虑插件之间兼容。

当然,实际项目里面,DroidPlugin 和插件 App 之间有通信需求的,有通行需求就有兼容问题。所以我们推荐使用 Android 的一些标准 API 来实现这些需求,比如 Intent、AIDL、ContentProvider 等机制。这样也许能将耦合性降到最低。

InfoQ:您提到这个项目是您个人开发的,那为何会以公司的名义开源出来?

张勇:这点当时没想那么多,因为这是在公司研发、也用在公司项目里面,那么以公司名义开源是很自然的事情。 另外 360 一向很重视开源,我们在 GitHub 上有一个统一的账户,所以我也很乐意将它加入进去。我把它以公司的名义开源出去,能够表明它是经过实践检验 的,能吸引更多的人来用,找出问题,回馈项目,这样可以形成一个良性的循环。这样大家可以一起来把这个框架做得更好。

InfoQ:DroidPlugin 后续有哪些开发计划?

张勇:第一个是继续完善框架,在项目介绍里也提到还有一些缺陷,后面我们会逐步解决掉。第二个是可能会去加 一些新的功能,比如说插件之间的依赖控制、一套低耦合的通讯机制等等。第三是目前用户使用的这些接口还不是太友好,我想稍微改一改,让它更易用一些。最后 等 API 稳定以后,可能会补上一些文档。

InfoQ:本次采访就到这里,感谢您接受采访。

2015 年 9 月 29 日 21:3410846
用户头像

发布了 164 篇内容, 共 93.3 次阅读, 收获喜欢 381 次。

关注

评论

发布
暂无评论
发现更多内容

Spring全家桶笔记:Spring+Spring Boot+Spring Cloud+Spring MVC

Crud的程序员

Java spring 程序员 架构

为什么你家的 K8s 应用平台不好用?

孙健波

Kubernetes PaaS KubeVela

胜天半子!阿里内部力荐SpringBoot全栈笔记全网首发,源码实战齐飞

Java架构之路

Java 程序员 架构 面试 编程语言

关于JDK15的简单理解

Java架构师迁哥

万字带你深入阿里开源的Canal工作原理

大数据老哥

大数据 canal

你kin你擦!阿里终于肯把内部高并发编程高阶笔记开源出来了

Java架构之路

Java 程序员 架构 面试 编程语言

跨界融合,区块链推动实体经济提档升级

CECBC区块链专委会

人工智能 云计算 大数据

永续合约APP系统软件开发

开發I852946OIIO

系统开发

《价值》- 护城河(6)

石云升

读书笔记 护城河 28天写作

EXCEL数据太“脏”无从下手?何须用python,ETL一分钟搞定

智分析

Excel ETL

AES128解密只能解一半的问题

李日盛

AES 问题定位

实现数字经济和实体经济深度融合

CECBC区块链专委会

区块链

客户服务高触达,零代码从短信/邮件跳转小程序客服

环信

Soul网关源码阅读(八)路由匹配初探

Java 源码阅读 网关

DDD分层架构最佳实践

程序员小毕

Java 编程 架构 面试 DDD

认识产品经理(第一节)

让我思考一会儿

百度首届智能小程序高校大赛圆满结束:关注学生心理健康小程序获全国一等奖

DT极客

江苏智慧平安社区建设,智慧社区管理平台开发

135深圳3055源中瑞8032

区块链电子合同技术方案,区块链电子合同存证

135深圳3055源中瑞8032

阿里开源SpringSecurity:用户+案例+认证+框架

996小迁

Java 程序员 架构 面试 springsecurity

蝉联 Apache 最活跃项目,Flink 社区是如何保持高速发展的?

Apache Flink

flink

第一周作业

Esther

​Kubernetes资源清单篇:如何创建资源?​

xcbeyond

Kubernetes 28天写作 Kubernetes从入门到精通

Redis 学习笔记 08:数据结构与对象小结

架构精进之路

redis 七日更 28天写作

架构师训练营第三周作业 - 学习总结

阿德儿

LeetCode题解:105. 从前序与中序遍历序列构造二叉树,递归+哈希表,JavaScript,详细注释

Lee Chen

算法 LeetCode 前端进阶训练营

首次公开!阿里巴巴技术团队共同携手编写的“大厂面试参考指南”v1.0版本

Crud的程序员

Java 架构 面试

阿里云 RTC QoS 屏幕共享弱网优化之若干编码器相关优化

阿里云视频云

音视频 WebRTC 网络 RTC 视频会议

一文读懂 Serverless,将配置化思想复用到平台系统中

Serverless Devs

Serverless 云原生 PaaS

边缘安全 | 正确使用CDN 让你更好规避安全风险

阿里云Edge Plus

安全 CDN

数字货币应用从C端走向B端 实践中这些难题仍需关注

CECBC区块链专委会

数字货币

开源中间件技术学习路线

开源中间件技术学习路线

专访DroidPlugin作者张勇:安卓黑科技是怎样炼成的-InfoQ