Android Plugin 插件化技术-Small插件框架
2017-02-03 09:31
477 查看
版权声明:本文为博主原创文章,未经博主允许不得转载。目录(?)[+]本篇文章只是整理了一些流行的开源插件化技术,其中言论纯属开源作者,不代表本人观点。
一、Small 简介:做最轻巧的跨平台插件化框架
完美内置
所有插件支持内置于宿主包中
高度透明
插件编码、布局编写方式与独立应用开发无异
插件代码调试与整包开发无异
极致剪裁
对插件分离所有一切能分离的公共代码、资源
无缝链接
通过设定URI,宿主、本地化应用插件、本地化web插件、在线网页,以及任何自定义的插件之间能够相互调起与传递参数
跨平台
目前已支持Android、iOS以及html5插件。并且三者之间可以通过同一套javascript接口进行通信。
二、Small Android(支持平台:Android API 15(4.0.3))
各个插件框架功能对比:
[1] 独立插件:一个完整的apk包,可以独立运行。比如从你的程序跑起淘宝、QQ,但这加载起来是要闹哪样?
非独立插件:依赖于宿主,宿主是个壳,插件可使用其资源代码并分离之以最小化,这才是业务需要嘛。
-- “所有不能加载非独立插件的插件化框架都是耍流氓”。
[2] ACDD加载.so用了Native方法(libdexopt.so),不是Java层,源码似乎未共享。
[3] Service更新频度低,可预先注册在宿主的manifest中,如果没有很好的理由说服我,现不支持。
[4] 要实现宿主、各个插件资源可互相访问,需要对他们的资源进行分段处理以避免冲突。
[5] 这些框架修改aapt源码、重编、覆盖SDK Manager下载的aapt,我只想说“杀(wan)鸡(de)焉(kai)用(xin)牛(jiu)刀(hao)”。
Small使用gradle-small-plugin,在后期修改二进制文件,实现了PP段分区。
[6] 使用public-padding对资源id的TT段进行分区,分开了宿主和插件。但是插件之间无法分段。
[7] 除了宿主提供一些公共资源与代码外,我们仍需封装一些业务层面的公共库,这些库被其他插件所依赖。
公共插件打包的目的就是可以单独更新公共库插件,并且相关插件不需要动到。
[8] AppCompat: Android Studio默认添加的主题包,Google主推的Metrial Design包也依赖于此。大势所趋。
[9] 联调插件:使用Android Studio调试宿主时,可直接在插件代码中添加断点调试。
透明度
三、Small Android 集成步骤:
一、Small 简介:做最轻巧的跨平台插件化框架
完美内置
所有插件支持内置于宿主包中
高度透明
插件编码、布局编写方式与独立应用开发无异
插件代码调试与整包开发无异
极致剪裁
对插件分离所有一切能分离的公共代码、资源
无缝链接
通过设定URI,宿主、本地化应用插件、本地化web插件、在线网页,以及任何自定义的插件之间能够相互调起与传递参数
跨平台
目前已支持Android、iOS以及html5插件。并且三者之间可以通过同一套javascript接口进行通信。
二、Small Android(支持平台:Android API 15(4.0.3))
各个插件框架功能对比:
DyLA : Dynamic-load-apk @singwhatiwanna, 百度 DiLA : Direct-Load-apk @melbcat APF : Android-Plugin-Framework @limpoxe ACDD : ACDD @bunnyblue DyAPK : DynamicAPK @TediWang, 携程 DPG : DroidPlugin @cmzy, 360功能
\ | DyLA | DiLA | ACDD | DyAPK | DPG | APF | Small |
---|---|---|---|---|---|---|---|
加载非独立插件[1] | × | x | √ | √ | × | √ | √ |
加载.so插件 | × | × | ! [2] | × | × | × | √ |
Activity生命周期 | √ | √ | √ | √ | × | √ | √ |
Service动态注册 | × | × | √ | × | × | √ | x [3] |
资源分包共享[4] | × | × | ! [5] | ! [5] | × | ! [6] | √ |
公共插件打包共享[7] | × | × | × | × | × | × | √ |
支持AppCompat[8] | × | × | × | × | × | × | √ |
支持本地网页组件 | × | × | × | × | × | × | √ |
支持联调插件[9] | × | x | × | × | × | × | √ |
非独立插件:依赖于宿主,宿主是个壳,插件可使用其资源代码并分离之以最小化,这才是业务需要嘛。
-- “所有不能加载非独立插件的插件化框架都是耍流氓”。
[2] ACDD加载.so用了Native方法(libdexopt.so),不是Java层,源码似乎未共享。
[3] Service更新频度低,可预先注册在宿主的manifest中,如果没有很好的理由说服我,现不支持。
[4] 要实现宿主、各个插件资源可互相访问,需要对他们的资源进行分段处理以避免冲突。
[5] 这些框架修改aapt源码、重编、覆盖SDK Manager下载的aapt,我只想说“杀(wan)鸡(de)焉(kai)用(xin)牛(jiu)刀(hao)”。
Small使用gradle-small-plugin,在后期修改二进制文件,实现了PP段分区。
[6] 使用public-padding对资源id的TT段进行分区,分开了宿主和插件。但是插件之间无法分段。
[7] 除了宿主提供一些公共资源与代码外,我们仍需封装一些业务层面的公共库,这些库被其他插件所依赖。
公共插件打包的目的就是可以单独更新公共库插件,并且相关插件不需要动到。
[8] AppCompat: Android Studio默认添加的主题包,Google主推的Metrial Design包也依赖于此。大势所趋。
[9] 联调插件:使用Android Studio调试宿主时,可直接在插件代码中添加断点调试。
透明度
\ | ACDD | DyAPK | APF | Small |
---|---|---|---|---|
插件Activity代码无需修改 | √ | √ | √ | √ |
插件引用外部资源无需修改name | × | × | × | √ |
插件模块无需修改build.gradle | × | x | × | √ |
Step 1. Clone Small (下载源码)
> cd [你要放Small的目录] > git clone https://github.com/wequick/Small.git[/code]强烈建议使用git命令行,方便更新维护。Windows用户入口: href="http://git-scm.com/downloads" target=_blank>Git for Windows
后续更新可以使用命令:git pull origin masterStep 2. Import Sample project (导入示例工程)
打开Android Studio,File->New->Import Project... 选择Sample文件夹,导入。
Sample示例工程
app宿主工程
app.*包含Activity/Fragment的组件
lib.*公共库组件
web.*本地网页组件
sign签名文件
顺便说下,这些app.*跟web.*可以从工具栏的
按钮单独运行。
其中app.home无法单独运行是因为它只包含一个Fragment,没有Launcher Activity。Step 3. Build libraries (准备基础库)
> [./]gradlew buildLib -q (-q是安静模式,可以让输出更好看,也可以不加)Step 4. Build bundles (打包所有组件)
> [./]gradlew buildBundle -q (-q是安静模式,可以让输出更好看,也可以不加)
步骤3跟4,如果你喜欢,也可以在Gradle任务导航里运行
单独编译一个组件可以使用 [./]gradlew -p web.about assembleRelease
或者Step 5. Import DevSample project (导入开发工程)
打开Android Studio,File->New->Import Project... 选择DevSample文件夹,导入。
DevSample开发工程
buildSrc组件编译插件,用于打包组件
small核心库,用于加载组件
buildSrc在修改后会被自动编译。其他步骤同上。除了编译单个组件的命令有所不同:> [./]gradlew :app.main:assembleReleaseP.s. gradlew命令支持缩写,比如assembleRelease可以缩写为aR
四、实现Android插件化的核心技术:
Android dynamic load classes
Android dynamic load resources
Android dynamic register activities
五、常见问题 FAQ
插件是否一定得内置到APK中,如果一定要内置,那这个框架仅仅是为了开发工程中解耦?内置是为了首次启动更快,如果不内置也行,可以在启动页下载插件。
目前开源的插件开发框架有很多,Small 跟这些框架的区别是什么,优缺点呢?
把核心代码量控制在了一个文件(ApkBundleLauncher)500行以内
不修改aapt源码,实现了资源id PP段的再分配(原理见Dynamic load resources)
通过对aapt生成的二进制文件的后期加工,最大化分离无用的资源,使得插件包最小达到4k左右
支持对本地化网页进行插件打包,实现跨平台
dynamic-load-apk使用代理的方式实现Activity生命周期,插件中不能用this,不够透明;
Direct-Load-apk对dynamic-load-apk进行了改进,支持this。但也是用代理Activity,实现较为繁琐;
Android-Plugin-Framework是一个相对完整的框架,但资源分区方案还不够理想,不支持加载.so插件;
ACDD 使用了osgi,没有细看。。坑点是资源分区要使用修改aapt源码再重新编译的方案;
DynamicAPK 坑点:修改aapt源码,不支持.so插件;
DroidPlugin支持对完整apk的动态加载,但是没有关于非独立插件的加载(资源分区要复杂得多);
这些框架似乎都不支持AppCompat包(但这很重要,材料设计的Design包等都依赖AppCompat);
Small的开发其实是跟随1、2、3走过来的。从实际场景出发,基于“轻量、透明、极小化、跨平台”的理念:
百度工程师开发的 Dynamic-load-apk
melbcat开源的 Direct-Load-apk
limpoxe开源的 Android-Plugin-Framework
bunnyblue开源的 ACDD
携程工程师开发的 DynamicAPK
360工程师开发的 DroidPlugin
目前大多插件框架对Service的支持不太好,Small是否支持,支持度怎么样。支持动态加载,不支持动态注册。实际场景中,Service的更新频度较低,注册可以预埋在宿主的manifest文件中。插件与宿主必须运行在同一个进程吗? 是否支持插件运行在单独的进程中。在同一个进程。当插件与宿主共有一个控件时(比方说自己写了一个下拉刷新的控件),开发过程中是不是要插件和宿主里面都含有这个控件? 同样,是否允许插件访问宿主的资源(比如说res)以及数据(SharedPreferences中的数据)。插件中所有的公共资源、类将会被分离。宿主、各个插件之间的资源可以互相访问,支持SharedPreferences,完全透明。
顶
0
踩
0
上一篇Android Hot patch 技术:Dexposed-来自阿里手机淘宝部门的开源项目
相关文章推荐
- Android Plugin 插件化技术-Small插件框架
- Android Plugin 插件化技术-Small插件框架
- [技术研究]Android插件化技术学习(Small插件框架)
- 插件化技术-Small插件框架
- Android Small插件化框架--启动插件Activity源码解析(上)
- Android 插件化原理 完胜360插件框架 技术实战
- Android Small插件化框架--启动插件Activity源码解析(上)
- android插件化small框架初探(一)
- Android Small插件化框架源码分析
- Android插件化框架和热修复技术的资料收集和汇总
- android插件化small框架初探(一)
- android插件化small框架初探(一)
- Android Plugin 插件化技术:DroidPlugin
- Android自助餐之插件化(使用Small框架)
- Android插件化框架和热修复技术的资料收集和汇总
- android插件化small框架初探(一)
- android插件化small框架初探(一)
- Android插件化(使用Small框架)
- Android插件化框架研究-DroidPlugin
- android-pluginmgr不需要插件规范的apk动态加载框架