Android FAQ

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

致谢

感谢以下开发者的提问:

You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.