Skip to content
galenlin edited this page Jun 6, 2016 · 22 revisions
  1. 插件是否一定得内置到APK中,如果一定要内置,那这个框架仅仅是为了开发工程中解耦?

内置是为了首次启动更快,如果不内置也行,可以在启动页下载插件。

  1. 目前开源的插件开发框架有很多,Small 跟这些框架的区别是什么,优缺点呢?
  2. 百度工程师开发的 Dynamic-load-apk
  3. FinalLody开源的 Direct-Load-apk
  4. limpoxe开源的 Android-Plugin-Framework
  5. bunnyblue开源的 ACDD
  6. 携程工程师开发的 DynamicAPK
  7. 360工程师开发的 DroidPlugin
  1. dynamic-load-apk使用代理的方式实现Activity生命周期,插件中不能用this,不够透明;

  2. Direct-Load-apk对dynamic-load-apk进行了改进,支持this。但也是用代理Activity,实现较为繁琐;

  3. Android-Plugin-Framework是一个相对完整的框架,但资源分区方案还不够理想,不支持加载.so插件;

  4. ACDD 使用了osgi,没有细看。。坑点是资源分区要使用修改aapt源码再重新编译的方案;

  5. DynamicAPK 坑点:修改aapt源码,不支持.so插件;

  6. DroidPlugin支持对完整apk的动态加载,但是没有关于非独立插件的加载(资源分区要复杂得多);

  7. 这些框架似乎都不支持AppCompat包(但这很重要,材料设计的Design包等都依赖AppCompat);

  8. Small的开发其实是跟随1、2、3走过来的。从实际场景出发,基于“轻量、透明、极小化、跨平台”的理念: * 把核心代码量控制在了一个文件(ApkBundleLauncher)500行以内 * 不修改aapt源码,实现了资源id PP段的再分配(原理见Dynamic load resources) * 通过对aapt生成的二进制文件的后期加工,最大化分离无用的资源,使得插件包最小达到4k左右 * 支持对本地化网页进行插件打包,实现跨平台

  9. 目前大多插件框架对Service的支持不太好,Small是否支持,支持度怎么样。

支持动态加载,不支持动态注册。实际场景中,Service的更新频度较低,注册可以预埋在宿主的manifest文件中。

  1. 插件与宿主必须运行在同一个进程吗? 是否支持插件运行在单独的进程中。

在同一个进程。

  1. 当插件与宿主共有一个控件时(比方说自己写了一个下拉刷新的控件),开发过程中是不是要插件和宿主里面都含有这个控件? 同样,是否允许插件访问宿主的资源(比如说res)以及数据(SharedPreferences中的数据)。

插件中所有的公共资源、类将会被分离。宿主、各个插件之间的资源可以互相访问,支持SharedPreferences,完全透明。

  1. 为什么偶尔出现pre-verified异常?

这个问题属于dex热修复范畴。首先出现这个问题的充分条件:
    (1) 一个“独善其身”的A.dex(所有的类引用都在本dex内,没有跨dex调用)
    (2) 另一个B.dex包含(1)中的某个类XiaoMing
    (3) 一个类加载器同时加载了(1)跟(2),查找时(2)优先于(1)
当程序试图调用XiaoMing时,在B中发现了,但是回头一看XiaoMing早已被A包养了。遂崩溃。
通常我们并不满足(1)。插件并非独立的,或多或少依赖于宿主包或者公共库,难以“独善其身”,无法被打上CLASS_ISPREVERIFIED标签。
/!\ 当出现这个问题时,请确认在不同的插件中是否引用了同一个第三方库或者其不同版本。

  1. 为什么我能编译通过,但是Android Studio IDE里一堆红色错误提示?

IDE认的是Debug模式下的代码,找不到便会出现红色错误。解决方法:Build->Clean

  1. 能不能下载插件?

支持。

  1. 下载了Sample,一启动就“闪退”?

如果log没有任何异常信息,请确认已经按照文档先编译插件:buildLib, buildBundle。
如果出现log: Package xx has no certificates at entry AndroidManifest.xml; ignoring!,请先设置签名。

  1. Small.setBaseUri怎么设置?有什么用?

这个是用于跨平台的,如果没有web类场景(本地网页插件、M站、PC站点)可以忽略。
用途示例:Small.setBaseUri("http://m.wequick.net/demo/");
那么在网页中点击链接"http://m.wequick.net/demo/xx.html",可以调用到本地的xx插件模块。

  1. Sample和DevSample什么关系?

DevSample是源码所在,其中的buildSrc发布后形成Sample里的net.wequick.tools.build:gradle-small:发布版本,small发布后形成Sample里的aarVersion = 'small发布版本'
DevSample是面向所有的开源贡献者或者想要调试源码的人;Sample则是面向普通开发者。
通常DevSample的代码会比较新,当累计更新到一定程度(实现某个功能、修复一定issue)后,会进行发布。
发布到Sample才是意义所在,这个过程需要更多人关注到DevSample的源码,更多的贡献、更积极的反馈都有助于这个过程的推进。

  1. 怎么测试升级呢?
  1. 要升级的插件增加其versionCode,重新编译:gradlew :app.xx:aR -q; (P.s. -Dbundle.arch=xx可以指定输出)
  2. 把升级的插件放到你的服务器上,假设URL为A
  3. 下载A到补丁包路径:bundle.getPatchFile()
  4. 标记升级:bundle.upgrade()
  5. 把应用退到后台再回来,更新即生效
    示例代码见Sample/app.home/MainFragment
  1. Cause: net/wequick/gradle/RootPlugin : Unsupported major.minor version 52.0

需要在本机安装JDK1.8,Windows用户可能需要重设环境变量。
验证安装成功方法:在命令行输入javac -version看是否为javac 1.8.0_xx

致谢

感谢以下开发者的提问: