如何构建一个存储接口所有实现名称的sbt插件?

时间:2016-12-14 01:47:55

标签: android sbt

我正在尝试做不可能的事情,似乎并没有起作用。总体目标是:我有一个Component接口,我想向用户显示实现该接口的类路径上的类列表。诀窍是,它必须在Android中运行。

我可以说,在运行时无法做到这一点。 java机制(ServiceLoader)已被Android工具链故意削弱,因此它不起作用。 Guava不适用于Android,ClassUtils也不适用Reflections

此时我已经牦牛剃了8小时海峡并且看不到尽头,所以我正在寻找替代方法。我目前的想法是构建一个插件(非常像sbt-spi,但不是,因为Android讨厌SPI),它可以在编译时生成一个文本文件,列出实现该接口的每个类,以便在运行时我可以打开该文件作为资源,然后使用反射开始构建它们。这是一个合理的想法吗?我该怎么办呢? (我目前的方法是“阅读sbt-spi插件来源并尝试复制它”,但这似乎是“要求智慧”是一种更好的方法)

1 个答案:

答案 0 :(得分:0)

知道了!毕竟我最终使用了sbt-spi(huzzah没有重新发明任何轮子!)并且只是将输出作为resourceGenerators任务的一部分移动到中间资源目录中:

lazy val androidEntryPoint = (project in file("android-entry-point"))
  .dependsOn(core, components, androidComponents)
  .enablePlugins(SpiPlugin)
  .settings(commonSettings: _*)
  .settings(resourceGenerators in Compile += Def.task{
    // This task copies the list of Components to the appropriate place to ensure
    // it gets included in an accessible place in the APK
    val res = collectResources.value._1  // item _1 here is for assets, item _2 is for resources.  See the output of sbt "show androidEntryPoint/android:collectResources"
    mapExport.value.toSeq.map { name =>
      IO.move(target.value / name, res / name)
      res / name
    }
  }.taskValue
)

那就是说,如果你能想到一个,我会喜欢听到更好的方法。如果在接下来的一周左右没有出现,我会将这个标记为答案。